Build the mental model
A passkey is a credential based on public-key cryptography instead of a typed secret. Your device generates a matched key pair: a public key handed to the service, and a private credential that never leaves the device.
How This Differs From Cybersecurity Basics
Every authentication method in Cybersecurity Basics relies on a secret the user types or possesses. Passkeys break entirely from that model.
1. Service sends a challenge
When you log in, the service sends a piece of data unique to that specific login attempt.
2. Device signs it
The device uses the private credential to sign the challenge — the credential itself never appears anywhere in this step.
3. Only the signature returns
The device sends back only the signature, never the credential.
4. Service verifies
The service checks the signature against the public key it already has, and access is granted if it matches.
Correcting a Common Misconception
The private key does NOT get sent to the website. It stays on your device permanently — only mathematical proof of holding it ever crosses the network.
- Passkey
- An authentication credential built on public-key cryptography, where the private credential never leaves the user's device or authenticator.
- Public-Key Cryptography
- A system using a matched pair of keys, where possession of the private key can be mathematically proven without ever revealing the private key itself.
PASSKEY CHALLENGE-RESPONSE FLOW
-------------------------------
PASSKEY CHALLENGE-RESPONSE FLOW
--------------------------------
SERVICE DEVICE
(stores PUBLIC key) (protects PRIVATE credential)
| |
| 1. login request |
|----------------------------------->|
| |
| 2. sends CHALLENGE |
|----------------------------------->|
| |
| 3. signs challenge
| with PRIVATE credential
| (never leaves device)
| |
| 4. returns SIGNATURE only |
|<-----------------------------------|
| |
5. verifies signature
using PUBLIC key
|
6. ACCESS GRANTED (or denied)Connect it to a real scenario
The code below simulates the shape of challenge-response authentication using plain string hashing instead of real public-key math. It is a teaching illustration only.
Registration
The device hashes its private credential once and gives the service only that derived verifier.
Login
The service sends a challenge, and the device combines it with its secret to produce a response, never sending the secret itself.
Verification
The service independently recomputes what a valid response should look like using only its stored verifier, and compares.
Run the simulation twice: once with the correct private credential, and once with an impostor guessing a wrong one. The legitimate device verifies successfully; the impostor does not.
Try the working example
// SIMPLIFIED ILLUSTRATION ONLY -- not real cryptography.
// Real passkeys use asymmetric (public/private key) math; this toy uses
// plain string hashing just to show the SHAPE of challenge-response:
// the device never transmits its secret, only a response to a challenge.
function simpleHash(text) {
let hash = 0;
for (let i = 0; i < text.length; i++) {
hash = (hash * 31 + text.charCodeAt(i)) >>> 0;
}
return hash.toString(16);
}
function registerDevice(privateCredential) {
return simpleHash(privateCredential);
}
function deviceRespond(privateCredential, challenge) {
const provisionalVerifier = simpleHash(privateCredential);
return simpleHash(challenge + provisionalVerifier);
}
function serviceVerify(storedVerifier, challenge, deviceResponse) {
const expected = simpleHash(challenge + storedVerifier);
return expected === deviceResponse;
}
const privateCredential = "device-secret-9f3a";
const storedVerifier = registerDevice(privateCredential);
const challenge = "login-challenge-001";
const response = deviceRespond(privateCredential, challenge);
const legitimateLoginValid = serviceVerify(storedVerifier, challenge, response);
const impostorResponse = deviceRespond("wrong-guess", challenge);
const impostorLoginValid = serviceVerify(storedVerifier, challenge, impostorResponse);
console.log(JSON.stringify({
storedVerifier,
challenge,
deviceResponse: response,
secretWasTransmitted: false,
legitimateLoginValid,
impostorLoginValid
}, null, 2));{
"storedVerifier": "c0bc4ea1",
"challenge": "login-challenge-001",
"deviceResponse": "b6bf07f2",
"secretWasTransmitted": false,
"legitimateLoginValid": true,
"impostorLoginValid": false
}5-minute try-it
Change `challenge` to "login-challenge-002" and re-run. Notice `storedVerifier` stays the same but `deviceResponse` changes — the response must be unique per challenge.
One important caution
Mistaking this illustration for real cryptography and trying to use it in an actual system
Continuing to believe the private key is literally transmitted to the website
FIDO Alliance — Passkeys — Digital Privacy & Modern Security