in pkg/sdk/security/crypto/paseto/v4/helpers.go [61:144]
func Decrypt(key, input []byte, f, i string) ([]byte, error) {
// Check arguments
if key == nil {
return nil, errors.New("paseto: key is nil")
}
if len(key) != KeyLength {
return nil, fmt.Errorf("paseto: invalid key length, it must be %d bytes long", KeyLength)
}
if input == nil {
return nil, errors.New("paseto: input is nil")
}
// Check token header
if !bytes.HasPrefix(input, []byte(v4LocalPrefix)) {
return nil, errors.New("paseto: invalid token")
}
// Trim prefix
input = input[len(v4LocalPrefix):]
// Check footer usage
if f != "" {
// Split the footer and the body
parts := bytes.SplitN(input, []byte("."), 2)
if len(parts) != 2 {
return nil, errors.New("paseto: invalid token, footer is missing but expected")
}
// Decode footer
footer := make([]byte, base64.RawURLEncoding.DecodedLen(len(parts[1])))
if _, err := base64.RawURLEncoding.Decode(footer, parts[1]); err != nil {
return nil, fmt.Errorf("paseto: invalid token, footer has invalid encoding: %w", err)
}
// Compare footer
if !security.SecureCompare([]byte(f), footer) {
return nil, errors.New("paseto: invalid token, footer mismatch")
}
// Continue without footer
input = parts[0]
}
// Decode token
raw := make([]byte, base64.RawURLEncoding.DecodedLen(len(input)))
if _, err := base64.RawURLEncoding.Decode(raw, input); err != nil {
return nil, fmt.Errorf("paseto: invalid token body: %w", err)
}
// Extract components
n := raw[:nonceLength]
t := raw[len(raw)-macLength:]
c := raw[macLength : len(raw)-macLength]
// Derive keys from seed and secret key
ek, n2, ak, err := kdf(key, n)
if err != nil {
return nil, fmt.Errorf("paseto: unable to derive keys from seed: %w", err)
}
// Compute MAC
t2, err := mac(ak, v4LocalPrefix, n, c, f, i)
if err != nil {
return nil, fmt.Errorf("paseto: unable to compute MAC: %w", err)
}
// Time-constant compare MAC
if !security.SecureCompare(t, t2) {
return nil, errors.New("paseto: invalid pre-authentication header")
}
// Prepare XChaCha20 stream cipher
ciph, err := chacha20.NewUnauthenticatedCipher(ek, n2)
if err != nil {
return nil, fmt.Errorf("paseto: unable to initialize XChaCha20 cipher: %w", err)
}
// Encrypt the payload
m := make([]byte, len(c))
ciph.XORKeyStream(m, c)
// No error
return m, nil
}