# @suaveplan/jws - RFC 7515 JSON Web Signature (verify + sign). Compact, JSON-flattened, and JSON-general (multi-signature) serializations; HS/RS/PS/ES/EdDSA algorithms; JWK + x5c + kid key resolution; crit allowlist enforcement; detached payload (§A.5); RFC 7797 b64 header support. ## Summary RFC 7515 **JSON Web Signature** (verify + sign). Pure TypeScript over `Uint8Array` + `DataView` plus the workspace crypto primitives (`@suaveplan/crypto-rsa`, `@suaveplan/crypto-curve`, `@suaveplan/crypto-hash`, `@suaveplan/crypto-utils`) and `@suaveplan/x509` for `x5c` chain validation. Zero browser globals, zero Node built-ins, zero external JOSE/JWT/jws-npm dependencies. ## Documentation tree - [builtin](./src/algorithms/builtin.md) — Seeds the default `AlgorithmRegistry` with the 13 built-in algorithm implementations required by RFC 7518 §3 and RFC 80… - [ecdsa](./src/algorithms/ecdsa.md) — RFC 7518 §3.4 ECDSA signing and verification over NIST P-256, P-384, and P-521. The signing input is hashed with the cu… - [eddsa](./src/algorithms/eddsa.md) — RFC 8037 §3.1 EdDSA over Ed25519. The signing input is signed directly by Ed25519 (no caller-side pre-hash — Ed25519 ha… - [hmac](./src/algorithms/hmac.md) — RFC 7518 §3.2 HMAC-with-SHA-2 signing and verification. The signing input is HMAC'd with the caller-supplied symmetric… - [none](./src/algorithms/none.md) — RFC 7518 §3.6 `"none"` algorithm. The `none` value declares "no integrity protection," which is virtually never what a… - [registry](./src/algorithms/registry.md) — In-package mapping from `alg` identifier to the concrete `AlgorithmImpl` that knows how to verify and (optionally) sign… - [rsa-pss](./src/algorithms/rsa-pss.md) — RFC 7518 §3.5 RSASSA-PSS signing and verification. The signing input is hashed, EMSA-PSS-encoded with a random salt, an… - [rsa](./src/algorithms/rsa.md) — RFC 7518 §3.3 RSASSA-PKCS1-v1_5 signing and verification. The signing input is hashed with SHA-256/SHA-384/SHA-512 resp… - [base64url](./src/base64url/base64url.md) — _(no submodules)_ - [base64url](./src/base64url/base64url.md) — _(no submodules)_ - [detached](./src/detached/detached.md) — _(no submodules)_ - [detached](./src/detached/detached.md) — _(no submodules)_ - [errors](./src/errors/error-codes.md) — _(no submodules)_ - [error-codes](./src/errors/error-codes.md) — _(no submodules)_ - [header](./src/header/header.md) — _(no submodules)_ - [b64](./src/header/b64.md) — RFC 7797 §3 implements the `b64` header parameter, allowing JWS producers to embed unencoded payloads directly into the… - [crit](./src/header/crit.md) — RFC 7515 §4.1.11 enforcement: every entry in `header.crit` MUST be in the caller's `acceptableCriticalHeaders` allowlis… - [header](./src/header/header.md) — _(no submodules)_ - [jwk](./src/keys/jwk.md) — Parse an RFC 7517 §4 / RFC 7518 §6 JSON Web Key into the typed key shape expected by the JWS algorithm impl for the dec… - [resolver](./src/keys/resolver.md) — Caller-supplied key-resolution function consulted when `header.kid` is present and no key has been supplied via `opts.k… - [x5c](./src/keys/x5c.md) — Decode an RFC 7515 §4.1.6 `x5c` certificate chain, delegate trust-path validation to `@suaveplan/x509.validateChain`, a… - [observability](./src/observability/metrics.md) — _(no submodules)_ - [metrics](./src/observability/metrics.md) — _(no submodules)_ - [schemas](./src/schemas/schemas.md) — _(no submodules)_ - [schemas](./src/schemas/schemas.md) — _(no submodules)_ - [compact](./src/serialization/compact/compact.md) — _(no submodules)_ - [compact](./src/serialization/compact/compact.md) — _(no submodules)_ - [flat](./src/serialization/flat/flat.md) — _(no submodules)_ - [flat](./src/serialization/flat/flat.md) — _(no submodules)_ - [general](./src/serialization/general/general.md) — _(no submodules)_ - [general](./src/serialization/general/general.md) — _(no submodules)_ - [sign](./src/sign/sign-pipeline.md) — _(no submodules)_ - [sign-pipeline](./src/sign/sign-pipeline.md) — _(no submodules)_ - [verify](./src/verify/verify-pipeline.md) — _(no submodules)_ - [verify-pipeline](./src/verify/verify-pipeline.md) — _(no submodules)_ - [base64url](./src/base64url/base64url.md) — _(no submodules)_- [detached](./src/detached/detached.md) — _(no submodules)_- [detached](./src/detached/detached.md) — _(no submodules)_- [errors](./src/errors/error-codes.md) — _(no submodules)_- [error-codes](./src/errors/error-codes.md) — _(no submodules)_- [header](./src/header/header.md) — _(no submodules)_- [b64](./src/header/b64.md) — RFC 7797 §3 implements the `b64` header parameter, allowing JWS producers to embed unencoded payloads directly into the… - [crit](./src/header/crit.md) — RFC 7515 §4.1.11 enforcement: every entry in `header.crit` MUST be in the caller's `acceptableCriticalHeaders` allowlis… - [header](./src/header/header.md) — _(no submodules)_- [jwk](./src/keys/jwk.md) — Parse an RFC 7517 §4 / RFC 7518 §6 JSON Web Key into the typed key shape expected by the JWS algorithm impl for the dec… - [resolver](./src/keys/resolver.md) — Caller-supplied key-resolution function consulted when `header.kid` is present and no key has been supplied via `opts.k… - [x5c](./src/keys/x5c.md) — Decode an RFC 7515 §4.1.6 `x5c` certificate chain, delegate trust-path validation to `@suaveplan/x509.validateChain`, a… - [observability](./src/observability/metrics.md) — _(no submodules)_- [metrics](./src/observability/metrics.md) — _(no submodules)_- [schemas](./src/schemas/schemas.md) — _(no submodules)_- [schemas](./src/schemas/schemas.md) — _(no submodules)_- [compact](./src/serialization/compact/compact.md) — _(no submodules)_- [compact](./src/serialization/compact/compact.md) — _(no submodules)_- [flat](./src/serialization/flat/flat.md) — _(no submodules)_- [flat](./src/serialization/flat/flat.md) — _(no submodules)_- [general](./src/serialization/general/general.md) — _(no submodules)_- [general](./src/serialization/general/general.md) — _(no submodules)_- [sign](./src/sign/sign-pipeline.md) — _(no submodules)_- [sign-pipeline](./src/sign/sign-pipeline.md) — _(no submodules)_- [verify](./src/verify/verify-pipeline.md) — _(no submodules)_- [verify-pipeline](./src/verify/verify-pipeline.md) — _(no submodules)_- [base64url](./src/base64url/base64url.md) — _(no submodules)_- [detached](./src/detached/detached.md) — _(no submodules)_- [detached](./src/detached/detached.md) — _(no submodules)_- [errors](./src/errors/error-codes.md) — _(no submodules)_- [error-codes](./src/errors/error-codes.md) — _(no submodules)_- [header](./src/header/header.md) — _(no submodules)_- [b64](./src/header/b64.md) — RFC 7797 §3 implements the `b64` header parameter, allowing JWS producers to embed unencoded payloads directly into the… - [crit](./src/header/crit.md) — RFC 7515 §4.1.11 enforcement: every entry in `header.crit` MUST be in the caller's `acceptableCriticalHeaders` allowlis… - [header](./src/header/header.md) — _(no submodules)_- [jwk](./src/keys/jwk.md) — Parse an RFC 7517 §4 / RFC 7518 §6 JSON Web Key into the typed key shape expected by the JWS algorithm impl for the dec… - [resolver](./src/keys/resolver.md) — Caller-supplied key-resolution function consulted when `header.kid` is present and no key has been supplied via `opts.k… - [x5c](./src/keys/x5c.md) — Decode an RFC 7515 §4.1.6 `x5c` certificate chain, delegate trust-path validation to `@suaveplan/x509.validateChain`, a… - [observability](./src/observability/metrics.md) — _(no submodules)_- [metrics](./src/observability/metrics.md) — _(no submodules)_- [schemas](./src/schemas/schemas.md) — _(no submodules)_- [schemas](./src/schemas/schemas.md) — _(no submodules)_- [compact](./src/serialization/compact/compact.md) — _(no submodules)_- [compact](./src/serialization/compact/compact.md) — _(no submodules)_- [flat](./src/serialization/flat/flat.md) — _(no submodules)_- [flat](./src/serialization/flat/flat.md) — _(no submodules)_- [general](./src/serialization/general/general.md) — _(no submodules)_- [general](./src/serialization/general/general.md) — _(no submodules)_- [sign](./src/sign/sign-pipeline.md) — _(no submodules)_- [sign-pipeline](./src/sign/sign-pipeline.md) — _(no submodules)_- [verify](./src/verify/verify-pipeline.md) — _(no submodules)_- [verify-pipeline](./src/verify/verify-pipeline.md) — _(no submodules)_- [base64url](./src/base64url/base64url.md) — _(no submodules)_- [detached](./src/detached/detached.md) — _(no submodules)_- [detached](./src/detached/detached.md) — _(no submodules)_- [errors](./src/errors/error-codes.md) — _(no submodules)_- [error-codes](./src/errors/error-codes.md) — _(no submodules)_- [header](./src/header/header.md) — _(no submodules)_- [b64](./src/header/b64.md) — RFC 7797 §3 implements the `b64` header parameter, allowing JWS producers to embed unencoded payloads directly into the… - [crit](./src/header/crit.md) — RFC 7515 §4.1.11 enforcement: every entry in `header.crit` MUST be in the caller's `acceptableCriticalHeaders` allowlis… - [header](./src/header/header.md) — _(no submodules)_- [jwk](./src/keys/jwk.md) — Parse an RFC 7517 §4 / RFC 7518 §6 JSON Web Key into the typed key shape expected by the JWS algorithm impl for the dec… - [resolver](./src/keys/resolver.md) — Caller-supplied key-resolution function consulted when `header.kid` is present and no key has been supplied via `opts.k… - [x5c](./src/keys/x5c.md) — Decode an RFC 7515 §4.1.6 `x5c` certificate chain, delegate trust-path validation to `@suaveplan/x509.validateChain`, a… - [observability](./src/observability/metrics.md) — _(no submodules)_- [metrics](./src/observability/metrics.md) — _(no submodules)_- [schemas](./src/schemas/schemas.md) — _(no submodules)_- [schemas](./src/schemas/schemas.md) — _(no submodules)_- [compact](./src/serialization/compact/compact.md) — _(no submodules)_- [compact](./src/serialization/compact/compact.md) — _(no submodules)_- [flat](./src/serialization/flat/flat.md) — _(no submodules)_- [flat](./src/serialization/flat/flat.md) — _(no submodules)_- [general](./src/serialization/general/general.md) — _(no submodules)_- [general](./src/serialization/general/general.md) — _(no submodules)_- [sign](./src/sign/sign-pipeline.md) — _(no submodules)_- [sign-pipeline](./src/sign/sign-pipeline.md) — _(no submodules)_- [verify](./src/verify/verify-pipeline.md) — _(no submodules)_- [verify-pipeline](./src/verify/verify-pipeline.md) — _(no submodules)_- [base64url](./src/base64url/base64url.md) — _(no submodules)_- [detached](./src/detached/detached.md) — _(no submodules)_ - [detached](./src/detached/detached.md) — _(no submodules)_- [errors](./src/errors/error-codes.md) — _(no submodules)_ - [error-codes](./src/errors/error-codes.md) — _(no submodules)_- [header](./src/header/header.md) — _(no submodules)_ - [b64](./src/header/b64.md) — RFC 7797 §3 implements the `b64` header parameter, allowing JWS producers to embed unencoded payloads directly into the… - [crit](./src/header/crit.md) — RFC 7515 §4.1.11 enforcement: every entry in `header.crit` MUST be in the caller's `acceptableCriticalHeaders` allowlis… - [header](./src/header/header.md) — _(no submodules)_- [jwk](./src/keys/jwk.md) — Parse an RFC 7517 §4 / RFC 7518 §6 JSON Web Key into the typed key shape expected by the JWS algorithm impl for the dec… - [resolver](./src/keys/resolver.md) — Caller-supplied key-resolution function consulted when `header.kid` is present and no key has been supplied via `opts.k… - [x5c](./src/keys/x5c.md) — Decode an RFC 7515 §4.1.6 `x5c` certificate chain, delegate trust-path validation to `@suaveplan/x509.validateChain`, a… - [observability](./src/observability/metrics.md) — _(no submodules)_ - [metrics](./src/observability/metrics.md) — _(no submodules)_- [schemas](./src/schemas/schemas.md) — _(no submodules)_ - [schemas](./src/schemas/schemas.md) — _(no submodules)_- [compact](./src/serialization/compact/compact.md) — _(no submodules)_ - [compact](./src/serialization/compact/compact.md) — _(no submodules)_- [flat](./src/serialization/flat/flat.md) — _(no submodules)_ - [flat](./src/serialization/flat/flat.md) — _(no submodules)_- [general](./src/serialization/general/general.md) — _(no submodules)_ - [general](./src/serialization/general/general.md) — _(no submodules)_- [sign](./src/sign/sign-pipeline.md) — _(no submodules)_ - [sign-pipeline](./src/sign/sign-pipeline.md) — _(no submodules)_- [verify](./src/verify/verify-pipeline.md) — _(no submodules)_ - [verify-pipeline](./src/verify/verify-pipeline.md) — _(no submodules)_ ## Install ```sh bun add @suaveplan/jws ``` ## Quick start ```ts import { compactSign, compactVerify } from "@suaveplan/jws"; const secret = new TextEncoder().encode("a-shared-32-byte-secret-pls-rotate"); const token = await compactSign("hello", secret, "HS256"); const result = await compactVerify(token, secret, { algorithms: ["HS256"] }); // result.payloadString === "hello" ``` ## Capabilities | Feature | Status | | -------------------------------- | ----------------------------------- | | RFC 7515 §3.1 compact form | ✓ | | RFC 7515 §7.2.2 JSON-flattened | ✓ | | RFC 7515 §7.2.1 JSON-general | ✓ (multi-signature) | | RFC 7515 §A.5 detached payload | ✓ | | RFC 7797 `b64: false` header | ✓ | | HS256 / HS384 / HS512 | ✓ (constant-time tag compare) | | RS256 / RS384 / RS512 | ✓ (`@suaveplan/crypto-rsa`) | | PS256 / PS384 / PS512 | ✓ (hash-length salt) | | ES256 / ES384 / ES512 | ✓ (`@suaveplan/crypto-curve`; DER rejected) | | EdDSA (Ed25519) | ✓ (RFC 8037) | | `alg: "none"` | ✓ (dual-flag opt-in only) | | Embedded `jwk` header | ✓ (`allowEmbeddedJwk: true`) | | Embedded `x5c` chain | ✓ (`@suaveplan/x509.validateChain`) | | `kid` resolver | ✓ (caller-supplied async fn) | | `crit` allowlist | ✓ | | AbortSignal end-to-end | ✓ | | Zod boundary at every entry | ✓ | | OpenTelemetry histograms+counters| ✓ | ## Security defaults - **Algorithm allowlist is mandatory at verify time.** There is no default — callers MUST pass `opts.algorithms`. Tokens whose `alg` is not on the list are rejected before any cryptography runs (defence against the JWT "alg confusion" CVE class). - **`alg: "none"` requires dual-flag opt-in.** Both `algorithms: ["none"]` AND `acceptNone: true` are required. - **`crit` parameters must be allowlisted.** Per RFC 7515 §4.1.11. - **ECDSA signatures must be fixed-length `R||S`.** DER-encoded signatures in the JOSE position throw `JWS.SIG_FORMAT_INVALID`. - **HMAC tag comparison is constant-time.** Via `@suaveplan/crypto-utils.constantTimeEqual`. - **PSS salt length is fixed at the hash output length.** Per RFC 7518 §3.5. ## Modules | Module | Doc | | --- | --- | | `base64url` | [`src/base64url/base64url.md`](src/base64url/base64url.md) | | Compact serialization | [`src/serialization/compact/compact.md`](src/serialization/compact/compact.md) | | Flat serialization | [`src/serialization/flat/flat.md`](src/serialization/flat/flat.md) | | General serialization | [`src/serialization/general/general.md`](src/serialization/general/general.md) | | Detached payload | [`src/detached/detached.md`](src/detached/detached.md) | | Header parse / serialize | [`src/header/header.md`](src/header/header.md) | | `crit` enforcement | [`src/header/crit.md`](src/header/crit.md) | | RFC 7797 `b64` | [`src/header/b64.md`](src/header/b64.md) | | Algorithm registry | [`src/algorithms/registry.md`](src/algorithms/registry.md) | | Built-in seeding | [`src/algorithms/builtin.md`](src/algorithms/builtin.md) | | HMAC (HS256/384/512) | [`src/algorithms/hmac.md`](src/algorithms/hmac.md) | | RSA-PKCS1-v1\_5 (RS\*) | [`src/algorithms/rsa.md`](src/algorithms/rsa.md) | | RSA-PSS (PS\*) | [`src/algorithms/rsa-pss.md`](src/algorithms/rsa-pss.md) | | ECDSA (ES\*) | [`src/algorithms/ecdsa.md`](src/algorithms/ecdsa.md) | | EdDSA (Ed25519) | [`src/algorithms/eddsa.md`](src/algorithms/eddsa.md) | | `alg: "none"` | [`src/algorithms/none.md`](src/algorithms/none.md) | | JWK → key | [`src/keys/jwk.md`](src/keys/jwk.md) | | `x5c` chain | [`src/keys/x5c.md`](src/keys/x5c.md) | | `KeyResolver` | [`src/keys/resolver.md`](src/keys/resolver.md) | | Verify pipeline | [`src/verify/verify-pipeline.md`](src/verify/verify-pipeline.md) | | Sign pipeline | [`src/sign/sign-pipeline.md`](src/sign/sign-pipeline.md) | | Error registry | [`src/errors/error-codes.md`](src/errors/error-codes.md) | | Schemas | [`src/schemas/schemas.md`](src/schemas/schemas.md) | | Metrics | [`src/observability/metrics.md`](src/observability/metrics.md) | ## License MIT.