A password is a static secret. Someone who steals it from a breach, phishing page, or infected device can submit the same value as the legitimate user. It remains usable until changed or disabled. Salting and slow hashing protect stored passwords, but they do not help once the attacker knows the password itself.
One-time passwords limit reuse of a captured code. Device-based second factors make a stolen password useless on its own. Passkeys go further by replacing the password with a key pair and binding each authentication to the intended site.
One-Time Passwords
A one-time password (OTP) is accepted for at most one successful authentication. Once accepted, it should not work again. An attacker who steals an unused code, for example through an adversary-in-the-middle attack, can still use it before the legitimate user does. OTP systems differ in how they generate the codes and track their use.
Hash Chains
In 1981, Leslie Lamport proposed generating one-time passwords from a chain of hashes. The user’s device starts with a random seed \(s\) and applies a hash function repeatedly: \(x_1 = H(s)\), \(x_2 = H(x_1)\), and so on up to \(x_{n}\). The server stores only the last value, \(x_n\).
At the first login, the user sends \(x_{n-1}\). The server checks that \(H(x_{n-1}) = x_n\), accepts the login, and replaces its stored value with \(x_{n-1}\). The next login uses \(x_{n-2}\), and so on backward through the chain.
Given a strong hash and a random seed, an eavesdropper who captures \(x_{n-1}\) cannot feasibly compute \(x_{n-2}\). A stolen copy of the server’s current value also does not reveal the next password, although an attacker able to replace that value could compromise the account. The idea was implemented in S/Key, described in 1995 and used for remote Unix logins. After the chain is exhausted, a new one must be enrolled securely.
S/Key computed the starting value from a secret passphrase and a public seed chosen by the server, so the user could regenerate the chain from a memorized passphrase, and the same passphrase produced a different chain on each server. A weak passphrase can be guessed offline from a single captured code.
Counter-Based and Time-Based Codes
Most one-time passwords today come from a shared secret key and a changing input:
-
HMAC-based one-time password (HOTP, 2005) computes \(\operatorname{HMAC}_K(c)\), where \(c\) is a counter, and reduces the result to a short decimal code, often six digits. The server can search a limited range of counters ahead of its current value, allowing for codes generated but never submitted. After accepting one, it advances past that counter.
-
Time-based one-time password (TOTP, 2011) uses a time counter, commonly based on 30-second intervals. The server may accept neighboring intervals to allow for delays or clock drift. It must also remember accepted uses so the same code cannot be reused within its validity window.
Authenticator apps such as Google Authenticator and Microsoft Authenticator compute TOTP codes. The app and the server share a secret key, usually transferred once by scanning a QR code when the account is set up. After that, the app does not need a network connection.
Before authenticator apps, time-based codes came from dedicated hardware. In the 1990s, many companies issued employees RSA SecurID tokens, small key fobs whose display shows a new code, typically every 60 seconds. SecurID uses its own algorithm rather than TOTP, but the idea is the same: the token and the server share a secret key and a clock. These devices are still used by many companies.
A challenge-based token instead computes a response to a challenge sent by the server. It uses challenge-response authentication with a random key held in a device rather than a password remembered by the user. The server holds a copy of the same key to check the response.
Short codes can be guessed. A six-digit code has only one million possibilities, so the server must limit failed attempts even when the shared key is strong.
The Server Still Holds a Secret
HOTP and TOTP require the server to use the shared key when checking codes. The server cannot replace that key with a one-way hash. Encrypting the key at rest helps protect a stolen database, but an attacker who obtains the usable key can generate future codes.
In March 2011, attackers breached RSA Security and stole information related to the SecurID tokens’ secret values. The stolen information was later linked to an attempted intrusion at Lockheed Martin, a U.S. defense contractor. RSA offered token replacements. A physical token had not removed the need to protect its shared secret on the server and during provisioning.
Delivering a Second Factor
A one-time code is usually a second factor, required after the password. That factor is something the user has: a phone, a phone number, or a dedicated device that holds the secret. Most services assume that every user carries a phone that runs apps and receives text messages. How the code reaches the user determines how well it holds up.
Text messages. The server sends a code using the Short Message Service (SMS). Delivery depends on control of a phone number, and the carrier, not the user, controls that number. In a SIM swap, an attacker persuades a mobile carrier to transfer the victim’s number to a SIM the attacker controls and then receives the codes. Because of this and other telephone-network risks, the U.S. National Institute of Standards and Technology (NIST) classifies this authentication method as restricted.
Authenticator apps. A TOTP code generated on the user’s phone never travels over the phone network, so a SIM swap does not affect it.
Hardware tokens. A dedicated device holds the secret, so it does not depend on a phone or a phone number. Some display a code, as SecurID tokens do. A security key, such as a YubiKey, plugs into a USB port or connects by near-field communication (NFC) and answers the site’s challenge itself after the user touches it. When it holds a passkey, it also asks for a PIN, or a fingerprint on models with a sensor. Hardware tokens and smart cards are used where phones are not allowed, such as facilities that handle classified information. We will return to security keys with passkeys.
Push notifications. The server sends a prompt to an app on the user’s phone asking whether to approve a login. This is convenient, but it invites approval by reflex. An attacker who already has the password can send prompt after prompt until the user taps Approve to make them stop. The technique is known as push fatigue or MFA fatigue.
In September 2022, an attacker with an Uber contractor’s password repeatedly triggered login prompts. The contractor eventually approved one, giving the attacker access to internal systems. Uber reported that the password had likely been stolen by malware and purchased by the attacker.
Number matching ties approval to a particular login attempt. The login screen displays a number that the user must enter in the authenticator app. This reduces approvals made merely to dismiss an unexpected prompt. Microsoft began enforcing number matching for Authenticator push approvals on May 8, 2023. An attacker can still relay the number or persuade a user to enter it.
Relaying a Login in Real Time
We will cover phishing and social engineering in detail later. The attack described here is one example of how phishing defeats one-time codes and push approvals.
Some phishing sites collect passwords with copied login forms. Others pass traffic between the victim and the real site in both directions. The phishing link takes the victim’s browser to the attacker’s server, which opens its own connection to the real site. When the browser asks for a page, the attacker’s server requests the same page from the real site and sends the response back to the browser. When the victim submits a form, the attacker’s server submits the same data to the real site.
Both connections use TLS, but TLS protects data only between the two ends of one connection. The attacker’s server is an end of both connections, so it sees everything the victim sends and everything the real site returns. It has a valid certificate for its own lookalike domain, so the browser does not show a warning.
This is an adversary-in-the-middle attack, with the phishing link putting the attacker in the middle. TLS does not stop it, because TLS authenticates the server the browser connected to, not the site the user meant to reach.
The victim sees the real site’s login pages, passed through the attacker’s server, and enters a password and one-time code or approves a push prompt. The attacker’s server forwards each step immediately. The real site sees a successful login with a valid second factor.
After login, the site commonly issues a session cookie, a token the browser sends with later requests to that site. If possession of the cookie is enough to use the session, the attacker’s server can keep a copy and the attacker can reuse it without repeating authentication.
The one-time property does not help here, because the attacker uses the code once, while it is still valid. In July 2022, Microsoft reported a campaign of this kind that had targeted more than 10,000 organizations since September 2021.
Ordinary passwords, manually entered codes, and push approvals do not cryptographically bind the login to the website shown in the browser. The real site cannot tell from a correct code that it was entered on a phishing page.
Passkeys
Each method so far adds a step to login without removing the password. Passwords are reused, guessed, and phished. One-time codes and push approvals make a stolen password insufficient by itself, but they add work to every login. SMS depends on the phone network, push prompts invite reflexive approval, SMS and number matching both require extra typing, and all of them can be relayed in real time. Hardware security keys resisted relaying, but they were a separate device to buy, carry, and keep track of. The goal of passkeys was a credential that does not leave a shared secret on the server, does not work on the wrong site, and is as easy to use as unlocking a phone.
A passkey is a public-key credential bound to a site or service. The browser and authenticator enforce that binding, so authentication does not depend solely on the user recognizing a lookalike domain.
The standards behind passkeys came from the FIDO (Fast Identity Online) Alliance, an industry association, and the World Wide Web Consortium (W3C), which develops web standards. The W3C standardized the browser interface, Web Authentication (WebAuthn), in March 2019. Together with a protocol for communicating with authenticators, it forms the FIDO2 standards. In May 2022, Apple, Google, and Microsoft announced broader support for these credentials across their platforms under the name passkeys.
A passkey uses public-key challenge-response authentication in the following sequence:
-
Registration. The authenticator creates a public-private key pair for the site, which stores the public key with the user’s account. The private key is not sent to the site.
-
Local verification. At login, the site sends a fresh challenge. The authenticator checks the user locally, for example with a fingerprint, face scan, or device PIN. Biometric data stays on the device.
-
Signing and verification. The authenticator uses the private key for that site to sign data covering the challenge and the site’s identity. The site verifies the signature, challenge, and site binding using the registered public key.
Synced passkeys can be copied securely between approved devices through a provider such as iCloud Keychain or Google Password Manager. They are protected with end-to-end encryption during synchronization. Device-bound passkeys remain on one authenticator, such as a hardware security key connected by USB or NFC.
Stealing the site’s public-key database does not give an attacker the private keys needed to log in. A signature recorded during one login will not work for the next challenge. A full server compromise can still expose account data or let the attacker change registered credentials.
Why Passkeys Resist Phishing
The browser records the page’s origin, consisting of its scheme (protocol), host, and port. Each passkey is bound to the domain of the site that registered it. The signed response covers that domain, the page’s origin, and the challenge.
For example, a page at a lookalike bank domain cannot request the real bank’s passkey. Relaying the real bank’s challenge through that page does not bypass the browser’s domain check. The bank also verifies the origin covered by the signed response, so a response for the phishing site’s origin would be rejected.
These checks prevent the ordinary login relay described above, assuming the browser, authenticator, and site’s verification are working correctly. The user is not asked to recognize and approve the domain binding manually.
Limits of Passkeys
Passkeys remove reusable passwords from the login exchange, but account security still depends on the following:
-
Synchronization depends on the provider’s encryption, device approval, and recovery controls. Stealing a cloud-account password alone does not necessarily reveal passkeys. For example, iCloud Keychain adds protections beyond account access.
-
Account recovery can provide a weaker route into an account. A password, emailed link, or help-desk fallback must be protected too.
-
Losing access to every copy requires recovery or another registered authenticator. A backup security key can provide that alternative.
-
Malware or a stolen session cookie can compromise an account after login, even when the passkey itself remains secure.
Next: Part 6: Biometric Authentication
Lecture 4: Part 1 | Part 2 | Part 3 | Part 4 | Part 5 | Part 6 | Appendix
Lecture 4 Study Guide | List of terms