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 }