Files
cmbuyer/admin/internal/taskclaim/token.go
T

53 lines
1.4 KiB
Go
Raw Normal View History

2026-08-04 22:33:16 +08:00
package taskclaim
import (
"crypto/hmac"
"crypto/sha256"
"crypto/subtle"
"encoding/binary"
"encoding/hex"
"hash"
)
const tokenDomain = "cmbuyer/task-claim-token/v1\x00"
func deriveToken(secret []byte, deviceID, taskID, authorizationID, attemptID string, generation int, nonce []byte) []byte {
mac := hmac.New(sha256.New, secret)
_, _ = mac.Write([]byte(tokenDomain))
writeTokenField(mac, deviceID)
writeTokenField(mac, taskID)
writeTokenField(mac, authorizationID)
writeTokenField(mac, attemptID)
var number [8]byte
binary.BigEndian.PutUint64(number[:], uint64(generation))
_, _ = mac.Write(number[:])
writeTokenBytes(mac, nonce)
return mac.Sum(nil)
}
func writeTokenField(writer hash.Hash, value string) { writeTokenBytes(writer, []byte(value)) }
func writeTokenBytes(writer hash.Hash, value []byte) {
var size [4]byte
binary.BigEndian.PutUint32(size[:], uint32(len(value)))
_, _ = writer.Write(size[:])
_, _ = writer.Write(value)
}
func tokenHash(token []byte) []byte {
sum := sha256.Sum256(token)
return sum[:]
}
func matchingHash(left, right []byte) bool {
return len(left) == sha256.Size && len(right) == sha256.Size && subtle.ConstantTimeCompare(left, right) == 1
}
func decodeToken(value string) ([]byte, bool) {
if len(value) != sha256.Size*2 {
return nil, false
}
decoded, err := hex.DecodeString(value)
return decoded, err == nil && hex.EncodeToString(decoded) == value
}