Documentation ¶
Overview ¶
Package jws implements the digital signature on JSON based data structures as described in https://tools.ietf.org/html/rfc7515
If you do not care about the details, the only things that you would need to use are the following functions:
jws.Sign(payload, algorithm, key) jws.Verify(encodedjws, algorithm, key)
To sign, simply use `jws.Sign`. `payload` is a []byte buffer that contains whatever data you want to sign. `alg` is one of the jwa.SignatureAlgorithm constants from package jwa. For RSA and ECDSA family of algorithms, you will need to prepare a private key. For HMAC family, you just need a []byte value. The `jws.Sign` function will return the encoded JWS message on success.
To verify, use `jws.Verify`. It will parse the `encodedjws` buffer and verify the result using `algorithm` and `key`. Upon successful verification, the original payload is returned, so you can work on it.
Index ¶
- Constants
- func AlgorithmsForKey(key interface{}) ([]jwa.SignatureAlgorithm, error)
- func RegisterCustomField(name string, object interface{})
- func RegisterSigner(alg jwa.SignatureAlgorithm, f SignerFactory)
- func RegisterVerifier(alg jwa.SignatureAlgorithm, f VerifierFactory)
- func Sign(payload []byte, alg jwa.SignatureAlgorithm, key interface{}, ...) ([]byte, error)
- func SignMulti(payload []byte, options ...Option) ([]byte, error)
- func SplitCompact(src []byte) ([]byte, []byte, []byte, error)
- func SplitCompactReader(rdr io.Reader) ([]byte, []byte, []byte, error)
- func SplitCompactString(src string) ([]byte, []byte, []byte, error)
- func Verify(buf []byte, alg jwa.SignatureAlgorithm, key interface{}, ...) ([]byte, error)
- func VerifyAuto(buf []byte, options ...VerifyOption) ([]byte, error)
- func VerifySet(buf []byte, set jwk.Set) ([]byte, error)
- type DecodeCtx
- type HMACSigner
- type HMACVerifier
- type HeaderPair
- type Headers
- type Iterator
- type JWKSetFetchFunc
- type JWKSetFetcher
- type Message
- func (m *Message) AppendSignature(v *Signature) *Message
- func (m *Message) ClearSignatures() *Message
- func (m *Message) DecodeCtx() DecodeCtx
- func (m Message) LookupSignature(kid string) []*Signature
- func (m Message) MarshalJSON() ([]byte, error)
- func (m Message) Payload() []byte
- 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
- type ReadFileOption
- type SignOption
- type 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)
- func (s Signature) Signature() []byte
- func (s *Signature) UnmarshalJSON(data []byte) error
- type Signer
- type SignerFactory
- type SignerFactoryFn
- type SimpleJWKSetFetcher
- type Verifier
- type VerifierFactory
- type VerifierFactoryFn
- type VerifyOption
- func WithDetachedPayload(v []byte) VerifyOption
- func WithFetchBackoff(b backoff.Policy) VerifyOption
- func WithFetchWhitelist(wl jwk.Whitelist) VerifyOption
- func WithHTTPClient(httpcl *http.Client) VerifyOption
- func WithJWKSetFetcher(f JWKSetFetcher) VerifyOption
- func WithMessage(m *Message) VerifyOption
- type Visitor
- type VisitorFunc
Constants ¶
const ( AlgorithmKey = "alg" ContentTypeKey = "cty" CriticalKey = "crit" JWKKey = "jwk" JWKSetURLKey = "jku" KeyIDKey = "kid" TypeKey = "typ" X509CertChainKey = "x5c" X509CertThumbprintKey = "x5t" X509CertThumbprintS256Key = "x5t#S256" X509URLKey = "x5u" )
Variables ¶
This section is empty.
Functions ¶
func AlgorithmsForKey ¶ added in v1.2.7
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 ¶ added in v1.1.2
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 ¶ added in v1.1.0
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 ¶ added in v1.1.0
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 ¶
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.
func SignMulti ¶
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 ¶
SplitCompact splits a JWT and returns its three parts separately: protected headers, payload and signature.
func SplitCompactReader ¶ added in v1.1.0
SplitCompactReader splits a JWT and returns its three parts separately: protected headers, payload and signature.
func SplitCompactString ¶ added in v1.1.0
SplitCompactString splits a JWT and returns its three parts separately: protected headers, payload and signature.
func Verify ¶
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 ¶ added in v1.2.14
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 ¶ added in v1.1.0
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.
Types ¶
type HMACSigner ¶ added in v1.1.0
type HMACSigner struct {
// contains filtered or unexported fields
}
HMACSigner uses crypto/hmac to sign the payloads.
func (HMACSigner) Algorithm ¶ added in v1.1.0
func (s HMACSigner) Algorithm() jwa.SignatureAlgorithm
type HMACVerifier ¶ added in v1.1.0
type HMACVerifier struct {
// contains filtered or unexported fields
}
func (HMACVerifier) Verify ¶ added in v1.1.0
func (v HMACVerifier) Verify(payload, signature []byte, key interface{}) (err error)
type HeaderPair ¶ added in v1.0.0
type Headers ¶
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{} }
Headers describe a standard Header set.
func NewHeaders ¶ added in v1.0.0
func NewHeaders() Headers
type JWKSetFetchFunc ¶ added in v1.2.14
type JWKSetFetcher ¶ added in v1.2.14
JWKSetFetcher is used to fetch JWK Set spcified in the `jku` field.
type Message ¶
type Message struct {
// contains filtered or unexported fields
}
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.
func NewMessage ¶ added in v1.0.8
func NewMessage() *Message
func Parse ¶
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 ¶ added in v1.1.0
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 ¶
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 (*Message) AppendSignature ¶ added in v1.0.8
func (*Message) ClearSignatures ¶ added in v1.0.8
func (Message) LookupSignature ¶
LookupSignature looks up a particular signature entry using the `kid` value
func (Message) MarshalJSON ¶ added in v1.0.8
func (*Message) SetDecodeCtx ¶ added in v1.2.8
func (*Message) SetPayload ¶ added in v1.0.8
func (Message) Signatures ¶
func (*Message) UnmarshalJSON ¶ added in v1.0.8
type Option ¶
func WithSigner ¶
type ReadFileOption ¶ added in v1.1.0
type ReadFileOption interface { Option // contains filtered or unexported methods }
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 SignOption ¶ added in v1.2.2
type SignOption interface { Option // contains filtered or unexported methods }
func WithHeaders ¶
func WithHeaders(h Headers) SignOption
WithHeaders allows you to specify extra header values to include in the final JWS message
type Signature ¶
type Signature struct {
// contains filtered or unexported fields
}
func NewSignature ¶ added in v1.0.8
func NewSignature() *Signature
func (Signature) ProtectedHeaders ¶
func (Signature) PublicHeaders ¶
func (*Signature) SetDecodeCtx ¶ added in v1.2.8
func (*Signature) SetProtectedHeaders ¶ added in v1.0.8
func (*Signature) SetPublicHeaders ¶ added in v1.0.8
func (*Signature) SetSignature ¶ added in v1.0.8
func (*Signature) Sign ¶ added in v1.1.0
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 (*Signature) UnmarshalJSON ¶ added in v1.2.8
type Signer ¶ added in v1.1.0
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 }
Signer generates the signature for a given payload.
type SignerFactory ¶ added in v1.1.0
type SignerFactoryFn ¶ added in v1.1.0
func (SignerFactoryFn) Create ¶ added in v1.1.0
func (fn SignerFactoryFn) Create() (Signer, error)
type SimpleJWKSetFetcher ¶ added in v1.2.14
type SimpleJWKSetFetcher struct {
// contains filtered or unexported fields
}
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`
func NewJWKSetFetcher ¶ added in v1.2.14
func NewJWKSetFetcher(options ...jwk.FetchOption) *SimpleJWKSetFetcher
type Verifier ¶ added in v1.1.0
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 ¶ added in v1.1.0
func NewVerifier(alg jwa.SignatureAlgorithm) (Verifier, error)
NewVerifier creates a verifier that signs payloads using the given signature algorithm.
type VerifierFactory ¶ added in v1.1.0
type VerifierFactoryFn ¶ added in v1.1.0
func (VerifierFactoryFn) Create ¶ added in v1.1.0
func (fn VerifierFactoryFn) Create() (Verifier, error)
type VerifyOption ¶ added in v1.2.2
type VerifyOption interface { Option // contains filtered or unexported methods }
VerifyOption describes an option that can be passed to the jws.Verify function
func WithDetachedPayload ¶ added in v1.2.5
func WithDetachedPayload(v []byte) VerifyOption
WithDetachedPayload can be used to verify a JWS message with a detached payload. If you have to verify using this option, you should know exactly how and why this works.
func WithFetchBackoff ¶ added in v1.2.14
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 ¶ added in v1.2.14
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 ¶ added in v1.2.14
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 ¶ added in v1.2.14
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 ¶ added in v1.2.2
func WithMessage(m *Message) VerifyOption
WithMessage can be passed to Verify() to obtain the jws.Message upon a successful verification.
type Visitor ¶ added in v1.0.0
type Visitor = iter.MapVisitor
type VisitorFunc ¶ added in v1.0.0
type VisitorFunc = iter.MapVisitorFunc