Documentation
¶
Index ¶
- Variables
- func RegisterAlgo(obj Algo)
- func RegisterEncAlgo(obj EncAlgo)
- func RegisterKeyAlgo(obj KeyAlgo)
- type Algo
- type EncAlgo
- type EncryptOptions
- type Header
- type HeaderKeyAlgo
- type JWK
- func (jwk *JWK) ApplyValues(values map[string]any) error
- func (jwk *JWK) Decrypt(rand io.Reader, msg []byte, opts crypto.DecrypterOpts) ([]byte, error)
- func (jwk *JWK) ExportRequiredPublicValues() map[string]any
- func (jwk *JWK) ExportRequiredValues() map[string]any
- func (jwk *JWK) ExportValues() map[string]any
- func (jwk *JWK) MarshalJSON() ([]byte, error)
- func (jwk *JWK) Public() crypto.PublicKey
- func (jwk *JWK) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error)
- func (jwk *JWK) String() string
- func (jwk *JWK) Thumbprint(method crypto.Hash) ([]byte, error)
- func (jwk *JWK) ThumbprintHex(method crypto.Hash) string
- func (jwk *JWK) UnmarshalJSON(v []byte) error
- type KeyAlgo
- type Payload
- func (b Payload) Get(key string) any
- func (b Payload) GetFloat(key string) float64
- func (b Payload) GetInt(key string) int64
- func (b Payload) GetNumericDate(key string) time.Time
- func (b Payload) GetString(key string) string
- func (b Payload) Has(key string) bool
- func (b Payload) Set(key string, value any) error
- type Token
- func (tok *Token) Decrypt(privKey any) error
- func (tok *Token) Encrypt(rand io.Reader, rcptKey any, opts *EncryptOptions) (string, error)
- func (tok *Token) GetAlgo() Algo
- func (tok *Token) GetAlgoErr() (Algo, error)
- func (tok *Token) GetContentType() string
- func (tok *Token) GetKeyId() string
- func (tok *Token) GetRawPayload() ([]byte, error)
- func (tok *Token) GetRawSignature() ([]byte, error)
- func (tok Token) GetSignString() []byte
- func (tok *Token) Header() Header
- func (tok *Token) IsEncrypted() bool
- func (tok *Token) Payload() Payload
- func (tok *Token) SetRawPayload(payload []byte, cty string) error
- func (tok *Token) Sign(rand io.Reader, priv crypto.PrivateKey) (string, error)
- func (tok *Token) Verify(opts ...VerifyOption) error
- type VerifyOption
- func VerifyAlgo(algo ...Algo) VerifyOption
- func VerifyExpiresAt(now time.Time, req bool) VerifyOption
- func VerifyMultiple(opts ...VerifyOption) VerifyOption
- func VerifyNotBefore(now time.Time, req bool) VerifyOption
- func VerifySignature(pub crypto.PublicKey) VerifyOption
- func VerifyTime(now time.Time, req bool) VerifyOption
Constants ¶
This section is empty.
Variables ¶
var ( ErrInvalidToken = errors.New("jwt: invalid token provided") ErrNoSignature = errors.New("jwt: token has no signature") ErrInvalidSignature = errors.New("jwt: token signature is not valid") ErrInvalidSignKey = errors.New("jwt: invalid key provided for signature") ErrInvalidSignatureLength = errors.New("jwt: token signature is not valid (bad length)") ErrHashNotAvailable = errors.New("jwt: hash method not available") ErrNoHeader = errors.New("jwt: header is not available (parsing failed?)") ErrNoPayload = errors.New("jwt: payload is not available (parsing failed?)") ErrInvalidPublicKey = errors.New("jwt: invalid public key provided") ErrNoPrivateKey = errors.New("jwt: private key is missing") ErrAlgNotSet = errors.New("jwt: alg has not been set in header") ErrUnknownAlg = errors.New("jwt: unrecognized alg value") ErrVerifyMissing = errors.New("jwt: a claim required for verification is missing") ErrVerifyFailed = errors.New("jwt: claim verification has failed") ErrNotEncrypted = errors.New("jwt: token is not encrypted") ErrUnknownEnc = errors.New("jwt: unrecognized enc value") ErrDecryptionFailed = errors.New("jwt: decryption failed") )
var ( // Key management algorithms (RFC 7518 Section 4) RSA_OAEP KeyAlgo = rsaOaepKeyAlgo{hash: crypto.SHA1, name: "RSA-OAEP"}.reg() RSA_OAEP_256 KeyAlgo = rsaOaepKeyAlgo{hash: crypto.SHA256, name: "RSA-OAEP-256"}.reg() Dir KeyAlgo = dirKeyAlgo{}.reg() A128KW KeyAlgo = aesKwAlgo{keySize: 16}.reg() A192KW KeyAlgo = aesKwAlgo{keySize: 24}.reg() A256KW KeyAlgo = aesKwAlgo{keySize: 32}.reg() // Content encryption algorithms (RFC 7518 Section 5) A128GCM EncAlgo = aesGcmEncAlgo{keySize: 16}.reg() A192GCM EncAlgo = aesGcmEncAlgo{keySize: 24}.reg() A256GCM EncAlgo = aesGcmEncAlgo{keySize: 32}.reg() A128CBC_HS256 EncAlgo = aesCbcHsEncAlgo{keySize: 32, hash: crypto.SHA256}.reg() A192CBC_HS384 EncAlgo = aesCbcHsEncAlgo{keySize: 48, hash: crypto.SHA384}.reg() A256CBC_HS512 EncAlgo = aesCbcHsEncAlgo{keySize: 64, hash: crypto.SHA512}.reg() )
var (
DeprecatedAllowEcdsaASN1Signatures = true // this will turn to false eventually
)
DeprecatedAllowEcdsaASN1Signatures controls whether ECDSA signature verification accepts ASN.1 DER-encoded signatures in addition to the fixed-length R||S format required by RFC 7518. This exists for backward compatibility and will eventually default to false.
Functions ¶
func RegisterAlgo ¶
func RegisterAlgo(obj Algo)
RegisterAlgo allows registration of custom algorithms. We assume this will be called during init in a single thread, so no locking is performed.
func RegisterEncAlgo ¶ added in v0.2.0
func RegisterEncAlgo(obj EncAlgo)
RegisterEncAlgo registers a JWE content encryption algorithm. This is typically called during init and no locking is performed.
func RegisterKeyAlgo ¶ added in v0.2.0
func RegisterKeyAlgo(obj KeyAlgo)
RegisterKeyAlgo registers a JWE key management algorithm. This is typically called during init and no locking is performed.
Types ¶
type Algo ¶
type Algo interface {
// String should return the name of the algo, for example "HS256"
String() string
// Sign should sign the provided buffer, and return the resulting
// signature. If the private key isn't of the appropriate type, an
// error should be triggered.
Sign(rand io.Reader, buf []byte, priv crypto.PrivateKey) ([]byte, error)
// Verify must verify the provided signature and return an error
// if the public key is not of the appropriate type or the signature
// is not valid.
Verify(buf, sign []byte, pub crypto.PublicKey) error
}
Algo is a jwt signature algorithm. Typical values include HS256 and ES256. By implementing this interface, you can also add support for your own custom types. Remember to call RegisterAlgo() so your new algo can be recognized appropriately.
var ( HS256 Algo = hmacAlgo(crypto.SHA256).reg() HS384 Algo = hmacAlgo(crypto.SHA384).reg() HS512 Algo = hmacAlgo(crypto.SHA512).reg() RS256 Algo = rsaAlgo(crypto.SHA256).reg() RS384 Algo = rsaAlgo(crypto.SHA384).reg() RS512 Algo = rsaAlgo(crypto.SHA512).reg() PS256 Algo = rsaPssAlgo(crypto.SHA256).reg() PS384 Algo = rsaPssAlgo(crypto.SHA384).reg() PS512 Algo = rsaPssAlgo(crypto.SHA512).reg() ES224 Algo = ecdsaAlgo("ES224").reg() ES256 Algo = ecdsaAlgo("ES256").reg() ES384 Algo = ecdsaAlgo("ES384").reg() ES512 Algo = ecdsaAlgo("ES512").reg() ES256K Algo = ecdsaAlgo("ES256K").reg() EdDSA Algo = ed25519Algo{}.reg() None Algo = noneAlgo{}.reg() )
note: the .reg() just performs a call to RegisterAlgo() and returns the object itself.
var ( // SLH-DSA SHA2 variants SLH_DSA_SHA2_128s Algo = slhdsaAlgo{params: slhdsa.SHA2_128s}.reg() SLH_DSA_SHA2_128f Algo = slhdsaAlgo{params: slhdsa.SHA2_128f}.reg() SLH_DSA_SHA2_192s Algo = slhdsaAlgo{params: slhdsa.SHA2_192s}.reg() SLH_DSA_SHA2_192f Algo = slhdsaAlgo{params: slhdsa.SHA2_192f}.reg() SLH_DSA_SHA2_256s Algo = slhdsaAlgo{params: slhdsa.SHA2_256s}.reg() SLH_DSA_SHA2_256f Algo = slhdsaAlgo{params: slhdsa.SHA2_256f}.reg() // SLH-DSA SHAKE variants SLH_DSA_SHAKE_128s Algo = slhdsaAlgo{params: slhdsa.SHAKE_128s}.reg() SLH_DSA_SHAKE_128f Algo = slhdsaAlgo{params: slhdsa.SHAKE_128f}.reg() SLH_DSA_SHAKE_192s Algo = slhdsaAlgo{params: slhdsa.SHAKE_192s}.reg() SLH_DSA_SHAKE_192f Algo = slhdsaAlgo{params: slhdsa.SHAKE_192f}.reg() SLH_DSA_SHAKE_256s Algo = slhdsaAlgo{params: slhdsa.SHAKE_256s}.reg() SLH_DSA_SHAKE_256f Algo = slhdsaAlgo{params: slhdsa.SHAKE_256f}.reg() )
func GetAlgoForSigner ¶ added in v0.1.7
func GetAlgoForSigner(s crypto.PrivateKey) (Algo, error)
GetAlgoForSigner will guess the correct algorithm for a given crypto.PrivateKey
type EncAlgo ¶ added in v0.2.0
type EncAlgo interface {
String() string
// KeySize returns the required key size in bytes.
KeySize() int
// Encrypt performs authenticated encryption. Returns the IV, ciphertext,
// and authentication tag. The aad parameter is the Additional
// Authenticated Data (the base64url-encoded protected header).
Encrypt(rand io.Reader, key, plaintext, aad []byte) (iv, ciphertext, tag []byte, err error)
// Decrypt performs authenticated decryption, verifying the tag.
Decrypt(key, iv, ciphertext, tag, aad []byte) ([]byte, error)
}
EncAlgo represents a JWE content encryption algorithm as defined in RFC 7518 Section 5. It provides authenticated encryption of the plaintext.
type EncryptOptions ¶ added in v0.2.1
type EncryptOptions struct {
// KeyAlgo specifies the key management algorithm. If nil, it is
// auto-detected from the recipient key type (e.g. *rsa.PublicKey →
// RSA-OAEP-256, *ecdh.PublicKey → ECDH-ES, []byte → dir).
KeyAlgo KeyAlgo
// EncAlgo specifies the content encryption algorithm. If nil, defaults
// to A256GCM.
EncAlgo EncAlgo
}
EncryptOptions configures the JWE encryption. All fields are optional; nil values are auto-detected from the recipient key type.
type Header ¶
Header type holds values from the token's header for easy access. Values are typically strings, but may be other types (e.g. the "epk" parameter in ECDH-ES is a JSON object).
func (Header) Get ¶
Get will return the value of the requested key from the header, or an empty string if the value is not found or is not a string.
func (Header) GetAlgo ¶
GetAlgo will return a Algo based on the alg value of the header, or nil if the algo is invalid or unknown. This will also work with custom algo as long as RegisterAlgo() was called.
func (Header) Has ¶
Has returns true if the key exists in the header (and there is a header), and can be used to test for a given key even if its value is empty.
type HeaderKeyAlgo ¶ added in v0.2.0
type HeaderKeyAlgo interface {
KeyAlgo
// GenerateCEKWithHeader generates a CEK and may return additional header
// parameters to include in the JWE protected header (e.g. "epk").
// The header parameter contains user-set headers (e.g. "apu", "apv").
// The encAlg parameter is the "enc" algorithm name for key derivation.
GenerateCEKWithHeader(rand io.Reader, keySize int, rcptKey any, header Header, encAlg string) (cek, encryptedKey []byte, extraHeaders map[string]any, err error)
// UnwrapKeyFromHeader recovers the CEK using header information. The
// header parameter contains the full protected header including
// algorithm-specific parameters (e.g. "epk", "apu", "apv").
UnwrapKeyFromHeader(encryptedKey []byte, keySize int, privKey any, header Header, encAlg string) ([]byte, error)
}
HeaderKeyAlgo is an optional extension of KeyAlgo for algorithms that need access to JWE header parameters during key management. ECDH-ES algorithms use this to include the ephemeral public key (epk) in the protected header and to read it back during decryption.
type JWK ¶ added in v0.1.1
type JWK struct {
PrivateKey crypto.PrivateKey `json:"-"`
PublicKey crypto.PublicKey `json:"-"`
KeyID string `json:"kid,omitempty"`
Algo string `json:"alg,omitempty"` // RSA-OAEP-256
Use string `json:"use,omitempty"`
Ext bool `json:"ext,omitempty"`
KeyOps []string `json:"key_ops,omitempty"`
}
JWK represents a JSON Web Key as defined in RFC 7517. It can hold either a public key, a private key, or both. JWK implements crypto.Signer when a private key is present, making it usable directly with Sign methods.
func (*JWK) ApplyValues ¶ added in v0.1.1
ApplyValues populates the JWK from a map of key-value pairs, typically obtained from JSON unmarshaling. The "kty" field is required and determines how the remaining fields are interpreted.
func (*JWK) Decrypt ¶ added in v0.2.0
Decrypt decrypts msg using the JWK's private key. Returns ErrNoPrivateKey if no private key is available. This method satisfies the crypto.Decrypter interface.
func (*JWK) ExportRequiredPublicValues ¶ added in v0.1.1
ExportRequiredPublicValues returns only the required public key fields, suitable for computing JWK Thumbprints per RFC 7638.
func (*JWK) ExportRequiredValues ¶ added in v0.1.1
ExportRequiredValues returns only the required JWK fields (kty and key material). If a private key is present, private key fields are included.
func (*JWK) ExportValues ¶ added in v0.1.1
ExportValues returns all JWK fields as a map, including optional metadata fields (kid, alg, use, ext, key_ops) and key material.
func (*JWK) MarshalJSON ¶ added in v0.1.1
MarshalJSON implements json.Marshaler. It exports the JWK including private key material if present.
func (*JWK) Public ¶ added in v0.1.1
Public returns the public key associated with this JWK. If a private key is present, the public key is derived from it. This method satisfies the crypto.Signer interface.
func (*JWK) Sign ¶ added in v0.1.6
Sign signs the digest using the JWK's private key. Returns ErrNoPrivateKey if no private key is available. This method satisfies the crypto.Signer interface.
func (*JWK) String ¶ added in v0.1.1
String returns a human-readable representation of the JWK showing the key type.
func (*JWK) Thumbprint ¶ added in v0.1.1
Thumbprint computes the JWK Thumbprint as defined in RFC 7638 using the specified hash method.
func (*JWK) ThumbprintHex ¶ added in v0.1.1
ThumbprintHex computes the JWK Thumbprint (RFC 7638) and returns it as a hex-encoded string. Returns an empty string on error.
func (*JWK) UnmarshalJSON ¶ added in v0.1.1
UnmarshalJSON implements json.Unmarshaler. It parses a JWK JSON object and populates the key fields accordingly.
type KeyAlgo ¶ added in v0.2.0
type KeyAlgo interface {
String() string
// GenerateCEK generates a Content Encryption Key and wraps it for the
// recipient. Returns the CEK and the encrypted key. For "dir", the
// encrypted key will be nil and the provided key is used directly as CEK.
GenerateCEK(rand io.Reader, keySize int, rcptKey any) (cek, encryptedKey []byte, err error)
// UnwrapKey recovers the CEK from the encrypted key using the recipient's
// private key or shared secret.
UnwrapKey(encryptedKey []byte, keySize int, privKey any) ([]byte, error)
}
KeyAlgo represents a JWE key management algorithm as defined in RFC 7518 Section 4. It handles wrapping and unwrapping of the Content Encryption Key.
var ( // ECDH-ES key agreement algorithms (RFC 7518 Section 4.6) ECDH_ES KeyAlgo = ecdhEsAlgo{name: "ECDH-ES"}.reg() ECDH_ES_A128KW KeyAlgo = ecdhEsAlgo{name: "ECDH-ES+A128KW", wrapKeySize: 16}.reg() ECDH_ES_A192KW KeyAlgo = ecdhEsAlgo{name: "ECDH-ES+A192KW", wrapKeySize: 24}.reg() ECDH_ES_A256KW KeyAlgo = ecdhEsAlgo{name: "ECDH-ES+A256KW", wrapKeySize: 32}.reg() )
func GetKeyAlgoForKey ¶ added in v0.2.1
GetKeyAlgoForKey returns the default JWE key management algorithm for the given key. This is used by Encrypt when no KeyAlgo is specified.
type Payload ¶
Payload represents the claims part of a JWT token as a map of key-value pairs. Standard claims such as "iss", "sub", "exp", "nbf", "iat", "jti" can be accessed via Get/Set, and convenience methods are provided for type conversion.
func (Payload) Get ¶
Get is a safe get that will return nil if the body itself is null or the value is nil. If you want to check if a value exists or not, use Has().
func (Payload) GetFloat ¶
GetFloat will attempt to parse the requested key as a float and return it. If the value is an int or any other kind of number-y value, it will be converted to float64 and returned, or return 0 in case of failure.
func (Payload) GetInt ¶
GetInt will attempt to parse the requested key as an integer and return it. If the value is a float or any other kind of number-y value, it will be converted (truncated) and returned as an int, or 0 in case of failure.
func (Payload) GetNumericDate ¶
GetNumericDate will return a time value based on the requested header, or a zero time if the parsing failed or the key is not set. Check IsZero() for success.
func (Payload) GetString ¶
GetString will get a value as a string, convert it to a string if possible or return an empty string if the value is not set or cannot be converted. GetString will return an empty string in case of failure.
type Token ¶
type Token struct {
// contains filtered or unexported fields
}
Token represents a JWT token
func New ¶
New will return a fresh and empty token that can be filled with information to be later signed using the Sign method. By default only the "alg" value of the header will be set if alg was passed.
func ParseString ¶
ParseString will generate a Token object from an encoded string. No verification is performed at this point, so it is up to you to call the Verify method.
func (*Token) Decrypt ¶ added in v0.2.0
Decrypt decrypts a JWE token, making the payload accessible via Payload() and GetRawPayload(). The privKey is the recipient's private key (for RSA-OAEP, ECDH-ES) or shared secret (for dir, AES-KW).
func (*Token) Encrypt ¶ added in v0.2.0
Encrypt encrypts the token's payload and returns the JWE compact serialization string. The rcptKey is the recipient's public key (for RSA-OAEP, ECDH-ES), shared secret (for dir, AES-KW), or encapsulation key (for ML-KEM).
If opts is nil, the key management algorithm is auto-detected from the key type and A256GCM is used for content encryption. Individual fields in opts may also be left nil for auto-detection.
func (*Token) GetAlgo ¶
GetAlgo will determine the algorithm in use from the header and return the appropriate Algo object, or nil if unknown or no algo is specified.
func (*Token) GetAlgoErr ¶ added in v0.1.8
GetAlgoErr performs similarly to GetAlgo but also return an error that can be either ErrAlgNotSet or ErrUnknownAlg
func (*Token) GetContentType ¶ added in v0.0.3
GetContentType returns the value of "cty" claim in the token's header, ro "application/jwt" if not set. It will prepend "application/" to values that have no slashes in them as defined in RFC 7515, Section 4.1.10.
func (*Token) GetRawPayload ¶ added in v0.0.3
GetRawPayload returns the raw value for the token's payload, or an error if it could not be decoded.
func (*Token) GetRawSignature ¶ added in v0.0.3
GetRawSignature returns the raw signature of a parsed token or of a freshly signed token.
func (Token) GetSignString ¶ added in v0.0.3
GetSignString is used by VerifySignature to get the part of the string that is used to generate a signature. It avoids duplicating memory in order to provide better performance.
func (*Token) Header ¶
Header returns the decoded header part of the token and is useful to read the key id value for the signature.
func (*Token) IsEncrypted ¶ added in v0.2.0
IsEncrypted returns true if the token is a JWE (encrypted) token, identified by having 5 dot-separated parts.
func (*Token) Payload ¶
Payload returns the payload part of the token, which contains the claims. If parsing failed, then this function will return nil. Payload methods such as Get() and Set() can still be called without causing a panic.
func (*Token) SetRawPayload ¶ added in v0.0.3
SetRawPayload sets the raw value of payload to any kind of data that can be later signed. This can be used to store non-JSON data in the payload.
func (*Token) Verify ¶
func (tok *Token) Verify(opts ...VerifyOption) error
Verify will perform the verifications passed as parameter in sequence, stopping at the first failure. If all verifications are successful, nil will be returned.
type VerifyOption ¶
VerifyOption is a function that performs a single verification check on a token. Multiple options can be composed via Token.Verify or VerifyMultiple.
func VerifyAlgo ¶
func VerifyAlgo(algo ...Algo) VerifyOption
VerifyAlgo returns a VerifyOption that will ensure the token's alg value is one of the specified algos. This allows to easily limit the acceptable signature scheme and should always be used.
func VerifyExpiresAt ¶
func VerifyExpiresAt(now time.Time, req bool) VerifyOption
VerifyExpiresAt returns a VerifyOption that will check the token's expiration to not be before now.
Example use: VerifyExpiresAt(time.Now(), false)
func VerifyMultiple ¶
func VerifyMultiple(opts ...VerifyOption) VerifyOption
VerifyMultiple compounds multiple conditions and fails if any of the passed condition fails. This will return success if no options are passed at all.
func VerifyNotBefore ¶
func VerifyNotBefore(now time.Time, req bool) VerifyOption
VerifyNotBefore returns a VerifyOption that will check the token's not before claim (nbf).
Example use: VerifyNotBefore(time.Now(), false)
func VerifySignature ¶
func VerifySignature(pub crypto.PublicKey) VerifyOption
VerifySignature will check the token's signature against the specified public key based on the algo used for the token. This will always fail for tokens which alg is set to "none".
func VerifyTime ¶
func VerifyTime(now time.Time, req bool) VerifyOption
VerifyTime will verify both the not before and the expires at claims, and is typically used with req=false so those checks only happen if the claims are specified.
If you know both nbf and exp claims will always be there, setting req=true will ensure this and improve security.