Changes ======= v2 has many incompatibilities with v1. To see the full list of differences between v1 and v2, please read the Changes-v2.md file (https://github.com/lestrrat-go/jwx/blob/develop/v2/Changes-v2.md) v2.0.16 31 Oct 2023 [Security] * [jws] ECDSA signature verification requires us to check if the signature is of the desired length of bytes, but this check that used to exist before had been removed in #65, resulting in certain malformed signatures to pass verification. One of the ways this could happen if R is a 31 byte integer and S is 32 byte integer, both containing the correct signature values, but R is not zero-padded. Correct = R: [ 0 , ... ] (32 bytes) S: [ ... ] (32 bytes) Wrong = R: [ ... ] (31 bytes) S: [ ... ] (32 bytes) In order for this check to pass, you would still need to have all 63 bytes populated with the correct signature. The only modification a bad actor may be able to do is to add one more byte at the end, in which case the first 32 bytes (including what would have been S's first byte) is used for R, and S would contain the rest. But this will only result in the verification to fail. Therefore this in itself should not pose any security risk, albeit allowing some illegally formated messages to be verified. * [jwk] `jwk.Key` objects now have a `Validate()` method to validate the data stored in the keys. However, this still does not necessarily mean that the key's are valid for use in cryptographic operations. If `Validate()` is successful, it only means that the keys are in the right _format_, including the presence of required fields and that certain fields have proper length, etc. [New Features] * [jws] Added `jws.WithValidateKey()` to force calling `key.Validate()` before signing or verification. * [jws] `jws.Sign()` now returns a special type of error that can hold the individual errors from the signers. The stringification is still the same as before to preserve backwards compatibility. * [jwk] Added `jwk.IsKeyValidationError` that checks if an error is an error from `key.Validate()`. [Bug Fixes] * [jwt] `jwt.ParseInsecure()` was running verification if you provided a key via `jwt.WithKey()` or `jwt.WithKeySet()` (#1007) v2.0.15 19 20 Oct 2023 [Bug fixes] * [jws] jws.Sign() now properly check for valid algorithm / key type pair when the key implements crypto.Signer. This was caused by the fact that when jws.WithKey() accepted keys that implemented crypto.Signer, there really is no way to robustly check what algorithm the crypto.Signer implements. The code has now been modified to check for KNOWN key types, i.e. those that are defined in Go standard library, and those that are defined in this library. For example, now calling jws.Sign() with jws.WithKey(jwa.RS256, ecdsaKey) where ecdsaKey is either an instance of *ecdsa.PrivateKey or jwk.ECDSAPrivateKey will produce an error. However, if you use a separate library that wraps some KMS library which implements crypto.Signer, this same check will not be performed due to the fact that it is an unknown library to us. And there's no way to query a crypto.Signer for its algorithm family. v2.0.14 17 Oct 2023 [New Features] * [jwk] jwk.IsPrivateKey(), as well as jwk.AsymmetricKey has been added. The function can be used to tell if a jwk.Key is a private key of an asymmetric key pair. [Security] * golang.org/x/crypto has been updated to 0.14.0. The update contains a fix for HTTP/2 rapid reset DoS vulnerability, which some security scanning softwares may flag. However, do note that this library is NOT affected by the issue, as it does not have the capability to serve as an HTTP/2 server. This is included in this release document so that users will be able to tell why this library may be flagged when/if their scanning software do so. v2.0.13 26 Sep 2023 [New Features] * [jwk] jwk.Equal has been added. Please note that this is equivalent to comparing the keys' thumbprints, therefore it does NOT take in consideration non-essential fields. [Miscellaneous] * Various documentation fixes and additions. v2.0.12 - 11 Aug 2023 [Bug fixes] * [jwt] jwt.Serializer was ignoring JWE flags (#951) [Miscellaneous] * [jwk] Check for seed length on OKP JWKs to avoid panics (#947) * [jws] Documentation for jws.WithKeySet() v2.0.11 - 14 Jun 2023 [Security] * Potential Padding Oracle Attack Vulnerability and Timing Attack Vulnerability for JWE AES-CBC encrypted payloads affecting all v2 releases up to v2.0.10, all v1 releases up to v1.2.25, and all v0 releases up to v0.9.2 have been reported by @shogo82148. Please note that v0 versions will NOT receive fixes. This release fixes these vulnerabilities for the v2 series. v2.0.10 - 12 Jun 2023 [New Features] * [jwe] (EXPERIMENTAL) Added `jwe.KeyEncrypter` and `jwe.KeyDecrypter` interfaces that works in similar ways as how `crypto.Signer` works for signature generation and verification. It can act as the interface for your encryption/decryption keys that are for example stored in an hardware device. This feature is labeled experimental because the API for the above interfaces have not been battle tested, and may need to changed yet. Please be aware that until the API is deemed stable, you may have to adapat our code to these possible changes, _even_ during minor version upgrades of this library. [Bug fixes] * Registering JWS signers/verifiers did not work since v2.0.0, because the way we handle algorithm names changed in 2aa98ce6884187180a7145b73da78c859dd46c84. (We previously thought that this would be checked by the example code, but it apparently failed to flag us properly) The logic behind managing the internal database has been fixed, and `jws.RegisterSigner` and `jws.RegisterVerifier` now properly hooks into the new `jwa.RegisterSignatureAlgorithm` to automatically register new algorithm names (#910, #911) [Miscellaneous] * Added limited support for github.com/segmentio/asm/base64. Compile your code with the `jwx_asmbase64` build tag. This feature is EXPERIMENTAL. Through limited testing, the use of a faster base64 library provide 1~5% increase in throughput on average. It might make more difference if the input/output is large. If you care about this performance improvement, you should probably enable `goccy` JSON parser as well, by specifying `jwx_goccy,jwx_asmbase64` in your build call. * Slightly changed the way global variables underneath `jwk.Fetch` are initialized and configured. `jwk.Fetch` creates an object that spawns wokers to fetch JWKS when it's first called. You can now also use `jwk.SetGlobalFetcher()` to set a fetcher object which you can control. v2.0.9 - 21 Mar 2023 [Security Fixes] * Updated use of golang.org/x/crypto to v0.7.0 [Bug fixes] * Emitted PEM file for EC private key types used the wrong PEM armor (#875) [Miscellaneous] * Banners for generated files have been modified to allow tools to pick them up (#867) * Remove unused variables around ReadFileOption (#866) * Fix test failures * Support bazel out of the box * Now you can create JWS messages using `{"alg":"none"}`, by calling `jws.Sign()` with `jws.WithInsecureNoSignature()` option. (#888, #890). Note that there is no way to call `jws.Verify()` while allowing `{"alg":"none"}` as you wouldn't be _verifying_ the message if we allowed the "none" algorithm. `jws.Parse()` will parse such messages witout verification. `jwt` also allows you to sign using alg="none", but there's no symmetrical way to verify such messages. v2.0.8 - 25 Nov 2022 [Security Fixes] * [jws][jwe] Starting from go 1.19, code related to elliptic algorithms panics (instead of returning an error) when certain methods such as `ScalarMult` are called using points that are not on the elliptic curve being used. Using inputs that cause this condition, and you accept unverified JWK from the outside it may be possible for a third-party to cause panics in your program. This has been fixed by verifying that the point being used is actually on the curve before such computations (#840) [Miscellaneous] * `jwx.GuessFormat` now returns `jwx.InvalidFormat` when the heuristics is sure that the buffer format is invalid. v2.0.7 - 15 Nov 2022 [New features] * [jwt] Each `jwt.Token` now has an `Options()` method * [jwt] `jwt.Settings(jwt.WithFlattenedAudience(true))` has a slightly different semantic than before. Instead of changing a global variable, it now specifies that the default value of each per-token option for `jwt.FlattenAudience` is true. Therefore, this is what happens: // No global settings tok := jwt.New() tok.Options.IsEnabled(jwt.FlattenAudience) // false // With global settings jwt.Settings(jwt.WithFlattenedAudience(true)) tok := jwt.New() tok.Options.IsEnabled(jwt.FlattenAudience) // true // But you can still turn FlattenAudience off for this // token alone tok.Options.Disable(jwt.FlattenAudience) Note that while unlikely to happen for users relying on the old behavior, this change DOES introduce timing issues: whereas old versions switched the JSON marshaling for ALL tokens immediately after calling `jwt.Settings`, the new behavior does NOT affect tokens that have been created before the call to `jwt.Settings` (but marshaled afterwards). So the following may happen: // < v2.0.7 tok := jwt.New() jwt.Settings(jwt.WithFlattenedAudience(true)) json.Marshal(tok) // flatten = on // >= v2.0.7 tok := jwt.New() // flatten = off jwt.Settings(jwt.WithFlattenedAudience(true)) json.Marshal(tok) // flatten is still off It is recommended that you only set the global setting once at the very beginning of your program to avoid problems. Also note that `Clone()` copies the settings as well. [Miscellaneous] * WithCompact's stringification should have been that of the internal indentity struct ("WithSerialization"), but it was wrongly producing "WithCompact". This has been fixed. * Go Workspaces have been enabled within this module. - When developing, modules will refer to the main jwx module that they are part of. This allows us to explicitly specify the dependency version in, for example, ./cmd/jwx/go.mod but still develop against the local version. - If you are using `goimports` and other tools, you might want to upgrade binaries -- for example, when using vim-go's auto-format-on-save feature, my old binaries took well over 5~10 seconds to compute the import paths. This was fixed when I switched to using go1.19, and upgraded the binaries used by vim-go v2.0.6 - 25 Aug 2022 [Bug fixes][Security] * [jwe] Agreement Party UInfo and VInfo (apv/apu) were not properly being passed to the functions to compute the aad when encrypting using ECDH-ES family of algorithms. Therefore, when using apu/apv, messages encrypted via this module would have failed to be properly decrypted. Please note that bogus encrypted messages would not have succeed being decrypted (i.e. this problem does not allow spoofed messages to be decrypted). Therefore this would not have caused unwanted data to to creep in -- however it did pose problems for data to be sent and decrypted from this module when using ECDH-ES with apu/apv. While not extensively tested, we believe this regression was introduced with the v2 release. v2.0.5 - 11 Aug 2022 [Bug fixes] * [jwt] Remove stray debug log * [jwk] Fix x5u field name, caused by a typo * [misc] Update golangci-lint action to v3; v2 was causing weird problems v2.0.4 - 19 Jul 2022 [Bug Fixes] * [jwk] github.com/lestrrat-go/httprc, which jwk.Cache depends on, had a problem with inserting URLs to be re-fetched into its queue. As a result it could have been the case that some JWKS were not updated properly. Please upgrade if you use jwk.Cache. * [jwk] cert.Get could fail with an out of bounds index look up * [jwk] Fix doc buglet in `KeyType()` method [New Features] * [jws] Add `jws.WithMultipleKeysPerKeyID()` sub-option to allow non-unique key IDs in a given JWK set. By default we assume that a key ID is unique within a key set, but enabling this option allows you to handle JWK sets that contain multiple keys that contain the same key ID. * [jwt] Before v2.0.1, sub-second accuracy for time based fields (i.e. `iat`, `exp`, `nbf`) were not respected. Because of this the code to evaluate this code had always truncated any-subsecond portion of these fields, and therefore no sub-second comparisons worked. A new option for validation `jwt.WithTruncation()` has been added to workaround this. This option controls the value used to truncate the time fields. When set to 0, sub-second comparison would be possible. FIY, truncatation will still happen because we do not want to use the monotonic clocks when making comparisons. It's just that truncating using `0` as its argument effectively only strips out the monotonic clock v2.0.3 - 13 Jun 2022 [Bug Fixes] * [jwk] Update dependency on github.com/lestrrat-go/httprc to v1.0.2 to avoid unintended blocking in the update goroutine for jwk.Cache v2.0.2 - 23 May 2022 [Bug Fixes][Security] * [jwe] An old bug from at least 7 years ago existed in handling AES-CBC unpadding, where the unpad operation might remove more bytes than necessary (#744) This affects all jwx code that is available before v2.0.2 and v1.2.25. [New Features] * [jwt] RFC3339 timestamps are also accepted for Numeric Date types in JWT tokens. This allows users to parse servers that errnously use RFC3339 timestamps in some pre-defined fields. You can change this behavior by setting `jwt.WithNumericDateParsePedantic` to `false` * [jwt] `jwt.WithNumericDateParsePedantic` has been added. This is a global option that is set using `jwt.Settings` v2.0.1 - 06 May 2022 * [jwk] `jwk.Set` had erronously been documented as not returning an error when the same key already exists in the set. This is a behavior change since v2, and it was missing in the docs (#730) * [jwt] `jwt.ErrMissingRequiredClaim` has been deprecated. Please use `jwt.ErrRequiredClaim` instead. * [jwt] `jwt.WithNumericDateParsePrecision` and `jwt.WithNumericDateFormatPrecision` have been added to parse and format fractional seconds. These options can be passed to `jwt.Settings`. The default precision is set to 0, and fractional portions are not parsed nor formatted. The precision may be set up to 9. * `golang.org/x/crypto` has been upgraded (#724) * `io/ioutil` has been removed from the source code. v2.0.0 - 24 Apr 2022 * This i the first v2 release, which represents a set of design changes that were learnt over the previous 2 years. As a result the v2 API should be much more consistent and uniform across packages, and should be much more flexible to accomodate real-world needs. For a complete list of changes, please see the Changes-v2.md file, or check the diff at https://github.com/lestrrat-go/jwx/compare/v1...v2 [Miscellaneous] * Minor house cleaning on code generation tools [jwt] * `jwt.ErrMissingRequiredClaim()` has been added v2.0.0-beta2 - 16 Apr 2022 [jwk] * Updated `jwk.Set` API and reflected pending changes from v1 which were left over. Please see Changes-v2.md file for details. * Added `jwk.CachedSet`, a shim over `jwk.Cache` that allows you to have to write wrappers around `jwk.Cache` that retrieves a particular `jwk.Set` out of it. You can use it to, for example, pass `jwk.CachedSet` to a `jws.Verify` cache := jwk.NewCache(ctx) cache.Register(ctx, jwksURL) cachedSet := jwk.NewCachedSet(cache, jwksURL) jws.Verify(signed, jws.WithKeySet(cachedSet)) v2.0.0-beta1 - 09 Apr 2022 [Miscellaneous] * Renamed Changes.v2 to Changes-v2.md * Housecleaning for lint action. * While v2 was not affected, ported over equivalent test for #681 to catch regressions in the future. * Please note that there is no stability guarantees on pre-releases. v2.0.0-alpha1 - 04 Apr 2022 * Initial pre-release of v2 line. Please note that there is no stability guarantees on pre-releases.