v147 · Security · DBSC
Compatibility Lab
Probes the cryptographic primitives that DBSC relies on — SubtleCrypto P-256 key generation and signing, WebAuthn/navigator.credentials, and secure context. Runs a live P-256 keypair generation + sign/verify cycle, mirroring the proof-of-possession step DBSC performs on every session refresh.
API probes
DBSC crypto dependency matrix
| Dependency | Required for | Available |
|---|---|---|
| SubtleCrypto (P-256 ECDSA) | Device keypair generation + signing | — |
| navigator.credentials (WebAuthn) | Hardware-backed key storage | — |
| Secure context (HTTPS) | DBSC requires HTTPS origins | — |
| SubtleCrypto.sign() with ECDSA | Proof-of-possession signature | — |
| Sec-Session-* headers | Browser-managed — not JS-visible | Browser-internal |
Live P-256 keygen + proof-of-possession
SubtleCrypto P-256 sign/verify (DBSC crypto primitive)
Click "Run proof-of-possession cycle" to generate a P-256 keypair and sign a challenge…
DBSC handshake pattern
/* Device Bound Session Credentials — server-side pattern */
/* DBSC is browser-managed: no direct JS API.
The browser handles key generation and signing internally.
Use HTTP headers to negotiate the session binding. */
/* 1. Server sends Sec-Session-Registration header: */
// HTTP/1.1 200 OK
// Sec-Session-Registration: (ES256);challenge="server-nonce-abc";
// authorization="https://example.com/dbsc/refresh"
/* 2. Browser generates device-bound P-256 keypair and sends
a signed registration to the authorization URL.
The registration is a signed JWT with the public key. */
/* 3. Server stores the public key, binds it to the session,
and returns a short-lived session cookie. */
/* 4. On every refresh, server returns:
Sec-Session-Challenge: "new-nonce";id="session-id"
Browser signs the challenge with the device key. */
/* 5. If proof-of-possession fails → session terminated.
A copied cookie without the device key cannot refresh. */
/* Detect if browser will attempt DBSC registration */
const DBSC_LIKELY = window.isSecureContext &&
typeof crypto !== 'undefined' &&
typeof crypto.subtle !== 'undefined';
/* The actual key generation is browser-internal.
For application-layer ECDSA (e.g. custom binding): */
async function generateDeviceKey() {
return crypto.subtle.generateKey(
{ name: 'ECDSA', namedCurve: 'P-256' },
false, // non-extractable — key stays in device
['sign', 'verify']
);
}
async function signChallenge(privateKey, challenge) {
const enc = new TextEncoder();
const sig = await crypto.subtle.sign(
{ name: 'ECDSA', hash: 'SHA-256' },
privateKey,
enc.encode(challenge)
);
return btoa(String.fromCharCode(...new Uint8Array(sig)));
}
References
implementation reference
Need the exact API surface, compatibility boundaries, errors, lifecycle, and source links? Read the matching gendn reference ↗