...

Text file src/github.com/lestrrat-go/jwx/docs/02-jws.md

Documentation: github.com/lestrrat-go/jwx/docs

     1# Working with JWS
     2
     3In this document we describe how to work with JWS using [`github.com/lestrrat-go/jwx/jws`](https://pkg.go.dev/github.com/lestrrat-go/jwx/jws)
     4
     5* [Parsing](#parsing)
     6  * [Getting the payload from a JWS encoded buffer](#getting-the-payload-from-a-jws-encoded-buffer)
     7  * [Parse a JWS encoded buffer into a jws.Message](#parse-a-jws-encoded-buffer-into-a-jwsmessage)
     8  * [Parse a JWS encoded message stored in a file](#parse-a-jws-encoded-message-stored-in-a-file)
     9* [Signing](#signing)
    10  * [Generating a JWS message in compact serialization format](#generating-a-jws-message-in-compact-serialization-format)
    11  * [Generating a JWS message in JSON serialization format](#generating-a-jws-message-in-json-serialization-format)
    12  * [Generating a JWS message with detached payload](#generating-a-jws-with-detached-payload)
    13  * [Using cloud KMS services](#using-cloud-kms-services)
    14* [Verifying](#verifying)
    15  * [Verification using `jku`](#verification-using-jku)
    16* [Using a custom signing/verification algorithm](#using-a-customg-signingverification-algorithm)
    17* [Enabling ES256K](#enabling-es256k)
    18# Parsing
    19
    20## Getting the payload from a JWS encoded buffer
    21
    22If you want to get the payload in the JWS message after it has been verified, use [`jws.Verify()`](https://pkg.go.dev/github.com/lestrrat-go/jwx/jws#Verify)
    23
    24```go
    25var encoded = []byte{...}
    26payload, _ := jws.Verify(encoded, alg, key)
    27```
    28
    29You must provide the algorithm and the public key to use for verification.
    30Please read "[Why don't you automatically infer the algorithm for `jws.Verify`?](99-faq.md#why-dont-you-automatically-infer-the-algorithm-for-jwsverify-)"
    31
    32If the algorithm or the key does not match, an error is returned.
    33
    34## Parse a JWS encoded buffer into a jws.Message
    35
    36You can parse a JWS buffer into a [`jws.Message`](https://pkg.go.dev/github.com/lestrrat-go/jwx/jws#Message) object. In this mode, there is no verification performed.
    37
    38```go
    39var payload = []byte{...}
    40msg, _ := jws.Parse(payload)
    41```
    42
    43Note that [`jws.Message`](https://pkg.go.dev/github.com/lestrrat-go/jwx/jws#Message) is not really built for general signing/verification usage.
    44It's built more so for inspection purposes.
    45Think twice before attempting to do anything more than inspection using [`jws.Message`](https://pkg.go.dev/github.com/lestrrat-go/jwx/jws#Message).
    46
    47## Parse a JWS encoded message stored in a file
    48
    49To parse a JWS stored in a file, use [`jws.ReadFile()`](https://pkg.go.dev/github.com/lestrrat-go/jwx/jws#ReadFile). [`jws.ReadFile()`](https://pkg.go.dev/github.com/lestrrat-go/jwx/jws#ReadFile) accepts the same options as [`jws.Parse()`](https://pkg.go.dev/github.com/lestrrat-go/jwx/jws#Parse).
    50
    51```go
    52message, _ := jws.ReadFile(`message.jws`)
    53```
    54
    55## Verify a JWS with detached payload
    56
    57To parse a JWS with detached payload, use the `jws.WithDetachedPayload()` option:
    58
    59```go
    60signed, _ := jws.Verify(signed, alg, key, jws.WithDetachedPayload(payload))
    61```
    62
    63# Signing
    64
    65## Generating a JWS message in compact serialization format
    66
    67In most cases this is all you really need.
    68
    69```go
    70signed, _ := jws.Sign(payload, alg, key)
    71```
    72
    73To sign a JWT, use [`jwt.Sign()`](https://pkg.go.dev/github.com/lestrrat-go/jwx/jwt#Sign)
    74
    75```go
    76signed, _ := jwt.Sign(token, alg, key)
    77```
    78
    79## Generating a JWS message in JSON serialization format
    80
    81Generally the only time you need to use a JSON serialization format is when you have to generate multiple signatures for a given payload using multiple signing algorithms and keys.
    82When this need arises, use the [`jws.SignMulti()`](https://pkg.go.dev/github.com/lestrrat-go/jwx/jws#SignMulti) method.
    83
    84```go
    85signer, _ := jws.NewSigner(alg)
    86signed, _ := jws.SignMulti(payload, jws.WithSigner(signer, key, pubHeaders, protHeaders)
    87```
    88
    89## Generating a JWS message with detached payload
    90
    91Use the `jws.WithDetachedPayload()` option to sign a detached payload:
    92
    93```go
    94signed, _ := jws.Sign(nil, alg, key, jws.WithDetachedPayload(payload))
    95```
    96
    97## Including Arbitrary Headers to Compact Serialization
    98
    99By default, only some header fields are included in the result from `jws.Sign()`.
   100If you want to include more headers fields in the resulting JWS, you will have to provide them via the `jws.WithHeaders()` option
   101
   102```go
   103hdrs := jws.NewHeaders()
   104hdrs.Set(`arbitrary-key`, `value`)
   105signed, _ := jws.Sign(payload, alg, key, jws.WithHEaders(hdrs))
   106```
   107
   108## Using cloud KMS services
   109
   110If you want to use cloud KMSes such as AWS KMS to sign and verify payloads, look for an object that implements
   111`crypto.Signer`. There are some [implementations written for this module](https://github.com/jwx-go/crypto-signer).
   112
   113Event if you cannot find an implementation that you are looking for in the above repository, any other implementation that implements `crypto.Signer` should work.
   114
   115# Verifying
   116
   117## Verification using a single key
   118
   119Simply use `jws.Verify()`. It will automatically do the right thing whether it's serialized in compact
   120form or JSON form.
   121
   122```go
   123payload, _ := jws.Verify(data, alg, key)
   124```
   125
   126The `alg` must be explicitly specified. See "[Why don't you automatically infer the algorithm for `jws.Verify`?](99-faq.md#why-dont-you-automatically-infer-the-algorithm-for-jwsverify-)"
   127
   128To verify a JWS message with detached payload, use the `jws.WithDetachedPayload()` option:
   129
   130```go
   131_, err := jws.Verify(data, alg, key, jws.WithDetachedPayload(payload))
   132```
   133
   134## Verification using `jku`
   135
   136Regular calls to `jws.Verify()` does not respect the JWK Set referenced in the `jku` field. In order to
   137verify the payload using the `jku` field, you must use the `jws.VerifyAuto()` function.
   138
   139```go
   140wl := ... // Create an appropriate whitelist
   141payload, _ := jws.VerifyAuto(buf, jws.WithFetchWhitelist(wl))
   142```
   143
   144This will tell `jws` to verify the given buffer using the JWK Set presented at the URL specified in
   145the `jku` field. If the buffer is a JSON message, then this is done for each of the signature in
   146the `signatures` array.
   147
   148The URL in the `jku` field must have the `https` scheme, and the key ID in the JWK Set must
   149match the key ID present in the JWS message.
   150
   151Because this operation will result in your program accessing remote resources, the default behavior
   152is to NOT allow any URLs. You must specify a whitelist
   153
   154```go
   155wl := jwk.NewMapWhitelist().
   156  Add(`https://white-listed-address`)
   157
   158payload, _ := jws.VerifyAuto(buf, jws.WithFetchWhitelist(wl))
   159```
   160
   161If you want to allow any URLs to be accessible, use the `jwk.InsecureWhitelist`.
   162
   163```go
   164wl := jwk.InsecureWhitelist{}
   165payload, _ := jws.VerifyAuto(buf, jws.WithFetchWhitelist(wl))
   166```
   167
   168If you must configure the HTTP Client in a special way, use the `jws.WithHTTPClient()` option:
   169
   170```go
   171client := &http.Client{ ... }
   172payload, _ := jws.VerifyAuto(buf, jws.WithHTTPClient(client))
   173```
   174
   175# Using a custom signing/verification algorithm
   176
   177Sometimes we do not offer a particular algorithm out of the box, but you have an implementation for it.
   178
   179In such scenarios, you can use the [`jws.RegisterSigner()`](https://pkg.go.dev/github.com/lestrrat-go/jwx/jws#RegisterSigner) and [`jws.RegisterVerifier()`](https://pkg.go.dev/github.com/lestrrat-go/jwx/jws#RegisterVerifier) functions to
   180generate your own verifier instance. 
   181
   182```go
   183jws.RegisterSigner(alg, signerFactory)
   184jws.RegisterVerifier(alg, verifierFactory)
   185```
   186
   187# Enabling ES256K
   188
   189See [Enabling Optional Signature Methods](./20-global-settings.md#enabling-optional-signature-methods)

View as plain text