const ( AlgorithmKey = "alg" ContentTypeKey = "cty" CriticalKey = "crit" JWKKey = "jwk" JWKSetURLKey = "jku" KeyIDKey = "kid" TypeKey = "typ" X509CertChainKey = "x5c" X509CertThumbprintKey = "x5t" X509CertThumbprintS256Key = "x5t#S256" X509URLKey = "x5u" )
func AlgorithmsForKey(key interface{}) ([]jwa.SignatureAlgorithm, error)
AlgorithmsForKey returns the possible signature algorithms that can be used for a given key. It only takes in consideration keys/algorithms for verification purposes, as this is the only usage where one may need dynamically figure out which method to use.
func RegisterCustomField(name string, object interface{})
RegisterCustomField allows users to specify that a private field be decoded as an instance of the specified type. This option has a global effect.
For example, suppose you have a custom field `x-birthday`, which you want to represent as a string formatted in RFC3339 in JSON, but want it back as `time.Time`.
In that case you would register a custom field as follows
jwe.RegisterCustomField(`x-birthday`, timeT)
Then `hdr.Get("x-birthday")` will still return an `interface{}`, but you can convert its type to `time.Time`
bdayif, _ := hdr.Get(`x-birthday`) bday := bdayif.(time.Time)
func RegisterSigner(alg jwa.SignatureAlgorithm, f SignerFactory)
RegisterSigner is used to register a factory object that creates Signer objects based on the given algorithm.
For example, if you would like to provide a custom signer for jwa.EdDSA, use this function to register a `SignerFactory` (probably in your `init()`)
func RegisterVerifier(alg jwa.SignatureAlgorithm, f VerifierFactory)
RegisterVerifier is used to register a factory object that creates Verifier objects based on the given algorithm.
For example, if you would like to provide a custom verifier for jwa.EdDSA, use this function to register a `VerifierFactory` (probably in your `init()`)
func Sign(payload []byte, alg jwa.SignatureAlgorithm, key interface{}, options ...SignOption) ([]byte, error)
Sign generates a signature for the given payload, and serializes it in compact serialization format. In this format you may NOT use multiple signers.
The `alg` parameter is the identifier for the signature algorithm that should be used.
For the `key` parameter, any of the following is accepted: * A "raw" key (e.g. rsa.PrivateKey, ecdsa.PrivateKey, etc) * A crypto.Signer * A jwk.Key
A `crypto.Signer` is used when the private part of a key is kept in an inaccessible location, such as hardware. `crypto.Signer` is currently supported for RSA, ECDSA, and EdDSA family of algorithms.
If the key is a jwk.Key and the key contains a key ID (`kid` field), then it is added to the protected header generated by the signature
The algorithm specified in the `alg` parameter must be able to support the type of key you provided, otherwise an error is returned.
If you would like to pass custom headers, use the WithHeaders option.
If the headers contain "b64" field, then the boolean value for the field is respected when creating the compact serialization form. That is, if you specify a header with `{"b64": false}`, then the payload is not base64 encoded.
If you want to use a detached payload, use `jws.WithDetachedPayload()` as one of the options. When you use this option, you must always set the first parameter (`payload`) to `nil`, or the function will return an error
func SignMulti(payload []byte, options ...Option) ([]byte, error)
SignMulti accepts multiple signers via the options parameter, and creates a JWS in JSON serialization format that contains signatures from applying aforementioned signers.
Use `jws.WithSigner(...)` to specify values how to generate each signature in the `"signatures": [ ... ]` field.
func SplitCompact(src []byte) ([]byte, []byte, []byte, error)
SplitCompact splits a JWT and returns its three parts separately: protected headers, payload and signature.
func SplitCompactReader(rdr io.Reader) ([]byte, []byte, []byte, error)
SplitCompactReader splits a JWT and returns its three parts separately: protected headers, payload and signature.
func SplitCompactString(src string) ([]byte, []byte, []byte, error)
SplitCompactString splits a JWT and returns its three parts separately: protected headers, payload and signature.
func Verify(buf []byte, alg jwa.SignatureAlgorithm, key interface{}, options ...VerifyOption) ([]byte, error)
Verify checks if the given JWS message is verifiable using `alg` and `key`. `key` may be a "raw" key (e.g. rsa.PublicKey) or a jwk.Key
If the verification is successful, `err` is nil, and the content of the payload that was signed is returned. If you need more fine-grained control of the verification process, manually generate a `Verifier` in `verify` subpackage, and call `Verify` method on it. If you need to access signatures and JOSE headers in a JWS message, use `Parse` function to get `Message` object.
func VerifyAuto(buf []byte, options ...VerifyOption) ([]byte, error)
VerifyAuto is a special case of Verify(), where verification is done using verifications parameters that can be obtained using the information that is carried within the JWS message itself.
Currently it only supports verification via `jku` which will be fetched using the object specified in `jws.JWKSetFetcher`. Note that URLs in `jku` can only have https scheme.
Using this function will result in your program accessing remote resources via https, and therefore extreme caution should be taken which urls can be accessed.
Without specifying extra arguments, the default `jws.JWKSetFetcher` will be configured with a whitelist that rejects *ALL URLSs*. This is to protect users from unintentionally allowing their projects to make unwanted requests. Therefore you must explicitly provide an instance of `jwk.Whitelist` that does what you want.
If you want open access to any URLs in the `jku`, you can do this by using `jwk.InsecureWhitelist` as the whitelist, but this should be avoided in most cases, especially if the payload comes from outside of a controlled environment.
It is also advised that you consider using some sort of backoff via `jws.WithFetchBackoff`
Alternatively, you can provide your own `jws.JWKSetFetcher`. In this case there is no way for the framework to force you to set a whitelist, so the default behavior is to allow any URLs. You are responsible for providing your own safety measures.
func VerifySet(buf []byte, set jwk.Set) ([]byte, error)
VerifySet uses keys store in a jwk.Set to verify the payload in `buf`.
In order for `VerifySet()` to use a key in the given set, the `jwk.Key` object must have a valid "alg" field, and it also must have either an empty value or the value "sig" in the "use" field.
Furthermore if the JWS signature asks for a spefici "kid", the `jwk.Key` must have the same "kid" as the signature.
type DecodeCtx interface { CollectRaw() bool }
HMACSigner uses crypto/hmac to sign the payloads.
type HMACSigner struct {
// contains filtered or unexported fields
}
func (s HMACSigner) Algorithm() jwa.SignatureAlgorithm
func (s HMACSigner) Sign(payload []byte, key interface{}) ([]byte, error)
type HMACVerifier struct {
// contains filtered or unexported fields
}
func (v HMACVerifier) Verify(payload, signature []byte, key interface{}) (err error)
type HeaderPair = mapiter.Pair
Headers describe a standard Header set.
type Headers interface { json.Marshaler json.Unmarshaler Algorithm() jwa.SignatureAlgorithm ContentType() string Critical() []string JWK() jwk.Key JWKSetURL() string KeyID() string Type() string X509CertChain() []string X509CertThumbprint() string X509CertThumbprintS256() string X509URL() string Iterate(ctx context.Context) Iterator Walk(context.Context, Visitor) error AsMap(context.Context) (map[string]interface{}, error) Copy(context.Context, Headers) error Merge(context.Context, Headers) (Headers, error) Get(string) (interface{}, bool) Set(string, interface{}) error Remove(string) error // PrivateParams returns the non-standard elements in the source structure // WARNING: DO NOT USE PrivateParams() IF YOU HAVE CONCURRENT CODE ACCESSING THEM. // Use AsMap() to get a copy of the entire header instead PrivateParams() map[string]interface{} }
func NewHeaders() Headers
type Iterator = mapiter.Iterator
type JWKSetFetchFunc func(string) (jwk.Set, error)
func (f JWKSetFetchFunc) Fetch(u string) (jwk.Set, error)
JWKSetFetcher is used to fetch JWK Set spcified in the `jku` field.
type JWKSetFetcher interface { Fetch(string) (jwk.Set, error) }
Message represents a full JWS encoded message. Flattened serialization is not supported as a struct, but rather it's represented as a Message struct with only one `signature` element.
Do not expect to use the Message object to verify or construct a signed payload with. You should only use this when you want to actually programmatically view the contents of the full JWS payload.
As of this version, there is one big incompatibility when using Message objects to convert between compact and JSON representations. The protected header is sometimes encoded differently from the original message and the JSON serialization that we use in Go.
For example, the protected header `eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9` decodes to
{"typ":"JWT", "alg":"HS256"}
However, when we parse this into a message, we create a jws.Header object, which, when we marshal into a JSON object again, becomes
{"typ":"JWT","alg":"HS256"}
Notice that serialization lacks a line break and a space between `"JWT",` and `"alg"`. This causes a problem when verifying the signatures AFTER a compact JWS message has been unmarshaled into a jws.Message.
jws.Verify() doesn't go through this step, and therefore this does not manifest itself. However, you may see this discrepancy when you manually go through these conversions, and/or use the `jwx` tool like so:
jwx jws parse message.jws | jwx jws verify --key somekey.jwk --stdin
In this scenario, the first `jwx jws parse` outputs a parsed jws.Message which is marshaled into JSON. At this point the message's protected headers and the signatures don't match.
To sign and verify, use the appropriate `Sign()` and `Verify()` functions.
type Message struct {
// contains filtered or unexported fields
}
func NewMessage() *Message
func Parse(src []byte) (*Message, error)
Parse parses contents from the given source and creates a jws.Message struct. The input can be in either compact or full JSON serialization.
func ParseReader(src io.Reader) (*Message, error)
Parse parses contents from the given source and creates a jws.Message struct. The input can be in either compact or full JSON serialization.
func ParseString(src string) (*Message, error)
Parse parses contents from the given source and creates a jws.Message struct. The input can be in either compact or full JSON serialization.
func ReadFile(path string, _ ...ReadFileOption) (*Message, error)
func (m *Message) AppendSignature(v *Signature) *Message
func (m *Message) ClearSignatures() *Message
func (m *Message) DecodeCtx() DecodeCtx
func (m Message) LookupSignature(kid string) []*Signature
LookupSignature looks up a particular signature entry using the `kid` value
func (m Message) MarshalJSON() ([]byte, error)
func (m Message) Payload() []byte
Payload returns the decoded payload
func (m *Message) SetDecodeCtx(dc DecodeCtx)
func (m *Message) SetPayload(v []byte) *Message
func (m Message) Signatures() []*Signature
func (m *Message) UnmarshalJSON(buf []byte) error
type Option = option.Interface
func WithSigner(signer Signer, key interface{}, public, protected Headers) Option
ReadFileOption describes options that can be passed to ReadFile. Currently there are no options available that can be passed to ReadFile, but it is provided here for anticipated future additions
type ReadFileOption interface { Option // contains filtered or unexported methods }
type SignOption interface { Option // contains filtered or unexported methods }
func WithHeaders(h Headers) SignOption
WithHeaders allows you to specify extra header values to include in the final JWS message
type SignVerifyOption interface { SignOption VerifyOption }
func WithDetachedPayload(v []byte) SignVerifyOption
WithDetachedPayload can be used to both sign or verify a JWS message with a detached payload.
When this option is used for `jws.Sign()`, the first parameter (normally the payload) must be set to `nil`.
If you have to verify using this option, you should know exactly how and why this works.
type Signature struct {
// contains filtered or unexported fields
}
func NewSignature() *Signature
func (s *Signature) DecodeCtx() DecodeCtx
func (s Signature) ProtectedHeaders() Headers
func (s Signature) PublicHeaders() Headers
func (s *Signature) SetDecodeCtx(dc DecodeCtx)
func (s *Signature) SetProtectedHeaders(v Headers) *Signature
func (s *Signature) SetPublicHeaders(v Headers) *Signature
func (s *Signature) SetSignature(v []byte) *Signature
func (s *Signature) Sign(payload []byte, signer Signer, key interface{}) ([]byte, []byte, error)
Sign populates the signature field, with a signature generated by given the signer object and payload.
The first return value is the raw signature in binary format. The second return value s the full three-segment signature (e.g. "eyXXXX.XXXXX.XXXX")
func (s Signature) Signature() []byte
func (s *Signature) UnmarshalJSON(data []byte) error
Signer generates the signature for a given payload.
type Signer interface { // Sign creates a signature for the given payload. // The scond argument is the key used for signing the payload, and is usually // the private key type associated with the signature method. For example, // for `jwa.RSXXX` and `jwa.PSXXX` types, you need to pass the // `*"crypto/rsa".PrivateKey` type. // Check the documentation for each signer for details Sign([]byte, interface{}) ([]byte, error) Algorithm() jwa.SignatureAlgorithm }
func NewSigner(alg jwa.SignatureAlgorithm) (Signer, error)
NewSigner creates a signer that signs payloads using the given signature algorithm.
type SignerFactory interface { Create() (Signer, error) }
type SignerFactoryFn func() (Signer, error)
func (fn SignerFactoryFn) Create() (Signer, error)
SimpleJWKSetFetcher is the default object used to fetch JWK Sets specified in `jku`, which uses `jwk.Fetch()`
For more complicated cases, such as using `jwk.AutoRefetch`, you will have to create your custom instance of `jws.JWKSetFetcher`
type SimpleJWKSetFetcher struct {
// contains filtered or unexported fields
}
func NewJWKSetFetcher(options ...jwk.FetchOption) *SimpleJWKSetFetcher
func (f *SimpleJWKSetFetcher) Fetch(u string) (jwk.Set, error)
type Verifier interface { // Verify checks whether the payload and signature are valid for // the given key. // `key` is the key used for verifying the payload, and is usually // the public key associated with the signature method. For example, // for `jwa.RSXXX` and `jwa.PSXXX` types, you need to pass the // `*"crypto/rsa".PublicKey` type. // Check the documentation for each verifier for details Verify(payload []byte, signature []byte, key interface{}) error }
func NewVerifier(alg jwa.SignatureAlgorithm) (Verifier, error)
NewVerifier creates a verifier that signs payloads using the given signature algorithm.
type VerifierFactory interface { Create() (Verifier, error) }
type VerifierFactoryFn func() (Verifier, error)
func (fn VerifierFactoryFn) Create() (Verifier, error)
VerifyOption describes an option that can be passed to the jws.Verify function
type VerifyOption interface { Option // contains filtered or unexported methods }
func WithFetchBackoff(b backoff.Policy) VerifyOption
WithFetchBackoff specifies the backoff.Policy object to be passed to `jwk.Fetch()` when `jws.VerifyAuto()` is used.
This option is ignored if WithJWKSetFetcher is specified.
func WithFetchWhitelist(wl jwk.Whitelist) VerifyOption
WithFetchWhitelist specifies the whitelist object to be passed to `jwk.Fetch()` when `jws.VerifyAuto()` is used. If you do not specify a whitelist, `jws.VerifyAuto()` will ALWAYS fail.
This option is ignored if WithJWKSetFetcher is specified.
func WithHTTPClient(httpcl *http.Client) VerifyOption
WithHTTPClient specifies the *http.Client object to be passed to `jwk.Fetch()` when `jws.VerifyAuto()` is used.
This option is ignored if WithJWKSetFetcher is specified.
func WithJWKSetFetcher(f JWKSetFetcher) VerifyOption
WithJWKSetFetcher specifies the JWKSetFetcher object to be used when `jws.VerifyAuto()`, for example, to use `jwk.AutoRefetch` instead of the default `jwk.Fetch()`
func WithMessage(m *Message) VerifyOption
WithMessage can be passed to Verify() to obtain the jws.Message upon a successful verification.
type Visitor = iter.MapVisitor
type VisitorFunc = iter.MapVisitorFunc