OpenSSL Studio / API Security & JWT Workshop

What you will do: Open seven sections: inspect a JWT, sign one with ML-DSA or SLH-DSA, build a composite ML-DSA-65+Ed25519 JWT, encrypt a payload as an HPKE JWE with ML-KEM-768 or the X25519 hybrid, compare token sizes, run the JOSE known-answer audit, and attack a JWT verifier in the Attack Lab.

Worked example: In PQC JWT Signing pick ML-DSA-65 on the @noble/post-quantum backend, Generate Keypair, sign the sample payload for Alice Engineer, then Verify (noble) reports Signature valid with the token's byte sizes.

Runtime and privacy: The cryptographic exercise runs in this browser. Review the site privacy terms before entering sensitive material; use synthetic inputs for learning and evaluation.

Browse all Crypto Lab tools · Learn with API Security & JWT

For your role

Developer / Engineer
Choose ML-DSA-44, 65 or 87 or an SLH-DSA set, pick the signing backend (@noble/post-quantum or SoftHSM3), Generate Keypair and Sign JWT: the editable payload and the resulting header show what your issuer and verifier will handle.
Security Architect
Step 3 offers two hybrid patterns, a Nested JWT and a Composite MLDSA65-Ed25519 signature: which verifiers accept each is the migration decision, and Step 4's ML-KEM-768 JWE shows encrypted tokens.
Researcher / Academic
Run the API Security JWT Known Answer Tests panel, then sign the same payload with each algorithm and backend to compare signature sizes and the composite encoding against the JOSE drafts.
Full API Security & JWT workshop — real PQC signing (ML-DSA, SLH-DSA, composite) and HPKE-based ML-KEM JWE encryption, which can run entirely inside softhsmv3 via PKCS#11 CKM_HPKE. Open the full learn module for guided walkthroughs and quizzes.

Real PQC JWT Signing

Generate a real ML-DSA keypair, sign a JWT over the canonical signing input b64u(header).b64u(payload), and verify the compact JWS — all in your browser. Algorithm codes follow RFC 9964 (ML-DSA for JOSE and COSE, published May 2026). SLH-DSA codes follow draft-ietf-cose-sphincs-plus-10 and composite codes draft-ietf-jose-pq-composite-sigs-04 — both still Internet-Drafts.

Signing backend

Keypair Generation

Scope note: RFC 9964 §7.2 explicitly excludes HashML-DSA (FIPS 204 §5.4) from JOSE/COSE — this workshop only exposes the pure-mode variants accordingly.

JWT Payload (Editable)

Educational use only. The signing input is b64u(JOSE header).b64u(payload) per RFC 7515 §5.1. Both noble and SoftHSM3 produce byte-identical signatures over the same input — a token signed via one backend verifies under the other, demonstrating that RFC 9964 interoperates across implementations.

API Security JWT Known Answer Tests

RFC 9964 · FIPS 203 · FIPS 204

Click Run validation tests to run 4 use-case scenarios. Evidence in this set: NIST ACVP-Server reference sample — Expected values copied from the public NIST ACVP-Server repository with immutable source identity.; Functional round-trip — Output produced by an implementation is consumed by the same or paired implementation..

Reference samples from the public NIST ACVP-Server repository · RFC 9964 · FIPS 203 · FIPS 204 · Generated keys are for educational use only.

Hybrid JWT Creation

During the PQC transition, a hybrid JWT combines a classical and a PQC signature so the token stays secure if either algorithm fails. Composite mode follows draft-ietf-jose-pq-composite-sigs-04 and verifies against that draft's published examples; it is a work-in-progress Internet-Draft, so treat this tab as experimental.

Signing backend

Nested JWT Creation Flow

Step 1
ES256 Inner Sign
Step 2
ML-DSA-65 Outer Sign
Step 3
Assemble nested token

Key insight: Neither approach lets an unmodified classical verifier accept the token on its own. Nested mode can serve one only if a gateway or protocol you define unwraps the inner JWT, and that path carries no PQC protection, so it must be retired on a schedule. Composite mode needs every verifier upgraded to draft-ietf-jose-pq-composite-sigs, but yields one token (3,309 B ML-DSA-65 + 64 B Ed25519 signature) that stays secure while either algorithm holds. Either way, the verifier's algorithm allowlist is what stops a downgrade to the classical-only path.

JWE Encryption with HPKE experimental · draft-ietf-jose-hpke-pq-pqt-01

Post-quantum JWE runs through HPKE. draft-ietf-jose-hpke-encrypt (in the RFC Editor queue) defines how HPKE carries a JWE, and draft-ietf-jose-hpke-pq-pqt-01 registers the ML-KEM suites used here. All operations run real crypto in your browser, and the code is checked against the examples published in that draft. It is still an early working-group draft, so the algorithm names may change — not a format to deploy yet. An earlier direct-KEM design (draft-ietf-jose-pqc-kem) was dropped for JOSE in 2026.

HPKE suite ("alg")

Both use the SHAKE256 KDF and AES-256-GCM. The hybrid keeps a classical X25519 component, so a flaw found in ML-KEM alone would not expose the payload.

KEM backend

The browser path runs @noble/post-quantum (ML-KEM, X-Wing) and @noble/hashes (SHAKE256) inside the hpke package.

JWE Compact Serialization (5 parts)

Header.Encrypted Key.IV (empty).Ciphertext.Tag (empty)

JWE keeps its 5 parts. In HPKE Integrated Encryption the Encrypted Key carries the HPKE encapsulated secret (1,088 bytes for HPKE-12), and the IV and Tag stay empty because HPKE manages its own nonce and puts the GCM tag inside the ciphertext.

1. Generate ML-KEM-768 Keypair

The recipient generates a ML-KEM-768 keypair and publishes the public key (1,184 bytes) as an "AKP" JWK with "alg": "HPKE-12". The private key is a 64-byte seed.

Encryption Pipeline

1
2
3
4

Check against the draft's published example

draft-ietf-jose-hpke-pq-pqt-01 Appendix A publishes, for each algorithm, a private key and a JWE made by the draft authors with a different ML-KEM implementation. Decrypting it here shows this code interoperates with theirs, not just with itself. With the SoftHSM3 backend the published private key is imported into the token and the example is opened there.

Key insight: moving JWE to post-quantum changes the key-establishment step, not the token format. HPKE packages "encapsulate a key, derive a symmetric key, encrypt" as one standard operation, so the same JWE layout works for classical ECDH suites (HPKE-0 to HPKE-7) and for ML-KEM. What does change is size: the 1,088-byte encapsulated secret makes every encrypted token roughly 1.5 KB larger than its plaintext.

Try it

Create a Nested JWT in Step 3. Who validates what?

Next step

Turn it into a plan: Hybrid Transition Planner

This tool practises the API Security & JWT module, phase 5 (Pilots & Migration); Hybrid Transition Planner produces a deliverable of that phase.