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 key
privateKey: <not generated>

Attacker laptop

device B · has cookie, no key
privateKey: <never had one>

Server log

Protocol steps shown above

  1. Register: client generates ECDSA P-256 keypair, sends public key to /dbsc/register, server stores it against the session.
  2. Refresh: server issues a challenge nonce; client signs with the private key; server verifies signature against the stored public key.
  3. 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 ↗