Try It
Four of the walkthrough's stories, put through the real verifier — the claims that travelled, the claims that stayed on the phone, and the eight-check ladder that decided. Then six ways the same bank story can go wrong on the wire, and a qualified signature with its five break-it experiments.
Every result here is real output, not a mock. Runs marked recorded were produced by the same verifier ahead of time — the live path needs a local service that isn't part of this site. Clone the repo and the same screens run against your own wallet; see The Experiment for what was built.
Get your wallet
Once, then never againOne PID, issued once, held in a non-extractable WebCrypto key. Every other story on this page presents from it.
Checking for a held credential…
Open a bank account
11 minutes → 40 secondsLara Bank's registered claim set — age_over_18 and nationality — requested and revealed, nothing else.
Checking for the local verifier service…
Prove you are over 18
The magic trickSame wallet, same verifier — but the request asks for one claim instead of two. Watch the disclosed list shrink and the verifier still accept.
Checking for the local verifier service…
A scammer tries it on
The bit nobody demosThe wallet is told it's presenting to "https://lara-bank-secure.verify-id.co" — a phishing relay. That KB-JWT is bound to the wrong audience, then forwarded to the real Lara Bank verifier anyway.
Checking for the local verifier service…
Open a bank account — but something's wrong
6 of 13 species · recordedSame onboarding story as before, six ways it can go wrong on the wire. Pick one and watch which of the eight checks catches it.
Sign a mortgage — qualified signature
Recorded runA real CA chain and a real PAdES signature, recorded once rather than driven live — no browser can perform PAdES signing interactively.
- signature_validtrue
- chain_trustedtrue
- document_unmodifiedtrue
- timestamp_validtrue
- is_qualifiedtrue
document_modified_after_signing — a page was inserted via a second incremental update after the signature was applied
- signature_validtrue
- chain_trustedtrue
- document_unmodifiedfalse
- timestamp_validtrue
- is_qualifiedtrue
the document was modified after the signature was applied
signature_from_revoked_cert — signed with a certificate whose serial is on the revoked set
- signature_validtrue
- chain_trustedfalse
- document_unmodifiedtrue
- timestamp_validtrue
- is_qualifiedtrue
signing certificate is on the revoked set
missing_or_forged_timestamp — signed with no timestamper — no timestamp token embedded at all
- signature_validtrue
- chain_trustedtrue
- document_unmodifiedtrue
- timestamp_validnull
- is_qualifiedtrue
no timestamp present
chain_to_untrusted_ca — signed by a certificate chaining to a root that isn't a registered trust anchor
- signature_validtrue
- chain_trustedfalse
- document_unmodifiedtrue
- timestamp_validtrue
- is_qualifiedtrue
certificate chain does not resolve to a trusted anchor
advanced_not_qualified_cert_as_qes — signed with an Advanced (AES) certificate — no qcStatements extension — everything else clean
- signature_validtrue
- chain_trustedtrue
- document_unmodifiedtrue
- timestamp_validtrue
- is_qualifiedfalse
certificate is Advanced (AES), not Qualified (QES) — no qcStatements extension
The one non-rejection: advanced_not_qualified_cert_as_qes passes every cryptographic check — signature_valid, chain_trusted, document_unmodified, timestamp_valid all stay true. Only is_qualified flips — a real ETSI qcStatements extension the QTSP chose to attach or withhold, a legal fact, not a mathematical one.