I was interested in "U2F" (Universal 2nd Factor) tokens, and took a closer look at the specifications and reference implementation code.

I got frustrated by the propensity of the authors of the various documents and source code to express and implement everything in a form myopic to the web "cloud" community. Granted, that is the trend de jour and where all the money is presently. However, having read it all, it seemed desirable to take a stab at describing U2F in plain engineer English:

The building block crypto algorithm of U2F is ECDSA (ANSI X9.62-2005).

All tokens have one public-key-pair programmed at the factory (with the public key in that pair signed by the token maker's Certificate Authority private key).

Additional public-key-pairs are generated on the fly by the token itself in response to REGISTER operations.

I'll use the term "authenticator" here to cover what the authors clearly intend to be a web site, but the U2F token could have more general usage. I'll use the term "intermediary" for what the authors intend to be a web browser or some sort of OS-level functionality; the "intermediary" facilitates communication between the "authenticator" and the U2F token.

Two operations exist: REGISTER and AUTHENTICATE. The former happens once initially when the token is introduced to authenticator. The latter happens each and every time the authenticator uses the token to help verify the identity of the user.

In a REGISTER operation, the authenticator (via the intermediary) provides two quantities:
challenge nonce (32 bytes)
application parameter (32 bytes)

The token generates a new public-key-pair and responds with:
public key (65 bytes)
key handle
attestation certificate
signature (computed using the FACTORY private key over future use byte, application parameter, challenge nonce, key handle, and public key)

The application parameter is the Achilles' Heel of the solution. If a malicious actor can manage to introduce the challenge + application quantities to the token for another authenticator, the token will be oblivious to the switch.

Everything hinges on placing faith in the intermediary not being compromised and the transport between the intermediary and the authenticator as being secure. To help prevent a malicious actor from feeding the token an arbitrary application parameter, the application parameter is not provided by the authenticator, but computed by the intermediary as a message digest using believed-good, unique information about the identity of the authenticator.

However, clearly, it would be desirable to not use the same token across multiple authenticators if security is of paramount importance.

Another important quantity is the key handle. Although it is not mandatory, it seems likely that this quantity is an encrypted version of the private key that is companion to the public key (both generated during the REGISTER operation). (The encryption method incorporates the application parameter for further uniqueness to the authenticator.) The operational advantage to doing this is that the token can be used with an infinite number of authenticators, since each authenticator is storing the private key (in hopefully adequately protected form) on behalf of the token.

ASIDE: The key handle seems fodder for lots of security research papers. The difference between a better and a lousy implementation is completely at the discretion of the U2F vendor, and there is no apparent visibility into what the design decisions were.

During the REGISTER operation, the authenticator can improve its trust of the legitimacy of the token by verifying the signature against the public key in the attestation certificate, and verifying the attestation certificate against a list of known good token Certificate Authority public keys. (This last bit seems to be a work in progress.)

In an AUTHENTICATE operation, the authenticator (via the intermediary) provides three quantities:
challenge nonce (32 bytes)
application parameter (32 bytes)
key handle

The key handle is the same as what was initially provided by the token to the authenticator during the REGISTER operation. (Likely, this is an encrypted version of the private key.)

In an AUTHENTICATE operation, the authenticator (via the intermediary) provides three quantities:
user presence (1 byte)
counter (4 bytes)
signature (computed using the associated private key over application parameter, user presence, counter, and challenge nonce)

Using the public key initially provided during the REGISTER operation, the authenticator uses the signature to verify the identity of the token.


back to main page contact