Skip to content

Merge release 4.2.1 into 4.3.x - #702

Merged
Spomky merged 11 commits into
4.3.xfrom
4.2.x-merge-up-into-4.3.x_ZRaIehPF
Aug 28, 2026
Merged

Merge release 4.2.1 into 4.3.x#702
Spomky merged 11 commits into
4.3.xfrom
4.2.x-merge-up-into-4.3.x_ZRaIehPF

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

Spomky and others added 11 commits August 28, 2026 12:26
…iver

`JWSBuilder::addSignature()` is documented as immutable but it wrote
`isPayloadEncoded` on `$this` before cloning. The bundle registers the
builder as a shared service, so the first call pinned the "b64" mode of
that service for the rest of the process and any later, unrelated build
failed with "Foreign payload encoding detected.".

Clone first, then perform the state transition on the clone, as
`JWEBuilder::addRecipient()` already does.

Fixes #679
The "release" step runs `git checkout <release branch>`, which is what makes
that branch available locally. The four following commands need it, but each
one used to live in its own job with its own `actions/checkout`, so they got a
fresh clone positioned on the default branch instead. Releasing from any branch
other than the default one therefore failed with "not a valid object name".

Keeping the five commands as steps of the same job preserves the working tree
between them.
`JWEBuilder::withSenderKey()` derived the key management mode and checked the
key against it, so it could not be used with ECDH-SS: called before
`addRecipient()` the content encryption algorithm was still unknown, and called
after it the "agree" mode was rejected as a foreign key management mode. The
sender key does not add a recipient: it no longer takes part in the
compatibility check and is verified by `build()`, once the recipients and the
content encryption algorithm are known whatever the call order is.

`determineCEK()` read the sender key from a per-recipient entry that is never
written, so a direct key agreement always ended up with no sender key at all. It
now falls back to the sender key of the builder, as `processRecipient()` does.

`JWEDecrypter::decryptUsingKey()` passed the sender key as the fourth argument
of `decryptUsingKeySet()`, which is the output key parameter: the sender key
never reached the algorithm and such a token could not be decrypted back.

Closes #680
JWKSet indexed its keys by "kid", so two keys carrying the same one
overwrote each other and the second silently won. RFC7517 section 4.5
explicitly allows a key set to hold several keys with the same "kid",
typically an RSA key and an EC key considered as equivalent
alternatives by the application.

Keys carrying an already used "kid" are now appended to the key set
instead of replacing the stored one, and "kid" lookups fall back to a
scan so that those extra keys stay reachable through get(), has() and
without(). The indexing logic that was duplicated in the constructor,
createFromKeyData() and with() now lives in a single place.

Fixes #682
fix(signature): apply the payload encoding to the clone, not the receiver
fix(encryption): allow a sender key with a static key agreement
fix(core): keep every key of a set sharing the same "kid"
`JWEBuilder::withSharedProtectedHeader()` and `JWEBuilder::withSharedHeader()`
called `getHeader()` on the already registered recipients, but `addRecipient()`
stores plain arrays. Setting a shared header after a recipient therefore raised
a fatal `Error` instead of running the duplicated-header-parameter check.

Closes #678
The loaders, the verifier, the decrypter and the serializer managers all
swallowed the exception explaining why a token could not be used, and the
caller was left with a bare "Unable to load and verify the token." with no
previous exception.

The last error met along the way is now chained as the previous exception. The
per-key failures of JWSVerifier and JWEDecrypter, which cannot throw without
changing the return semantics, are reported through a callable accepted as an
additional argument; it will become part of the signature in 5.0.0.

Closes #681
fix(core): keep the cause of a load or verification failure
…after-recipient

fix(encryption): read the recipient header from the builder state
@Spomky Spomky self-assigned this Aug 28, 2026
@Spomky
Spomky merged commit ea8000d into 4.3.x Aug 28, 2026
18 of 19 checks passed
@Spomky
Spomky deleted the 4.2.x-merge-up-into-4.3.x_ZRaIehPF branch August 28, 2026 17:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant