I was just wondering how a YubiKey actually performs authentication.

I started using the YubiKey 5C NFC in 2023, and later I also bought a USB‑A model. At the time I introduced it to protect my 1Password account, planning to register one key for everyday carry and another as a spare kept at home. (source) (source)

You plug it into a USB port and touch it when needed. With a smartphone you use NFC. The user interaction is minimal, but I’ve never taken the time to understand exactly what’s happening behind the scenes.

Does that gold‑colored part read a fingerprint? And how does it work at all when it has no battery?

This time, I read through Yubico’s official documentation and the authentication specifications to investigate those points. This is not an article that disassembled the key or measured its cryptographic processing. It’s a record of re‑examining the usual login process from the perspective of its underlying mechanisms.

YubiKey Authentication Methods

YubiKey is a hardware device that can handle multiple authentication methods internally. Depending on which method is used, the information exchanged and the security properties differ.

The YubiKey 5 series I purchased supports features such as FIDO2, FIDO U2F, OATH, Yubico OTP, PIV, and OpenPGP. They do not all use the same cryptographic processing. Looking at the official feature list, it’s more accurate to think of the small device as containing multiple applications with different purposes. (source)

The main differences can be summarized as follows.

MethodWhat is verifiedWhat is sent to the service
FIDO2 / U2FSign with the private key that corresponds to the public keyA signature on the authentication request, etc.
OATH‑TOTP / HOTPCompute a code from a secret shared with the serverA 6‑digit or 8‑digit authentication code
Yubico OTPData encrypted with a shared secret, including a counter and other fieldsA long string one‑time password
PIV / OpenPGPPerform cryptographic operations using the stored private keySignatures, decryption results, and other responses appropriate to the operation

The mechanism used when the browser says “please touch” is different from the one used when an authenticator app displays a six‑digit number. Mixing these up would even change the answer to the the question of whether the secret is being handed over to the server.

There are also products, such as the Security Key series, that are limited to FIDO functionality. (source)

First, we’ll focus on FIDO2, which is used in web security keys and passkeys.

Public and Private Keys

The core of FIDO‑based authentication is digital signatures using public‑key cryptography.

A public key and a private key form a pair of keys. The private key is used to sign data, and the public key supplied to the service is used to verify that the signature is valid.

Digital signatures serve a different purpose from encryption that lets only the recipient read the contents. What we want to confirm is whether the party possessing the corresponding private key signed the data in question.

When a YubiKey is used as a FIDO authenticator, the public key is registered with the service, and the operations that use the private key are performed inside the key itself. The service checks the signature on each login to verify that the registered key is still being presented by the legitimate user. The Yubico FIDO2 Developer Guide explains this architecture and the roles of the various participants. (source)

A major difference from passwords is that, during login, you do not need to send the secret itself—something that can be reused—to the service.

You cannot produce the same signature by looking only at the public key. The cryptographic algorithm and key size are chosen so that deriving the private key from the public key is computationally infeasible.

Data leaks such as exposed email addresses, or compromises of the server itself, are separate issues. What this mitigates is the risk that a leaked stored public key could directly grant the ability to sign as the user.

Registering the Key

Before you can log in, the key must be registered. This is the step where you perform an action like “Add security key” in the service’s settings screen.

During registration, the service sends to the browser a random value, the service’s identifier, account information, the supported cryptographic algorithms, and other details. The browser or operating system forwards this information to the authenticator, which generates the authentication key. The public key, credential ID, and other returned data are then associated by the service with the user’s account and stored. The registration flow is also documented in Yubico’s materials.

A credential ID is a value that identifies the authentication credential being used. The same physical key can be registered with multiple sites because each site and each registration handles its own credential information.

At this point, the service is essentially registering “this account is allowed to authenticate using this public key.” It doesn’t treat the user as authenticated merely because the YubiKey’s product name matches.

Even if you purchase another key of the same model, you won’t be able to log in unless it is registered.

At the time of registration, the account holder must also be verified. The authenticator does not inherently know which account it belongs to. The service first confirms the user’s identity and then binds the key to that account. Therefore, the step of allowing a key to be added is also important.

Interaction During Login

After registration, the service generates a new random value for each login attempt. This is called a challenge.

It asks, “Please sign the data that includes this value using the registered key,” and then checks whether a valid signature is returned. Because a different challenge is presented each time, a previously correct signature cannot be reused to answer the current challenge. The Yubico documentation on authentication processing outlines the challenges and the information returned. (source)

For example, suppose the signature for the value “A” was correct during yesterday’s login. If today the service issues the value “B,” sending yesterday’s signature for “A” will not work for today’s authentication. When verifying a signature, the service checks not only that the key matches but also that the response includes the challenge that was issued this time.

Being able to answer the new challenge serves as proof that the key can be used at that moment. A copy of past communications alone cannot generate a fresh response.

The service generates challenges that are sufficiently unpredictable, keeps track of which authentication operation each challenge was issued for, and rejects responses that have already been used or have expired.

If we greatly simplify the sequence of operations, it looks like this:

sequenceDiagram
    participant S as Service
    participant B as Browser/OS
    participant Y as YubiKey
    participant U as User
    S->>B: This challenge and its authentication requirements
    B->>B: Inspect the caller and the authentication target
    B->>Y: Authentication target'sIDand the information to be signed
    Y-->>U: Request operation
    U->>Y: Touch, if necessaryPINVerify, etc.
    Y->>Y: Sign with the private key
    Y-->>B: Signature and authenticator information
    B-->>S: Authentication response
    S->>S: Verify the signature and each condition with the public key

Data to be Signed

So far I’ve described “signing the challenge,” but the actual WebAuthn authentication response contains a bit more information.

Conceptually, the data to be signed takes the following form:

authenticatorData || SHA-256(clientDataJSON)

|| indicates that the data is concatenated. clientDataJSON contains the challenge, the origin of the request, the type of operation, and other fields, while authenticatorData includes the hash of the RP ID, flags related to the user’s interaction and verification, and so on. The exact format and verification procedures are defined in the WebAuthn specification. (source)

In other words, the signature is tied not only to “answering this random value” but also to “which authentication target and what verification was performed.” If you later modify only the flags, the data being signed changes, and the verification will fail.

The JSON data held by the browser is passed to the authenticator as a fixed‑length value via a hash. The JSON itself is also included in the resulting response, allowing the service to verify both its contents and the signature.

The YubiKey does not have a feature that inspects the browser’s address bar. It receives the information generated by the browser and performs cryptographic processing on it. Consequently, a browser that correctly generates the information and a service that correctly verifies the returned information are also part of this mechanism.

Countermeasures against phishing

Even compared with one‑time passwords, FIDO authentication is resistant to phishing because it includes a mechanism that restricts the authentication target.

Numeric authentication codes can be entered by a human into a field. The code itself does not determine whether the destination is legitimate. In contrast, FIDO credentials are tied to the identifier of the service for which they were registered. The U2F protocol overview also explains this binding to the authentication target. (source)

In WebAuthn, the browser checks the origin of the page that actually called the API and verifies whether the requested RP ID is permitted. The RP ID is an identifier that represents the authentication target, typically a domain name. The authenticator also uses credentials that correspond to that RP ID.

Here, the origin and the RP ID are not necessarily the same string. The origin includes the scheme and port, whereas the RP ID deals with just the domain name. For example, if a service is designed to use example.com as its RP ID, it may share that ID across subdomains used for login. The fine‑grained permission checks are performed by the browser according to the specification.

Even if a site on a completely different domain that looks identical tries to use the key intended for the legitimate site, the browser will verify whether it is allowed to handle that request. Changing the authentication target will cause the credentials registered for the legitimate site to no longer match.

By incorporating a check of the authentication target into the authentication process, we no longer have to rely solely on humans detecting a fake site. However, this assumes a properly functioning browser and OS, as well as correct verification on the service side.

Touch and fingerprint authentication

The part you touch on a standard YubiKey 5 series is not a fingerprint sensor.

What that interaction confirms is that the user is present and has touched the key. In FIDO this is called User Presence, abbreviated UP. For the inserted key, the system does not simply keep issuing authentication requests from software; it requires the user’s action to complete the process.

In contrast, verifying the user with a PIN or biometric authentication is called User Verification, abbreviated UV. These two concepts are distinguished even in the official documentation. Touching alone does not reveal who the person is. (source)

Fingerprint support is available on compatible products such as the YubiKey Bio.

Moreover, merely touching the device does not prove that the user fully understands the content of the current authentication request. There is no screen on the device that displays the name of the target service, so you must rely on the browser or OS display to see which request is being responded to. The act of confirming the operation and the act of understanding the request’s content need to be considered separately.

The role of the PIN

The FIDO2 PIN and a website password are verified against different parties.

A website password is used to authenticate yourself to that service. A FIDO2 PIN, on the other hand, is used to verify the person who is using the authenticator in hand. It is not a system where the PIN is sent to the service’s server for the server to check a match.

The PIN entered via the browser or OS prompt is used to verify the user with the authenticator. The service receives UV information indicating that verification succeeded, along with a signature. The fact that the PIN is managed on the authenticator side is also explained in the developer guide mentioned above. (source)

If an authentication method requires PIN verification, simply possessing the key is insufficient; the PIN must also be known. This combines physical possession of the device with knowledge of the PIN.

However, a PIN is not required for every use case. Some workflows ask for only a touch in addition to a password. The conditions vary depending on the service’s requirements, the credential’s protection settings, and the authenticator’s capabilities. Assuming that “because I set a PIN, all authentication methods are protected by that PIN” is also risky.

YubiKey’s FIDO2 implementation includes a limit on the number of PIN entry attempts. The FIDO feature documentation explains that repeated incorrect entries will lock the FIDO2, and a reset is required to restore it. It is not designed as a mechanism that lets you endlessly try every possible guess after forgetting the PIN. (source)

That reset does not restore the original authentication credentials. Since the previous keys can no longer be used for login, a backup authentication method becomes necessary.

In a FIDO2 setup used on the web, WebAuthn sits between the website and the browser, while CTAP sits between the browser/OS and an external authenticator. The official CTAP documentation makes it clear when you consider the two segments separately. (source)

Website
    │ WebAuthn API
Browser/OS
    │ CTAP
YubiKey

WebAuthn is the API that a site uses to request the registration or use of authentication credentials. In JavaScript terms, you would use navigator.credentials.create() or navigator.credentials.get(). The site does not directly construct the USB communication data itself.

CTAP is the protocol that enables communication between the client and the authenticator. It carries exchanges such as “create a credential” or “provide a response to this authentication request” over the supported connection methods. USB and NFC serve as the channels that transport this communication.

U2F is a FIDO protocol that has been in use before. It is primarily employed as a second factor added to a password, and it incorporates the basics of public‑key cryptography, signing a challenge, and a binding to the authentication target. In FIDO2, user verification via PIN or other means, as well as discoverable credentials (to be discussed later), become available, enabling password‑less login.

Even if you possess a key that supports FIDO2, the site may not adopt password‑less authentication. The registration method and login requirements depend on the other party’s implementation.

Storage methods and capacity of credentials

The way credentials are stored also determines whether the device’s internal memory is used.

FIDO2 distinguishes between discoverable credentials and non‑discoverable credentials. The former allows the authenticator to locate the credential that corresponds to the authentication target on its own, whereas the latter requires the service to send a credential ID to specify which credential to use. The Yubico documentation on credentials explains this distinction. (source)

When a credential is discoverable, the authenticator also stores information about the account, so when a site requests “authenticate with this service’s account,” the authenticator can search for the appropriate candidate. This enables a login flow where the user selects an account without first entering a username.

In the case of non‑discoverable credentials, the service first identifies the account and provides the corresponding credential ID to the authenticator. The authenticator does not need to maintain a list of all registered targets.

Yubico’s explanation of U2F key generation describes how the key material is protected so that only the key itself can reconstruct it, while the key handle is stored externally. For subsequent authentications, that handle is returned to the key, which then restores the necessary key material internally for use. (source)

This point requires clarification when saying “the private key never leaves the device.” Not exposing the private key in a usable form is different from ensuring that no protected data ever exits the device. Even if you copy the handle, you cannot generate a signature with it alone; the original key is required to restore the key material.

While we cannot assume that this U2F explanation represents the internal implementation of every method, it does show that you do not need to think of each registration as adding a separate entry to the device’s list of keys.

On the other hand, there is a limit to how many discoverable credentials can be stored. The service provider documentation states that YubiKey 5 firmware versions 5.0–5.6.x can hold up to 25 credentials, while versions 5.7 and later can hold up to 100. You should not assume the capacity solely from the product name; you need to consider the firmware version and the type of credentials. The version of the device I have on hand has not been checked this time.

Relationship with Passkeys

The “passkey” that has become common lately also refers to a different scope than the YubiKey.

A passkey is a term for authentication that replaces passwords and uses FIDO credentials. They can be stored on a smartphone, a computer, a password‑management app, or on a security key such as a YubiKey. The FIDO Alliance’s explanation (source) distinguishes between synced passkeys and device‑bound passkeys.

Synced passkeys are made usable on multiple devices through the mechanisms of the supporting provider. While this makes them convenient even on a new smartphone, the accounts to which they are synced and the recovery methods for those accounts also become subject to management.

Passkeys created on a YubiKey are tied to the physical key. Even if you replace your computer, you can still use the same key by plugging it in. However, simply purchasing a new key for the same account does not automatically transfer the old key’s credentials to it.

Using a single YubiKey on multiple computers is essentially connecting the same authenticator to different devices. It does not involve distributing the private key to each computer. Conversely, the USB‑C and USB‑A keys I own must be registered as separate authenticators.

TOTP and HOTP

When using the Yubico Authenticator to display numbers, OATH‑TOTP or HOTP is employed. In this case, the authenticator and the service share the same secret.

TOTP uses the current time as its varying input, while HOTP uses a counter. From these inputs and the shared secret, an HMAC is computed and reduced to a length that is easy to enter as a numeric code. The HOTP mechanism is defined in RFC 4226 (source).

A highly abbreviated form of a TOTP looks like this:

Time slot number = floor((current Unix timestamp – reference time) / update interval)
Authentication code = calculated from the shared secret and the time slot number

If the update interval is 30 seconds, the same input is used throughout each interval, and the input changes when the next interval begins. The service can also compute the code from the same secret and time information, allowing it to verify whether the entered number matches. RFC 6238 (source) describes this time‑based method.

The fact that the service also holds the secret is what distinguishes it from FIDO authentication.

The advantage of using a YubiKey is that the secret needed for code generation is stored on the key itself and processed internally. Even if you open the authenticator app on a different computer, you can generate a code simply by plugging in the same key. The official OATH documentation (source) also explains this difference in where the secret is stored.

However, the generated number is returned to the app and is the information that a human enters on a website. Even when the secret is moved to hardware, there is no automatic mechanism—like the one in FIDO—to restrict where that number can be entered. Even when using a YubiKey, resistance to phishing varies depending on the authentication method.

The QR code read during enrollment is not merely decorative. In most cases it contains the secret used to generate the code and its configuration. From this principle, it becomes clear that such information should not be photographed and posted publicly.

Yubico OTP

When you insert and touch the YubiKey, a long string is entered into the input field. This behavior occurs when using features such as Yubico OTP, depending on the configuration.

Yubico OTP encrypts data that includes identification information, a counter, a timer, random numbers, and other fields with a shared AES key, then outputs the result as a string. In the standard configuration, the string is 44 characters long. The Yubico OTP documentation (source) explains the meanings of each field and the generation process.

The verifier checks the contents using the corresponding shared key and, using the counter and other values, ensures that a previously accepted token is not accepted again. This differs from the FIDO authentication flow described earlier, where the service provides a new challenge that is signed with a public‑key scheme.

Also, the timer in this scheme does not directly represent the current date and time. It tracks the elapsed time since the device was powered on. Assuming that, because it’s an OTP, it’s simply a six‑digit number that changes every 30 seconds leads to a misunderstanding.

Because USB can send characters as a keyboard, it can function like a dedicated input device. The same OTP application slot can also be used to store static passwords, HOTP values, or challenge‑response data. The slot documentation (source) shows that even short and long touch gestures are assigned to separate functions.

If you configure the slot to output a static password, the resulting string is, of course, not a one‑time value. You need to consider the convenience of the input method separately from the inherent properties of the authentication scheme.

Power and Clock

The YubiKey does not contain an internal battery; it draws power from the device it is connected to in order to operate.

When used over USB, it receives power from the host. NFC‑enabled models obtain the necessary power from the magnetic field of the reader. The device does not need to stay powered on while it is not in use. The product specifications for the YubiKey 5C NFC (source) also indicate that it does not require a battery.

Sensitive information and settings are retained in non‑volatile memory, so the device does not forget its enrolled data each time power is removed. It operates only when needed: it powers up, receives input, performs cryptographic processing, and returns the result.

When generating TOTP with a YubiKey, it uses the time information from the host device to which it is connected. The device does not keep an internal clock running on a battery and continuously update the display every 30 seconds. In fact, the Yubico Authenticator troubleshooting guide (source) advises checking the host’s clock when a TOTP is rejected.

With FIDO authentication, there is no need to generate a code based on the current time at all; you simply respond to the challenge provided by the service. The ability to perform one‑time authentication without a battery is also possible because the device can receive a different input each time from an external source.

Even though the key itself doesn’t need a battery, the host device must still be powered on. The fact that the YubiKey doesn’t require a network connection is separate from the network communication needed to log in to a web service.

PIV and OpenPGP

In addition to web‑login functionality, YubiKey also supports PIV and OpenPGP.

PIV is a standard for smart‑card‑based authentication and related operations, and the YubiKey can perform key generation, signing, and other processes. The PIV overview (source) shows the architecture in which an application sends commands and receives results. OpenPGP is also used for handling keys for signing, decryption, and authentication.

These can be used not only to generate keys internally but also to import private keys that were created externally. The OpenPGP API (source) also includes an import operation. When importing a key that was created elsewhere, a copy of the key may still exist in another location, which changes how backups should be considered.

Also, these signatures do not share the same domain restrictions as FIDO authentication. What operations are allowed on the data depends on the method and software being used. While they share the characteristic of being devices that store secrets, they are not equivalent even in the context of authentication.

Registering a Backup Key

In a 2023 article, I wrote that you should register both the key you carry with you and the key you keep at home. If you implement this approach with FIDO authentication, the two keys become independent authentication methods.

It is not a procedure that reads the private key created with the main key and copies it to the backup. Instead, you register both public keys with the service, creating a state where either key can authenticate the account. If you lose a key, you can log in with the backup and delete the registration of the lost key.

The FIDO Alliance’s enterprise white paper (source) also explains the practice of preparing backup credentials to account for the loss of a physical key and its recovery.

A backup that you merely purchase is not yet recognized by the service. Even if you try to register it after losing the main key, you will still need to authenticate in order to reach the registration screen.

Backups for TOTP work differently. If you want the same account’s code to be generated by multiple keys, you can register the same shared secret on each of them. The Yubico Authenticator documentation on backup keys (source) explains how to set this up. This needs to be distinguished from the practice of adding separate public keys to a service, as is done with FIDO.

Because the secret cannot be extracted, it also prevents you from conveniently retrieving it after a loss. A backup is designed to allow you to continue using that authentication method.

Post‑Login Sessions and Account Recovery

However, after logging in, services typically use sessions. Once you have been authenticated, you don’t need to touch the YubiKey for every subsequent action. Browser, device, and session management remain necessary. If the service requires re‑authentication before a critical operation, the key comes into play again at that point.

The same applies to account recovery pathways. While a method for regaining access when a key becomes unusable is needed, allowing recovery without re‑verifying the user’s identity would diminish the purpose of having a strong key. This is why authentication and recovery must be considered together.