Sign in with a passkey, enter your details once, and five completed forms are generated
on your device. The raw data never leaves the browser while this happens, and you can check that yourself in the network tab.
5×
the same details, typed by hand, five times
vs
1×+ automatic
one entry, five finished forms
00:00.0
1 Passkey
2 Data entry
3 Commitment
4 Five forms
2 · One-time data entry
Sample data sheet
This is a public demo with no data controller behind it. Do not enter a real
NHS number or any other real personal data, use the "Fill in sample data" button.
3 · What we sent
The exact JSON sent to the Worker
–
Open your browser's network tab (F12 → Network), find this request and look
at its body. It contains neither the raw values of the fields above nor the blinding nonce,
only blind commitments and field names.
4 · Five completed forms
Security panel
The Worker receives the JSON above: one blind commitment per field name, whether the
submission is complete, and a timestamp. It never receives a raw value or the commitment
key (the nonce), because those never leave this page.
The commitment is computed as HMAC-SHA-256(nonce, field value).
The nonce is 32 random bytes, generated with crypto.getRandomValues(), and lives only in memory.
The Worker applies its own secret, kept outside the database (a pepper), to the incoming
commitments and returns a signed receipt. That proves the submission happened and was complete,
but it does not verify the content (see the limit below).
The question is not how long it takes to crack a SHA-256 output. An attacker does not search
the hash's output space, but the input space: an NHS number has 10 digits, the last of which
is a check digit, so there are about 10⁹ ≈ 2³⁰ possibilities. On ordinary hardware that is a matter
of seconds if the hash stands on its own.
The two boxes below compute live, on this machine. This is not an animation.
1 · Plain hash, 6-digit sample
Not started
Speed: – · Time: –
2 · Keyed (HMAC) commitment, same space
Not started
Speed: – · Time: –
Salt (random per record): protects against precomputed (rainbow) tables. On its own
it is not enough against a targeted brute force if the attacker also holds the database.
Pepper (keyed hash), with the key kept outside the database: a database dump on its own
is useless, because the key is not in it.
Blind commitment: the nonce never leaves the browser, so there is nothing on the
server side to brute-force.
The limit we have to state
With a blind commitment the Worker cannot verify the content of the data, only that the
submission is structurally complete and whether the same value can be shown again later. Real
content verification would need an issuer. This demo contains no such thing, and does not claim
to.