- Home
- Lab
The lab · runs entirely in your browser
Sign it. Break it. See which validator notices.
Real ECDSA P-256 and ML-DSA-65 keys are generated in this tab. Sign a document, attack its post-quantum layer four ways, and compare what a classical validator reports with what Perennis reports.
Document
Or drop a file here. It is read in this tab and never sent anywhere.
Sign with both keys
- Generate throwaway keys
- Hash the document · SHA-256
- ECDSA P-256 signature
- ML-DSA-65 signature over the binding
- Bind the two layers
Tamper with it
Signature envelope
Classical validator
WaitingReads the ECDSA layer only, as an unmodified validator treats an attribute it has no rule for.
- ECDSA P-256 signature over the document
Perennis validator
WaitingAccepts only if every check passes: TS 119 312 V2.1.1 §6.4.1.
- ECDSA P-256 signature over the document
- Post-quantum layer present
- ML-DSA-65 signature valid for the signer’s key
- Layer bound to this document and this ECDSA signature
Event log
The lab needs a current browser and a secure connection (https or localhost) for the Web Cryptography API. The rest of the site works without it.
Read this before you draw conclusions
What is real here, and what is simplified.
Real
- The keys and signatures. ECDSA P-256 runs in your browser’s Web Cryptography API; ML-DSA-65 runs in noble-post-quantum 0.7.1, served from this site.
- The verification. Every verdict is computed from the bytes on screen, each time you click.
- The sizes: a 3 309-byte ML-DSA-65 signature and a 1 952-byte public key, as FIPS 204 specifies.
- The privacy. The page makes no network request with your file; you can check in your browser’s developer tools.
Simplified
- No certificates. On the platform each key is certified by a classical or a post-quantum CA, with CRL and OCSP.
- No PDF or CMS encoding. On the platform the ML-DSA-65 signature is a CMS SignedData (RFC 9882) in the unsigned attributes of a PAdES signature.
- The classical validator here is a model of how an unmodified validator treats an attribute it has no rule for. Real measurements are on the Evidence page.
- Not a legal signature. The keys belong to no one and disappear when you close the tab.
On the real platform
The same pattern, on a PAdES document.
We ran three of these changes against a document signed through the production platform. An unmodified EU DSS kept the signature valid each time; the Perennis validator refused each one.
| Change to the signed PDF | EU DSS 6.3* | Perennis validator |
|---|---|---|
| None | PASSED | PASSED |
| Post-quantum layer removed | PASSED | FAILED |
| 1 octet changed in the ML-DSA certificate | PASSED | FAILED |
| 1 octet changed in the ML-DSA signature | PASSED | FAILED |
The /ByteRange octets are identical in all four files, so the classical verdict is correct for what it checks. Only a validator that reads the post-quantum layer can tell the files apart.
After an archive time-stamp is added (PAdES-B-LTA), EU DSS also reports all three changes, as a time-stamp hash failure: it sees that bytes changed, not that the post-quantum signature is invalid.
* With the pilot’s issuing CA trusted. Validated against the EU trusted lists, the pilot CA gives INDETERMINATE because it is on no trusted list; no cryptographic check fails.
Questions about the lab
Why does the classical validator pass when the post-quantum layer is gone?
Because it is right about what it checks. The ECDSA signature still matches the document bytes, and the post-quantum layer sits outside those bytes so that existing tools keep working. Removing it changes nothing a classical validator reads. Only a validator that requires the layer can notice.
Does grafting a valid ML-DSA signature fool Perennis?
No. The grafted signature verifies on its own, which the log shows, but the layer is bound to the digest of another document and another ECDSA signature. The binding check fails.
Can I use my own PDF?
Yes, any file. It is read into memory in this tab, signed and checked there, and discarded when you leave. Nothing is uploaded.
How long does ML-DSA-65 take?
The event log shows the times measured on your device. They depend on your browser and hardware, and include JavaScript overhead that a native implementation does not have.