demo · v147
Cookie replay simulator
Run the same stolen cookie from two browsers. Without DBSC, both pass. With DBSC, the attacker can't sign the proof-of-possession challenge, so the refresh fails and the session is killed.
Note: the DBSC protocol runs against a real server. This page simulates both the
client and the relying-party in JavaScript, using
SubtleCrypto for an ECDSA P-256
keypair and an in-page "refresh endpoint" so you can step through every state transition without a backend.
The legit machine generates a keypair, registers the public key with the server, and is issued a short-lived session cookie. Every refresh challenges the client to sign a nonce — proof it still holds the private key. The attacker steals only the cookie; they cannot answer the challenge.
Legit device
device A · holds private keyprivateKey: <not generated>
Attacker laptop
device B · has cookie, no keyprivateKey: <never had one>
Server log
Protocol steps shown above
- Register: client generates ECDSA P-256 keypair, sends public key to
/dbsc/register, server stores it against the session. - Refresh: server issues a challenge nonce; client signs with the private key; server verifies signature against the stored public key.
- Protected API: only callable with a fresh, signed session token. Stolen cookies cannot refresh, so they expire and get evicted.
// client: register
const { publicKey, privateKey } = await crypto.subtle.generateKey(
{ name: 'ECDSA', namedCurve: 'P-256' }, false, ['sign']);
await fetch('/dbsc/register', { method: 'POST', body: jwk(publicKey) });
// client: refresh
const { challenge } = await fetch('/dbsc/challenge').then(r => r.json());
const sig = await crypto.subtle.sign(
{ name: 'ECDSA', hash: 'SHA-256' }, privateKey, te(challenge));
await fetch('/dbsc/refresh', { method: 'POST', body: sig });
see also
implementation reference
Need the exact API surface, compatibility boundaries, errors, lifecycle, and source links? Read the matching gendn reference ↗