Home Supported Standards Terms & Conditions Privacy Policy Documentation Contact About

← Return to debugger  |  Encryption / Decryption →

Generate key pairs, sign any value, and validate signatures — all in your browser. Three panes are post-quantum: pane 1 is SLH-DSA (FIPS 205, formerly SPHINCS+), pane 4 is ML-DSA (FIPS 204, formerly CRYSTALS-Dilithium), and pane 5 is Composite ML-DSA, which pairs ML-DSA with ECDSA or EdDSA so that a break of either leaves the other holding. Panes 1 and 4 also offer the context string and the pre-hash variants (HashML-DSA / HashSLH-DSA), which are different algorithms rather than options. Pane 2 uses RSA (PKCS#1 v1.5 and PSS); pane 3 uses ECC (ECDSA over P-256/P-384/P-521/secp256k1, EdDSA over Ed25519/Ed448, Schnorr over secp256k1, and BLS over BLS12-381); pane 6 uses BBS over BLS12-381 (both ciphersuites), which signs a list of messages and can derive an unlinkable proof over any subset of them. Panes 7 and 8 are about an envelope rather than a primitive: pane 7 is JWS (RFC 7515) over a JSON payload — every registered algorithm including all eleven post-quantum ones, all three serializations, detached and unencoded payloads; pane 8 is the W3C XML Digital Signature — enveloped, enveloping and detached, four canonicalization methods, and a configurable transform chain. Both refuse to sign input that does not parse. The RSA and ECDSA panes let you pair the signature with a wide range of hash algorithms — SHA-2, SHA-3, BLAKE2b, BLAKE3, and the legacy RIPEMD-160 / SHA-1 / MD5. Those eight panes are digital signature panes (the JWS and XML ones can also carry an HMAC, which is not one); the panes below them are symmetric MACs (keyed-hash: HMAC / KMAC / keyed-BLAKE; block-cipher: AES-CMAC / CBC-MAC / GMAC; universal-hash: Poly1305 / SipHash), labelled separately because a MAC uses a shared secret and is not a true digital signature. No key material is stored: keys live only in this page and are never written to local storage.

Which of these is actually standardised, and which is a draft. Post-quantum cryptography is not one thing yet, and this page marks the difference rather than blurring it. Published: the primitives ML-DSA (FIPS 204), SLH-DSA (FIPS 205) and their pre-hash variants, and ML-DSA’s JOSE binding, RFC 9964. Draft: SLH-DSA in JOSE (draft-ietf-cose-sphincs-plus-10, which registers only two of the twelve parameter sets) and the composite algorithms (draft-ietf-jose-pq-composite-sigs-03). Every pane resting on a draft carries a red Draft standard badge and names the revision it implements. Absent, for two different reasons. FN-DSA (Falcon) has a specification — draft-ietf-cose-falcon-04 registers FN-DSA-512 and FN-DSA-1024 — but no implementation this page can load: the library that provides Falcon is ESM-only and this client is bundled as CommonJS, and the alternative on npm is an unmaintained WASM wrapper not worth adding to a security tool for an algorithm whose FIPS 206 is still unpublished. HQC, which NIST selected in March 2025 as the backup KEM, has the opposite problem: no draft FIPS, no IETF binding and no implementation at all, so adding it would mean inventing a wire format — the one thing a debugger must never do. Also absent: any post-quantum XML Signature, because no algorithm URI has been registered for one.

Tip: click a pane's title to collapse/expand it.

SLH-DSA Digital Signature Asymmetric

Heads up: SLH-DSA runs entirely in JavaScript, so key generation and especially signing can take several seconds — the small-signature (s) and 256-bit parameter sets are the slowest. This is expected; give each operation a moment to finish.

Key Pair
Variant — context string and pre-hash

These two controls select a different algorithm, not an option on this one. A context string (FIPS 205 §10.2) is mixed into the formatted message, so a signature made for one application cannot be replayed into another — a verifier using a different context, or none, will refuse it. A pre-hash selects HashSLH-DSA (FIPS 205 §10.2.2), which signs a digest of the message and puts the hash function’s OID into the signed bytes; a pure verifier will not accept a pre-hashed signature or vice versa. RFC 9964 requires the context to be EMPTY for the JOSE algorithms, so a non-empty context here is a raw-primitive feature and the JWS pane below does not offer it.

Stateful Hash-Based Signatures — LMS/HSS and XMSS/XMSS^MT Asymmetric Post-quantum Stateful

The private key below changes every time you sign, and that is the whole subject. These are the two schemes NIST SP 800-208 approves — LMS/HSS (RFC 8554, with RFC 9858's SHA-256/192 and SHAKE256 parameter sets) and XMSS/XMSS^MT (RFC 8391, with SP 800-208's). Like SLH-DSA above they are Merkle trees over one-time signatures and secure if the hash function is; unlike it they are stateful, so the signer must remember which one-time keys it has spent. Spend one twice on different messages and an attacker gets the material to forge a third — which is why SP 800-208 §1 restricts these to places where the state can be guaranteed, firmware signing above all, and why RFC 8554 §5.4.1 requires the new index to reach storage before the signature is released. The pane keeps the index in the private key box and rewrites it on every Sign.

⏳ Why some parameter sets say “verify only here”. Generating a key means building a whole tree, and every leaf of it is a full one-time key pair — 220 of them for LMS_SHA256_M32_H20, which is hours in any language and days in a browser. Verification is untouched by this: it hashes one authentication path, so every parameter set in both registries verifies and describes here at once. That gap is also the entire argument for the multi-tree variants, and you can watch it: XMSS-SHA2_20_256 cannot be generated at all, while XMSSMT-SHA2_20/4_256 reaches the same 220 signatures out of trees of 32 leaves and generates in a fraction of a second.

Scheme & parameter set
Key pair — and its remaining state

Both specifications define the public key and the signature to the byte and leave the private key to the implementation (RFC 8554 §5.2, RFC 8391 §4.1.3), because nothing interoperable depends on it. What is below is therefore this tool's own format — a seed and an index, tagged LMSK or XMSK so it can never be mistaken for something another tool reads. The public key and the signature are the standard encodings exactly.

What happens if one index is used twice

This is the failure SP 800-208 exists to prevent, on demand. It signs the Value and the second value below from the same index and leaves the key's index untouched. Both signatures verify — nothing about either is detectably wrong to a verifier, which is exactly why the rule has to be enforced at the signer. What an attacker holds afterwards is two Winternitz chains revealed at two different heights, which is the material a forgery on a third message is built from. Use it on this throwaway key; never let it happen to a real one.

RSA Digital Signature Asymmetric

Pick a padding scheme and any hash. Hashes marked legacy/insecure/broken are supported for interop/testing only — don't use them for real signatures. BLAKE2b-512 and BLAKE3-256 have no PKCS#1 v1.5 identifier, so use PSS with them.

Key Pair
ECC Digital Signature Asymmetric

ECDSA over any curve can use any hash. EdDSA (Ed25519 / Ed448), Schnorr (BIP-340) and BLS (BLS12-381) hash the message themselves, so the Hash selection is ignored for those. Schnorr and BLS keys export only as hex (no standard JWK). Hashes marked legacy/insecure/broken are for interop/testing only.

Key Pair
ML-DSA Digital Signature Asymmetric

Post-quantum ML-DSA (FIPS 204, formerly CRYSTALS-Dilithium). The primary NIST post-quantum signature standard; fast lattice-based signing. Its JOSE and COSE binding is RFC 9964 — a published standard, not a draft.

🔑 The private key here is the 32-byte SEED, not the expanded key. RFC 9964 §3.2 requires an ML-DSA JWK’s priv parameter to be the seed, and the expanded 2560/4032/4896-byte signing key is re-derived from it on every use. That is why the Private Key box is short. A JWK carrying the expanded key is readable by almost nothing.

Key Pair
Variant — context string and pre-hash

These two controls select a different algorithm, not an option on this one. A context string (FIPS 204 §5.2) is mixed into the formatted message, so a signature made for one application cannot be replayed into another — a verifier using a different context, or none, will refuse it. A pre-hash selects HashML-DSA (FIPS 204 §5.4), which signs a digest of the message and puts the hash function’s OID into the signed bytes; a pure verifier will not accept a pre-hashed signature or vice versa. RFC 9964 requires the context to be EMPTY for the JOSE algorithms, so a non-empty context here is a raw-primitive feature and the JWS pane below does not offer it.

Composite ML-DSA Signature Asymmetric PQ/T hybrid Draft standard

Draft standard — draft-ietf-jose-pq-composite-sigs-03. The combiner and the domain-separation labels below are taken verbatim from that revision; the JOSE algorithm names have no IANA assignment yet. The sibling document for X.509 is draft-ietf-lamps-pq-composite-sigs, which differs from this one in how the ECDSA component is encoded.

A composite signature is one signature made of two: an ML-DSA signature and a traditional ECDSA or EdDSA one, over the same message, verified together. It exists because nobody yet wants to bet a long-lived signature on lattices alone — the composite stays valid if either component survives, so a break of ML-DSA leaves ECDSA holding and a quantum computer leaves ML-DSA holding. Both halves must verify. If only one did, the construction would be strictly worse than the stronger component on its own.

The signed message is M’ = Prefix || Label || 0x00 || PH(M), where Prefix is the ASCII “CompositeAlgorithmSignatures2025”, Label identifies the exact combination, 0x00 encodes an empty application context as a length (it is not a string terminator), and PH is the per-algorithm pre-hash. The label is then used a second time as the ML-DSA context, which is what stops a component signature being lifted out of a composite and replayed as a standalone ML-DSA signature. The signature is the ML-DSA signature followed by the traditional one, both fixed length.

Key Pair
BBS Digital Signature Asymmetric Selective disclosure

BBS over BLS12-381 (draft-irtf-cfrg-bbs-signatures), the same implementation the SD-JWT VC workflow uses for bbs-2023. It signs an ordered list of messages rather than one value, and the holder can then derive a proof that reveals only the messages they choose — each derivation is freshly randomised, so two proofs from one signature are unlinkable. Both ciphersuites the draft defines are here; they differ in more than a hash name (XMD/SHA-256 vs XOF/SHAKE-256, and each has its own fixed P1), so a key and a signature belong to one suite. Octet-string inputs — messages, header, presentation header, key info, key DST — are read as UTF-8 text or as hex, per the selector below; choose hex to reproduce the draft's own test vectors.

Key Pair
Derived Proof (selective disclosure)
JWS — JSON Web Signature Asymmetric or MAC

RFC 7515 over a JSON payload, with every algorithm the JOSE registry defines: HS* (RFC 7518 §3.2), RS*, PS*, ES*, EdDSA over Ed25519 and Ed448 (RFC 8037), ES256K (RFC 8812) and the unsecured none. Only HS256 is Required; RS256 and ES256 are Recommended and everything else is Optional — each option below says which. The signature covers BASE64URL(header) + "." + BASE64URL(payload), so the payload's own whitespace is inside the signature: this pane never reformats it for you. Sign refuses a payload that is not well-formed JSON. Note HS* is a MAC with a shared secret — a JWS, but not a digital signature.

Algorithm & Serialization

       

Key
XML Digital Signature Asymmetric or MAC

No post-quantum algorithms are offered here, and that is not a gap in this page. The panes above sign with ML-DSA, SLH-DSA, FN-DSA and the PQ/T composites, and the JWS pane offers all thirteen as alg values — but no post-quantum algorithm URI has been registered for XML Signature by W3C or IANA, and none is proposed in any draft. There is therefore nothing to put in a <SignatureMethod Algorithm="…">, and inventing one would produce a document that no other implementation could ever read. When such a URI is registered it belongs here; until then this pane stops at RSASSA-PSS.

W3C XMLDSIG (RFC 3275) over an XML document, using the same in-browser engine the SAML, WS-Trust and WS-Federation workflows sign with. All three signature types are here — enveloped (the Signature goes inside the document), enveloping (the document goes inside a ds:Object in the Signature), detached (the Signature stands alone and names what it covers). Sign refuses XML that is not well-formed, and nothing here rewrites your input: a signature covers the exact octets that get canonicalized, so any "cleaning" would invalidate what it is about to produce. The transforms are an ordered chain and are applied in the order shown below the fields — a canonicalization ends the chain. HMAC-* is a MAC with a shared secret, not a digital signature. C14N 1.1 is not offered: its whole difference from 1.0 is xml:base inheritance, which this engine does not implement, and naming a method it does not perform would be worse than leaving it out.

Signature
Transforms — applied in this order: enveloped-signature → XPath → base64 → canonicalization

 

Key Pair & KeyInfo
Keyed-Hash MACs Symmetric (MAC)

A MAC authenticates with a single shared secret — it proves integrity and origin but gives no non-repudiation (both parties hold the same key), so it is not a digital signature. Compute a tag, or Verify a pasted tag.

Secret Key
Block-Cipher MACs Symmetric (MAC)

AES-based MACs. AES-CBC-MAC is legacy (insecure for variable-length messages). AES-GMAC here uses a fixed all-zero nonce for a deterministic demo tag — real GMAC needs a unique nonce per message.

Secret Key
Universal-Hash MACs Symmetric (MAC)

Poly1305 is a one-time authenticator — its 32-byte key must be unique per message. UMAC, VMAC, and PMAC are not offered: no maintained pure-JS implementation exists.

Secret Key