The hard part I skipped: Passkeys Cryptography
Understanding elliptic curves, signatures, and challenges (with visual help)
A short follow-up to my previous article on passkeys. I initially skipped the cryptographic part, like everyone, I didn’t feel like doing the hard part. But since you can’t really understand passkeys without going under the hood, this is the moment to do it.
How Passkeys Work at the Cryptographic Level
When you register a passkey with a service (the relying party), your device generates a key pair, a public key and a private key. The public key is shared with the server, while the private key is securely stored in your device’s enclave or secure element (for example, the Trusted Platform Module or Secure Enclave).
When you later authenticate, the server sends a challenge, a random piece of data, to your device. Your device signs this challenge using the private key, producing a digital signature. The server then uses the public key it stored earlier to verify the signature. If the verification passes, the server knows two things:
- The signature could only have been created by the matching private key.
- The challenge is fresh, meaning the authentication attempt is not a replay of a previous one.
This process provides proof of possession of the private key, without ever transmitting it over the network.
At a high level, the math works like this:
- The device generates a signature using the private key.
- The server verifies the signature with the public key.
- If verification passes, the server knows the user is authentic.
The Math Behind the Verification
WebAuthn supports multiple cryptographic algorithms, with ECDSA (Elliptic Curve Digital Signature Algorithm) and EdDSA (Ed25519) being the most common. RSA-based algorithms like RSASSA-PKCS1-v1_5 and RSASSA-PSS are also supported for compatibility.
The principle behind all these algorithms is that the public key is mathematically linked to the private key, allowing verification without ever exposing the private key. The algorithms differ in curves, key sizes, and signing methods, but all implement challenge-response authentication.
ECDSA Example: A Step-by-Step Walkthrough
Let’s be honest: the math behind ECDSA is not easy to follow. Even with a clear explanation, keeping track of all the variables (d, k, r, s, Q, R, G, H...) and understanding how they relate to each other can feel overwhelming. You’re dealing with elliptic curve operations, modular arithmetic, and multiple interdependent steps, all happening simultaneously.
That’s why I’ve created an interactive visual guide that walks you through each step with animations and highlights. Instead of just reading about the process, you can see it unfold:
🎯 Launch Interactive Visual Guide
The guide breaks down the entire process into digestible steps, showing you exactly when each variable is created, how they combine, and where they end up. I highly recommend opening it in a new tab and following along as you read the explanation below.
Now, let’s walk through ECDSA from setup to verification.
Initial Setup: Creating the Key Pair
When you first register a passkey, your device creates a key pair on an elliptic curve. Think of an elliptic curve as a mathematical space where certain operations are easy in one direction but nearly impossible to reverse.
The setup starts with a fixed point called the generator `G`, which is a standard point that everyone using this curve agrees upon. Your device then:
1. Generates a private key `d`, which is simply a large random number. This is your secret, stored securely in your device’s enclave, and never shared with anyone.
2. Computes the public key `Q` using the formula `Q = d * G`. This operation means “multiply the generator point `G` by the scalar `d`” in elliptic curve arithmetic.
Here’s the crucial property: computing `Q` from `d` and `G` is easy, but computing `d` from `Q` and `G` is computationally infeasible. This one-way property is what makes the cryptography secure. Your device sends `Q` to the server during registration, but `d` stays locked away forever.
Authentication: Creating a Signature
Now, when you return to authenticate, the server sends you a challenge `H` (typically a hash of random data plus contextual information). Your device needs to prove it still possesses the private key `d` without revealing it. Here’s how the signature is created:
1. Generate a fresh nonce `k`: For each signature, your device creates a new random number called `k`. This nonce is temporary and unique to this specific authentication attempt. Using a new `k` every time ensures that even signing the same challenge twice produces different signatures, preventing replay attacks.
2. Create a curve point `R`: Using the same generator `G` from setup, compute `R = k * G`. This point `R` has two coordinates, an x-coordinate and a y-coordinate.
3. Extract `r`: Take the x-coordinate of point `R` and call it `r`. This becomes the first part of your signature.
4. Compute `s`: Now comes the part that actually involves your private key. Calculate `s = k^(-1) * (H + r*d) mod n`, where:
- `k^(-1)` is the modular inverse of your nonce `k`
- `H` is the hash of the challenge from the server
- `r` is the x-coordinate we just extracted
- `d` is your private key
- `n` is the order of the elliptic curve (a fixed parameter)
5. Send the signature: Your device sends the pair `(r, s)` back to the server. Notice that neither `d` (your private key) nor `k` (your temporary nonce) are included, only the values `r` and `s` derived from them.
Verification: The Server’s Role
The server now has:
- The challenge `H` it originally sent
- Your signature `(r, s)`
- Your public key `Q` from registration
Using elliptic curve mathematics, the server can verify that this signature could only have been created by someone who knows the private key `d` corresponding to public key `Q`. The verification algorithm checks the mathematical relationship between all these values. If the relationship holds, the server has proof that you possess the private key without you ever transmitting it.
The beauty of this system is in its asymmetry: creating the signature requires the private key `d`, but verifying it only requires the public key `Q`. The server can be confident of your identity without ever knowing your secret.
If you found this explanation dense (and honestly, who wouldn’t?), go back to the interactive visual guide. Click through each step and watch how the variables flow from one operation to the next. It makes the whole process much clearer than words alone can convey.
Other Algorithms
- EdDSA (Ed25519): A faster, modern elliptic curve algorithm with deterministic signatures (no random `k` needed, which eliminates certain implementation risks).
- RSASSA-PKCS1-v1_5 and RSASSA-PSS: RSA-based algorithms that use different mathematical operations (prime factorization instead of elliptic curves) but follow the same principle of public key verification.
All these algorithms implement the same core concept: only the private key holder can produce a signature that the public key can verify, ensuring authenticity without exposing secrets.
Why the Challenge Matters
The challenge prevents replay attacks. Each authentication request generates a new random challenge, so an old signature is useless. Including contextual data, like the domain name, prevents phishing or cross-origin attacks, ensuring the signature is valid only for the legitimate site.
Security Properties
The cryptographic mechanism provides three main guarantees:
- Authenticity – Only the legitimate private key holder can produce a valid signature.
- Integrity – Any modification to the challenge or signed data invalidates the signature.
- Non-repudiation – Once the challenge is signed, the signer cannot plausibly deny having authenticated (depending on implementation).
These properties make passkeys robust against phishing, credential stuffing, and password leaks. The private key never leaves your device, and even the server breach won’t compromise your credentials.
If you enjoyed this deeper dive and want to keep exploring the technical side of authentication, subscribe to the newsletter or follow me on X for future updates.
If you find this content useful, feel free to support me with a coffee



