Skip to content

Add Jwe module (RFC 7516) ported from the upstream JOSE PR - #4

Merged
leonitousconforti merged 1 commit into
mainfrom
feat/jwe
Jul 28, 2026
Merged

Add Jwe module (RFC 7516) ported from the upstream JOSE PR#4
leonitousconforti merged 1 commit into
mainfrom
feat/jwe

Conversation

@leonitousconforti

Copy link
Copy Markdown
Owner

Ports the JWE module from Effect-TS/effect#6566 at its latest commit (35830ea0), so all of that PR's JWE security hardening is included. Complements #3, which ported the PR's fixes for the modules that already existed here.

Changes

  • src/Jwe.ts (new) — JWE Compact Serialization (RFC 7516): encrypt/decrypt built on WebCrypto, ProtectedHeader and Compact schemas, and a typed JweError. Content encryption: A128/192/256GCM and A128CBC-HS256/A192CBC-HS384/A256CBC-HS512. Key management: dir, RSA-OAEP(-256), A*KW, A*GCMKW, ECDH-ES (direct and key-wrap), and PBES2. RSA1_5 is intentionally unsupported — WebCrypto does not implement it and RFC 8725 discourages it.
  • src/Jwa.ts — add JweAlgorithm, JweEncryption, and encryptionParameters (RFC 7518 Sections 4–5).
  • src/index.ts — regenerated (pnpm codegen) to export Jwe.
  • test/Jwe.test.ts (new) — round-trips all 16×6 alg × enc combinations, extra protected-header parameters, tampered-ciphertext and tampered-CBC-HMAC-tag rejection, wrong-key failure, and the RFC 7516 Appendix A.3 vector as external ground truth.
  • test/Security.test.ts — port the upstream JWE hardening regressions: PBES2 iteration-count bound (DoS guard), alg/enc allowlists, unrecognized crit rejection, typed Malformed on bad base64url, ECDH-ES apu/apv bound into the KDF, dir key-length mismatch, wrong-length CEK failing closed, and a non-exportable dir key failing closed.
  • Changeset (minor).

Security posture carried over from upstream

  • Every attacker-reachable crypto call on the decrypt path fails closed with a typed JweError — never an unhandled defect.
  • Unrecognized crit extensions are rejected (RFC 7516 §4.1.13).
  • The attacker-controlled PBES2 p2c is bounded (1000–10000 by default) before the expensive derivation runs (RFC 8725).
  • The unwrapped CEK's length is validated before it reaches AES importKey.
  • The ECDH-ES epk is imported on the recipient's own curve; WebCrypto validates the point lies on it, defeating invalid-curve attacks.
  • Constant-time CBC-HMAC tag comparison.

Adaptation notes

Imports go through the effect barrel instead of the monorepo's relative paths, docs use @since 1.0.0 with @see RFC links, tests use this repo's it.live + expect conventions, and the upstream header.p2c! assertion became a narrowed local. Test helpers take Uint8Array<ArrayBuffer> (TS 6 flags the ArrayBufferLike default against BufferSource).

Verification

pnpm check, pnpm lint, pnpm circular, pnpm build, and pnpm test all pass (44/44, including the 29 new JWE tests).

@leonitousconforti
leonitousconforti merged commit 0fa7f8b into main Jul 28, 2026
1 check passed
@leonitousconforti
leonitousconforti deleted the feat/jwe branch July 28, 2026 16:38
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