Files
opencloud/vendor/github.com/lestrrat-go/jwx/v3/Changes
dependabot[bot] 42987b038b build(deps): bump github.com/open-policy-agent/opa from 1.15.2 to 1.17.1
Bumps [github.com/open-policy-agent/opa](https://github.com/open-policy-agent/opa) from 1.15.2 to 1.17.1.
- [Release notes](https://github.com/open-policy-agent/opa/releases)
- [Changelog](https://github.com/open-policy-agent/opa/blob/v1.17.1/CHANGELOG.md)
- [Commits](https://github.com/open-policy-agent/opa/compare/v1.15.2...v1.17.1)

---
updated-dependencies:
- dependency-name: github.com/open-policy-agent/opa
  dependency-version: 1.17.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-16 08:40:16 +00:00

604 lines
32 KiB
Plaintext

Changes
=======
v3 has many incompatibilities with v2. To see the full list of differences between
v2 and v3, please read the Changes-v3.md file (https://github.com/lestrrat-go/jwx/blob/develop/v3/Changes-v3.md)
v3.1.1 7 May 2026
* [jws] Coordinated RFC 7797 `b64=false` handling pass: `jws.Verify`
rejects payloads with `b64=false` unless `b64` is also listed in
`crit`; `jws.Sign` auto-declares `b64` in `crit` when emitting
`b64=false`; `Message.MarshalJSON` honors `b64=false` instead of
silently re-encoding; `jws.VerifyCompactFast` refuses any compact
JWS carrying `b64` (the fast path doesn't process extension
headers); and `b64` is now declared as a typed boolean header
field rather than handled ad-hoc.
(#2081, #2087, #2102, #2104, #2106)
* [jws] Reject malformed general-form JSON-serialized JWS: inputs
with a top-level `header` member as a sibling of `signatures` are
rejected (the spec only permits `header` inside per-signature
objects), as are inputs whose `protected` member is a literal
JSON object instead of a base64url-encoded string.
(#2089, #2108)
* [jws] `jws.AlgorithmsForKey` failures from unclassifiable keys
are now wrapped in a typed sentinel so callers can branch on
"couldn't categorize this key" without string matching the error
message. (#2110)
* [jws] Verify error-shape consistency: `VerifyCompactFast`
refusals now match the `jws.VerifyError()` taxonomy used by the
slow path, fan-out verify errors name the loose `WithKeySet`
options that were tried, multi-signature `b64` mismatches name
the offending signature index and conflicting value, and the
compact `b64=false`+payload-contains-`.` error references RFC
7797 §5.2 and points at `WithDetachedPayload`.
(#2083, #2085, #2114)
* [jws] Keys fetched via the `jku` header are no longer accepted
for signature verification when the JWK declares `use=enc`.
(#2060)
* [jws][jwe] `jws.VerifyMessage` and `jwe.DecryptMessage` observe
context cancellation between loop iterations rather than only at
boundaries. Long fan-out verify/decrypt loops now respond to a
cancelled context promptly. (#2112, #2117)
* [jwe] Reject PBES2 messages whose `p2c` (iteration count) does
not parse cleanly into int64 or violates the configured bound.
The error now names the violated bound (min vs max) instead of
the generic "out of range". (#2119)
* [jwe] `jwe.WithKey()` validates the alg-vs-key shape at option
construction time rather than during encryption, so misuse
surfaces at the call site instead of inside the encrypt loop.
(#2121)
* [jwe] Decrypt error-path cleanup: per-key failures from key-set
providers are surfaced via `errors.Join` so each underlying
error remains inspectable; the joined error count is bounded to
keep diagnostics readable; the redundant outer `Decrypt:` prefix
is dropped; and the compression-cap error names the
"decompressed" payload, the option, and the size.
(#2123, #2125, #2127)
* [jwe] Add `jwe.WithDisabledKeyAlgorithms(...)` as a global
policy hook (`jwe.Configure(...)` or per-call) for refusing
specific key-management algorithms across all `jwe.Decrypt`
calls. (#2129)
* [jwe] Reject messages whose protected-header `alg` conflicts
with a per-recipient `alg`. The previous behavior silently
preferred the protected-header value. (#2052)
* [jwk] Stop duplicating JWK fields at the JWKS top level on
parse. A JWKS whose top-level object carries fields with the
same names as JWK members no longer copies those values into
every key in `keys`. (#2133)
* [jwk] A custom `jwk.KeyParser` returning `(nil, nil)` now
signals "continue to the next parser" rather than "successfully
produced a nil key". Callers no longer end up with a nil
`jwk.Key` from a successful parse when an extension returns the
empty pair. (#2140)
* [jwk] Stream the JWKS `keys` array with a cap-before-allocate
strategy. Inputs respect `WithMaxKeys` before any unbounded
slice growth, and bounded-size JWKS no longer over-allocate
based on attacker-controlled length hints. (#2137)
* [jwk] Wrap `jwk.ParseKey` errors with the `jwk.ParseError`
sentinel so callers can branch on parse-vs-other failures with
`errors.Is(err, jwk.ParseError())`. (#2135)
* [jwk] ECDSA public keys whose X / Y coordinates exceed the
curve's byte length are rejected with a typed error instead of
reaching curve arithmetic with an out-of-range `big.Int`.
(#2050)
* [jwt] `jwt.ParseRequest` no longer skips the request body when
the request uses chunked transfer encoding. The
Content-Length-based fast path previously bypassed `ParseForm`
for chunked requests even when `WithFormKey` was supplied.
(#2091)
* [jwt] Pedantic mode (`jwt.WithPedanticParse(true)`) enforces
that nested-envelope JWTs declare `cty=JWT`. Tokens missing
`cty` or carrying a different value are rejected. (#2094)
* [jwt] `jwt.ParseInsecure` parses the loop-local payload split
from the input rather than the original input bytes. Fixes a
case where `ParseInsecure` could return a token assembled from
a different signature segment than the one being inspected.
(#2097)
* [jwt] `jwt.WithMaxDeltaIs(...)` and `jwt.WithMinDeltaIs(...)`
reject tokens whose compared claim is missing rather than
treating it as zero. Validation no longer silently succeeds
when the claim isn't present on the token. (#2099)
* [jwt] `jwt.Parse` / `jwt.ParseRequest` only call `ParseForm`
when `WithFormKey` is supplied. Previously the form body could
be consumed even when the caller did not opt in to form-source
extraction. (#2058)
* [jwt] Fix `AddressClaim.MarshalJSON` to handle non-printable
bytes correctly. (#2056)
* [jwa] Unify the signature, key-encryption, and
content-encryption algorithm tables behind a single
registration entry point. Extension algorithms register once
rather than via three parallel APIs. (#2066)
* [cmd/jwx] Warn before writing a private key to a TTY; reject
`keysize <= 0` for `oct` key generation. (#2071)
v3.1.0 19 Apr 2026
* [jwk] Add `jwk.WithRejectDuplicateKID(bool)` — when enabled, `jwk.Parse` /
`jwk.ParseReader` / `jwk.ParseString` return an error if the input JWKS
contains more than one key sharing the same non-empty `kid`. Usable as a
`jwk.Configure()` global or a per-call override. Default behavior
(first-match-wins) is unchanged.
* [jwk] Add `jwk.WithMaxKeys(int)` — caps the number of keys accepted
by `jwk.Parse` / `jwk.ParseReader` / `jwk.ParseString` in both the
JSON `"keys"` array and the PEM/X.509 block stream (default 1000).
Usable as a `jwk.Configure()` global or a per-call override.
Replaces the hardcoded internal PEM cap of the same value, so the
default behavior is unchanged. Backport of the v4 amplification
cap that mirrors `jws.WithMaxSignatures` and
`jwe.WithMaxRecipients`.
* [jws] Add `jws.WithDetachedPayloadReader(io.Reader)` — a streaming
variant of `jws.WithDetachedPayload([]byte)` that consumes the
payload from an `io.Reader` instead of a byte slice, so the payload
is never materialized in memory. It is a `jws.Sign()` / `jws.Verify()`
option; the two remain the default entry points. Only HMAC/RSA/ECDSA
algorithms are supported; EdDSA, custom-family algorithms, and
algorithms registered via `jws.RegisterSigner()` / `jws.RegisterVerifier()`
are rejected with a clear error pointing at `jws.WithDetachedPayload()`.
On sign, multiple `jws.WithKey()` options combined with `jws.WithJSON()`
produce a general-form multi-signature JWS (the payload is streamed
once and fanned out to each signer). On verify, only single-signature
JWS input is supported; `jws.WithKeySet()`, `jws.WithKeyProvider()`,
and `jws.WithVerifyAuto()` are not accepted. (#1663)
* [jws] Add `jws.Base64StreamEncoder` — the stream-capable extension
of `jws.Base64Encoder`. The default encoder and `*base64.Encoding`
values supplied via `jws.WithBase64Encoder()` are auto-wrapped, so
typical callers see no change. Custom encoders only need to
implement this additional interface if they want to be usable with
`jws.WithDetachedPayloadReader()`. (#1663)
* [jws] Fix `jws.Sign` with `WithDetachedPayload` + `WithJSON` to
omit the `"payload"` member from the output per RFC 7515
Appendix F. Previously the payload was still emitted, producing
non-detached JSON. (#1663)
* [jwk] BREAKING: `jwk.PublicSetOf` now returns an error when the input
set contains a symmetric (oct) key. Previously, symmetric keys were
silently passed through — which meant callers following the documented
"publish my public JWKS" pattern could leak HMAC secret material.
Callers who genuinely want the legacy pass-through behavior can opt in
with `jwk.WithAllowSymmetric(true)`. The signature is now variadic
(`PublicSetOf(v Set, options ...PublicSetOption)`), so existing call
sites compile unchanged. The minor version is bumped from v3.0.x →
v3.1.0 to reflect this deliberate behavior change.
`jwk.PublicKeyOf` on a single symmetric key is unchanged — it still
returns the key as-is, matching its documented behavior.
* [jws][jwe][jwk] Replace intermediate map[string]any allocation in
MarshalJSON with a pair-slice + sync.Pool pattern, matching the approach
already used in jwt. Eliminates per-call map and key-slice allocations
in the serialization hot path.
* [jwt][jwe][jws][jwk] Fix inconsistent mutex locking across main data
structures. Named getters on JWK key types, MarshalJSON on JWK keys,
UnmarshalJSON on JWE headers, makePairs/MarshalJSON on JWT tokens,
rawBuffer on JWS headers, and Set/Keys on jwk.Set were missing proper
lock protection. Switch all mutex fields from *sync.RWMutex (pointer)
to sync.RWMutex (value) so go vet -copylocks catches accidental copies,
and convert affected value-receiver methods to pointer receivers.
* [jwe] Add `WithMaxRecipients(int)` to reject JWE messages with more recipients
than the configured limit. Default is 100. Can be set globally via
`jwe.Settings()` or per-call in `jwe.Decrypt()` / `jwe.Parse()`. (#1633)
* [jws] Add `WithMaxSignatures(int)` to reject JWS JSON-serialized messages with
more signatures than the configured limit. Default is 100. Can be set globally
via `jws.Settings()` or per-call in `jws.Parse()`. (#1636)
* [jwk] The default HTTP client used by `jwk.Fetch()` and `jwk.Cache` now
enforces a 30-second timeout, blocks HTTPS-to-HTTP redirect downgrades at
every hop, and limits redirect chains to 5 hops. This mitigates SSRF via
redirect chains and slowloris-style DoS from unresponsive JWKS endpoints.
Callers who provide their own `http.Client` via `jwk.WithHTTPClient()` are
not affected. (#1634, #1637, #1639, #1640)
* [jwk] Add `jwk.DefaultHTTPClient()` which returns a new `*http.Client`
configured with the library's default protections. Useful for restoring
defaults after calling `jwk.Configure(jwk.WithHTTPClient(...))`. (#1638)
* [jwk] `WithMaxFetchBodySize(int64)` can now be set globally via
`jwk.Configure()` in addition to per-call. (#1631)
* [jwk] Add `jwk.WrapHTTPClientDefaults()` to apply the library's default
safety behaviors (timeout, redirect policy) to a caller-provided
`*http.Client`. Existing client settings (Transport, Jar, etc.) are
preserved; CheckRedirect is wrapped rather than overwritten.
* [jwt] Add `jwt.WithStrictStringClaims(true)` option for `jwt.Parse()` and
`jwt.ReadFile()` to reject JSON `null` for string registered claims
(`iss`, `sub`, `jti`). By default, null is silently accepted as an empty
string. (#1484)
* [jwa] Add fully-specified EdDSA signature algorithms `Ed25519` and `Ed448` per
RFC 9864. The polymorphic `EdDSA` algorithm is now marked as deprecated.
New Go accessors: `jwa.EdDSAEd25519()` and `jwa.EdDSAEd448()` (function names
are tentative and may change in future releases).
Ed448 signing/verification requires `github.com/cloudflare/circl` because
Go's standard library does not support Ed448. To avoid pulling in this
extra dependency for all users, Ed448 support is provided as a separate
module (`github.com/lestrrat-go/jwx-circl-ed448`). Import it for side
effects to enable Ed448:
import _ "github.com/lestrrat-go/jwx-circl-ed448"
Without this import, Ed448 is registered as an algorithm identifier but
will return an error at sign/verify time.
* [jwk] Add `jwk/jwkunsafe` package with `NewKey(kty)` and `NewPublicKey(kty)`
functions for creating empty, unpopulated JWK key objects. This is intended
for extension module authors who need to register custom KeyImporter
implementations for new key types.
* [jws] Add `jws.RegisterAlgorithmForKeyType()` for external modules to register
additional algorithm-to-key-type mappings.
* [jws/jwsbb] Add `jwsbb.RegisterAlgorithm()` for external modules to
register custom algorithm implementations (e.g. Ed448).
* [jws] `jws.Verify()` and `jws.VerifyCompactFast()` now validate the "crit"
(Critical) header parameter per RFC 7515 Section 4.1.11. Signatures with an
empty "crit" array, standard JOSE header names in "crit", or "crit"-listed
extensions not present in the protected header are now rejected. To disable
this validation on a per-call basis, pass
`jws.WithCritValidation(false)` to `jws.Verify()`.
* [jwe] `jwe.Decrypt()` now validates the "crit" (Critical) header parameter
per RFC 7516 Section 4.1.13, matching the jws behavior above. Messages with
an empty "crit" array, standard JOSE header names in "crit", or "crit"-listed
extensions not present in the protected header are now rejected. Declare
extensions with `jwe.WithCritExtension()`, or disable validation on a
per-call basis with `jwe.WithCritValidation(false)`. (#1735)
* [jwk] BREAKING (extension modules): `jwk.RegisterKeyExporter` now takes a
`jwk.KeyKind` instead of `jwa.KeyType`. Call sites migrate with
`jwk.KeyKind(kty.String())`; for curve-specific exporters, use a compound
identity like `jwk.KeyKind("OKP:Ed448")`. Only affects extension-module
authors registering custom exporters; library users calling `jwk.Export`
are unaffected.
* [jwk] Fixed inverted rlocker condition in RSA key export. (#1576)
* [jwe] Fixed X25519 ECDH-ES key agreement to include `apu` and `apv` parameters
in the Concat KDF derivation, matching the ECDSA path. Previously these values
were silently discarded during encryption, weakening the key derivation per
RFC 7518 Section 4.6.2.
* [jwe] POTENTIALLY BREAKING: `jwe.Decrypt()` now rejects PBES2 messages with
a `p2c` (iteration count) below 1,000 by default. This prevents accepting
tokens with trivially low iteration counts that eliminate PBKDF2 brute-force
protection. To restore the previous behavior or adjust the threshold, call
`jwe.Settings(jwe.WithMinPBES2Count(0))`.
* [jwk] Fixed a deadlock in `jwk.Cache` that occurred when repeated `Refresh()` calls
failed (e.g. HTTP 500 responses). Each failure killed an httprc worker goroutine,
and after all workers were exhausted, subsequent `Refresh()` calls would block forever. (#1551)
* [jws] Add `jws.RegisterAlgorithmForCurve()` for external modules to register
algorithm-to-curve mappings. `jws.AlgorithmsForKey()` now filters results
by the key's curve when applicable. (#1620)
* [jwk] Add `jwk.WithMaxFetchBodySize()` option to limit the response body size
when fetching remote JWK Sets via `jwk.Fetch()` and `jwk.Cache`. (#1622)
* [jwe] Add `jwe.WithMaxPBES2Count()` and `jwe.WithMinPBES2Count()` as per-call
options to `jwe.Decrypt()`, allowing callers to override the global PBES2
iteration count limits on a per-decryption basis. (#1623)
* [jwk] `jwk.X509CertChain()` now correctly returns `false` as the second return
value when the certificate chain is nil. (#1624)
* [jwk] Fixed a data race in the x509 decoder registry iteration. (#1625)
* [jwk] `jwk.Parse()` now limits PEM input to 1,000 blocks maximum to prevent
resource exhaustion from inputs containing thousands of small PEM blocks. (#1626)
* [jwk] RSA JWK validation is now enforced consistently across JSON parse,
JWKS parse, PEM/X.509 parse, and `jwk.Import()`. Keys with moduli smaller
than 2048 bits or unsafe public exponents are now rejected by default.
Compatibility knobs were added to `jwk.Configure()` via
`jwk.WithMinRSAModulusBits(...)` and `jwk.WithMinRSAPublicExponent(...)`.
* [jwt] `jwt.Validate()` now rejects negative durations passed to
`jwt.WithAcceptableSkew()`. (#1627)
* [jwt/openid] `openid.Birthdate` now accepts year `0000` as a valid value per
the OpenID Connect Core specification. (#1628)
* [jwk][jws][jwe] Generated `Set()` methods now deep-copy slice and byte-slice
values so callers cannot mutate internal header or key state after setting
a field. (#1659)
* [jwk] When `UnmarshalJSON` fails on a private key (RSA, EC, OKP, Symmetric),
all sensitive fields are now zeroed before the error is returned. This
prevents leaking partial key material through half-constructed objects. (#1660)
v3.0.13 12 Jan 2026
* [jwt] The `jwt.WithContext()` option is now properly being passed to `jws.Verify()` from
`jwt.Parse()`.
* [jwx] github.com/lestrrat-go/httprc/v3 has been upgraded to remove dependency on
github.com/lestrrat-go/option (v1)
* [jwk] `jwk.Clone()` has been fixed to properly work with private fields.
v3.0.12 20 Oct 2025
* [jwe] As part of the next change, now per-recipient headers that are empty
are no longer serialized in flattened JSON serialization.
* [jwe] Introduce `jwe.WithLegacyHeaderMerging(bool)` option to control header
merging behavior in during JWE encryption. This only applies to flattened
JSON serialization.
Previously, when using flattened JSON serialization (i.e. you specified
JSON serialization via `jwe.WithJSON()` and only supplied one key), per-recipient
headers were merged into the protected headers during encryption, and then
were left to be included in the final serialization as-is. This caused duplicate
headers to be present in both the protected headers and the per-recipient headers.
Since there may be users who rely on this behavior already, instead of changing the
default behavior to fix this duplication, a new option to `jwe.Encrypt()` was added
to allow clearing the per-recipient headers after merging to leave the `"headers"`
field empty. This in effect makes the flattened JSON serialization more similar to
the compact serialization, where there are no per-recipient headers present, and
leaves the headers disjoint.
Note that in compact mode, there are no per-recipient headers and thus the
headers need to be merged regardless. In full JSON serialization, we never
merge the headers, so it is left up to the user to keep the headers disjoint.
* [jws] Calling the deprecated `jws.NewSigner()` function for the first time will cause
legacy signers to be loaded automatically. Previously, you had to explicitly
call `jws.Settings(jws.WithLegacySigners(true))` to enable legacy signers.
We incorrectly assumed that users would not be using `jws.NewSigner()`, and thus
disabled legacy signers by default. However, it turned out that some users
were using `jws.NewSigner()` in their code, which lead to breakages in
existing code. In hindsight we should have known that any API made public before will
be used by _somebody_.
As a side effect, jws.Settings(jws.WithLegacySigners(...)) is now a no-op.
However, please do note that jws.Signer (and similar) objects were always intended to be
used for _registering_ new signing/verifying algorithms, and not for end users to actually
use them directly. If you are using them for other purposes, please consider changing
your code, as it is more than likely that we will somehow deprecate/remove/discouraged
their use in the future.
v3.0.11 14 Sep 2025
* [jwk] Add `(jwk.Cache).Shutdown()` method that delegates to the httprc controller
object, to shutdown the cache.
* [jwk] Change timing of `res.Body.Close()` call
* [jwe] Previously, ecdh.PrivateKey/ecdh.PublicKey were not properly handled
when used for encryption, which has been fixed.
* [jws/jwsbb] (EXPERIMENTAL/BREAKS COMPATIBILITY) Convert most functions into
thin wrappers around functions from github.com/lestrrat-go/dsig package.
As a related change, HAMCHashFuncFor/RSAHashFuncFor/ECDSAHashFuncFor/RSAPSSOptions
have been removed or unexported.
Users of this module should be using jwsbb.Sign() and jwsbb.Verify() instead of
algorithm specific jwsbb.SignRSA()/jwsbb.VerifyRSA() and such. If you feel the
need to use these functions, you should use github.com/lestrrat-go/dsig directly.
v3.0.10 04 Aug 2025
* [jws/jwsbb] Add `jwsbb.ErrHeaderNotFound()` to return the same error type as when
a non-existent header is requested. via `HeaderGetXXX()` functions. Previously, this
function was called `jwsbb.ErrFieldNotFound()`, but it was a misnomer.
* [jws/jwsbb] Fix a bug where error return values from `HeaderGetXXX()` functions
could not be matched against `jwsbb.ErrHeaderNotFound()` using `errors.Is()`.
v3.0.9 31 Jul 2025
* [jws/jwsbb] `HeaderGetXXX()` functions now return errors when
the requested header is not found, or if the value cannot be
converted to the requested type.
* [jwt] `(jwt.Token).Get` methods now return specific types of errors depending
on if a) the specified claim was not present, or b) the specified claim could
not be assigned to the destination variable.
You can distinguish these by using `errors.Is` against `jwt.ClaimNotFoundError()`
or `jwt.ClaimAssignmentFailedError()`
v3.0.8 27 Jun 2025
* [jwe/jwebb] (EXPERIMENTAL) Add low-level functions for JWE operations.
* [jws/jwsbb] (EXPERIMENTAL/BREAKS COMPATIBILITY) Add io.Reader parameter
so your choice of source of randomness can be passed. Defaults to crypto/rand.Reader.
Function signatures around jwsbb.Sign() now accept an addition `rr io.Reader`,
which can be nil for 99% of use cases.
* [jws/jwsbb] Add HeaderParse([]byte), where it is expected that the header
is already in its base64 decoded format.
* misc: replace `interface{}` with `any`
v3.0.7 16 Jun 2025
* [jws/jwsbb] (EXPERIMENTAL) Add low-level fast access to JWS headers in compact
serialization form.
* [jws] Fix error reporting when no key matched for a signature.
* [jws] Refactor jws signer setup.
* Known algorithms are now implemented completely in the jws/jwsbb package.
* VerifierFor and SignerFor now always succeed, and will also return a Signer2
or Verifier2 that wraps the legacy Signer or Verifier if one is registered.
v3.0.6 13 Jun 2025
* This release contains various performance improvements all over the code.
No, this time for real. In particular, the most common case for signing
a JWT with a key is approx 70% more efficient based on the number of allocations.
Please read the entry for the (retracted) v3.0.4 for what else I have to
say about performance improvements
* [jwt] Added fast-path for token signing and verification. The fast path
is triggered if you only pass `jwt.Sign()` and `jwt.Parse()` one options each
(`jwt.WithKey()`), with no suboptions.
* [jws] Major refactoring around basic operations:
* How to work with Signer/Verifier have completely changed. Please take
a look at examples/jws_custom_signer_verifier_example_test.go for how
to do it the new way. The old way still works, but it WILL be removed
when v4 arrives.
* Related to the above, old code has been moved to `jws/legacy`.
* A new package `jws/jwsbb` has been added. `bb` stands for building blocks.
This package separates out the low-level JWS operations into its own
package. So if you are looking for just the signing of a payload with
a key, this is it.
`jws/jwsbb` is currently considered to be EXPERIMENTAL.
v3.0.5 11 Jun 2025
* Retract v3.0.4
* Code for v3.0.3 is the same as v3.0.3
v3.0.4 09 Jun 2025
* This release contains various performance improvements all over the code.
Because of the direction that this library is taking, we have always been
more focused on correctness and usability/flexibility over performance.
It just so happens that I had a moment of inspiration and decided to see
just how good our AI-based coding agents are in this sort of analysis-heavy tasks.
Long story short, the AI was fairly good at identifying suspicious code with
an okay accuracy, but completely failed to make any meaningful changes to the
code in a way that both did not break the code _and_ improved performance.
I am sure that they will get better in the near future, but for now,
I had to do the changes myself. I should clarify to their defence that
the AI was very helpful in writing cumbersome benchmark code for me.
The end result is that we have anywhere from 10 to 30% performance improvements
in various parts of the code that we touched, based on number of allocations.
We believe that this would be a significant improvement for many users.
For further improvements, we can see that there would be a clear benefit to
writing optimized code path that is designed to serve the most common cases.
For example, for the case of signing JWTs with a single key, we could provide
a path that skips a lot of extra processing (we kind of did that in this change,
but we _could_ go ever harder in this direction). However, it is a trade-off between
maintainability and performance, and as I am currently the sole maintainer of
this library for the time being, I only plan to pursue such a route where it
requires minimal effort on my part.
If you are interested in helping out in this area, I hereby thank you in advance.
However, please be perfectly clear that unlike other types of changes, for performance
related changes, the balance between the performance gains and maintainability is
top priority. If you have good ideas and code, they will always be welcome, but
please be prepared to justify your changes.
Finally, thank you for using this library!
v3.0.3 06 Jun 2025
* Update some dependencies
* [jwe] Change some error messages to contain more context information
v3.0.2 03 Jun 2025
* [transform] (EXPERIMENTAL) Add utility function `transform.AsMap` to convert a
Mappable object to a map[string]interface{}. This is useful for converting
objects such as `jws.Header`, `jwk.Key`, `jwt.Token`, etc. to a map that can
be used with other libraries that expect a map.
* [jwt] (EXPERIMENTAL) Added token filtering functionality through the TokenFilter interface.
* [jwt/openid] (EXPERIMENTAL) Added StandardClaimsFilter() for filtering standard OpenID claims.
* [jws] (EXPERIMENTAL) Added header filtering functionality through the HeaderFilter interface.
* [jwe] (EXPERIMENTAL) Added header filtering functionality through the HeaderFilter interface.
* [jwk] (EXPERIMENTAL) Added key filtering functionality through the KeyFilter interface.
* [jwk] `jwk.Export` previously did not recognize third-party objects that implemented `jwk.Key`,
as it was detecting what to do by checking if the object was one of our own unexported
types. This caused some problems for consumers of this library that wanted to extend the
features of the keys.
Now `jwk.Export` checks types against interface types such as `jwk.RSAPrivateKey`, `jwk.ECDSAPrivateKey`, etc.
It also uses some reflect blackmagic to detect if the given object implements the `jwk.Key` interface
via embedding, so you should be able to embed a `jwk.Key` to another object to act as if it
is a legitimate `jwk.Key`, as far as `jwk.Export` is concerned.
v3.0.1 29 Apr 2025
* [jwe] Fixed a long standing bug that could lead to degraded encryption or failure to
decrypt JWE messages when a very specific combination of inputs were used for
JWE operations.
This problem only manifested itself when the following conditions in content encryption or decryption
were met:
- Content encryption was specified to use DIRECT mode.
- Contentn encryption algorithm is specified as A256CBC_HS512
- The key was erronously constructed with a 32-byte content encryption key (CEK)
In this case, the user would be passing a mis-constructed key of 32-bytes instead
of the intended 64-bytes. In all other cases, this construction would cause
an error because `crypto/aes.NewCipher` would return an error when a key with length
not matching 16, 24, and 32 bytes is used. However, due to use using a the provided
32-bytes as half CEK and half the hash, the `crypto/aes.NewCipher` was passed
a 16-byte key, which is fine for AES-128. So internally `crypto/aes.NewCipher` would
choose to use AES-128 instead of AES-256, and happily continue. Note that no other
key lengths such as 48 and 128 would have worked. It had to be exactly 32.
This does indeed result in a downgraded encryption, but we believe it is unlikely that this would cause a problem in the real world,
as you would have to very specifically choose to use DIRECT mode, choose
the specific content encryption algorithm, AND also use the wrong key size of
exactly 32 bytes.
However, in abandunce of caution, we recommend that you upgrade to v3.0.1 or later,
or v2.1.6 or later if you are still on v2 series.
* [jws] Improve performance of jws.SplitCompact and jws.SplitCompactString
* [jwe] Improve performance of jwe.Parse
v3.0.0 1 Apr 2025
* Release initial v3.0.0 series. Code is identical to v3.0.0-beta2, except
for minor documentation changes.
Please note that v1 will no longer be maintained.
Going forward v2 will receive security updates but will no longer receive
feature updates. Users are encouraged to migrate to v3. There is no hard-set
guarantee as to how long v2 will be supported, but if/when v4 comes out,
v2 support will be terminated then.
v3.0.0-beta2 30 Mar 2025
* [jwk] Fix a bug where `jwk.Set`'s `Keys()` method did not return the proper
non-standard fields. (#1322)
* [jws][jwt] Implement `WithBase64Encoder()` options to pass base64 encoders
to use during signing/verifying signatures. This useful when the token
provider generates JWTs that don't follow the specification and uses base64
encoding other than raw url encoding (no padding), such as, apparently,
AWS ALB. (#1324, #1328)
v3.0.0-beta1 15 Mar 2025
* [jwt] Token validation no longer truncates time based fields by default.
To restore old behavior, you can either change the global settings by
calling `jwt.Settings(jwt.WithTruncation(time.Second))`, or you can
change it by each invocation by using `jwt.Validate(..., jwt.WithTruncation(time.Second))`
v3.0.0-alpha3 13 Mar 2025
* [jwk] Importing/Exporting from jwk.Key with P256/P386/P521 curves to
ecdh.PrivateKey/ecdh.PublicKey should now work. Previously these keys were not properly
recognized by the exporter/importer. Note that keys that use X25519 and P256/P384/P521
behave differently: X25519 keys can only be exported to/imported from OKP keys,
while P256/P384/P521 can be exported to either ecdsa or ecdh keys.
v3.0.0-alpha2 25 Feb 2025
* Update to work with go1.24
* Update tests to work with latest latchset/jose
* Fix build pipeline to work with latest golangci-lint
* Require go1.23
v3.0.0-alpha1 01 Nov 2024
* Initial release of v3 line.