Sunday, 21 October 2012



A YubiKey is a small USB key that is provided by Yubico [Edited to correct name]. When plugged into a computer, it provides a one-time password that uniquely identifies the YubiKey.


One YubiKey costs ~25USD (19.20EUR at the time of writing). Discounts are available for large purchase volumes.

Hardware Required

Computer of any major (Mac, Linux, Windows) OS. YubiKey token.

A software YubiKey could easily be implemented, e.g. as an application for a smart phone.


When a plugged into a host system, and a button on the YubiKey is pressed, a one-time-password is produced (OTP) and "typed" (by the fact that it is a USB HID) into the host system.

The OTP is as follows:

  • Secret ID (6B)
  • Session Counter (2B)
  • Timestamp (3B)
  • Session Use (1B)
  • Output from an LSFR (a psuedo-random number, 2B)
  • Checksum, CRC-16 (2B)
This is for a total of 16 bytes. The output is encrypted using AES-ECB and a 128-bit key which is also presumed unique to the device. This is then encoded in BASE16  [Edit 25th Oct 2012: It's not quite BASE16, it's referred to as ModHex and is specific to YubiKey. Thanks to Simon Josefsson] and "typed" to the host system.

The server which authenticates the device retrieves the plain-text of the OTP and verifies the secret ID. If the OTP decrypt successfully and secret ID matches a given username [Edit 25th Oct 2012: The sever also ensures that the session counter and Session Use have not already been seen and have increased monotonically. Thanks to Simon Josefsson], then the authentication was a success.



If the server is compromised, all keys must be re-issued (keys can be "re-burnt" without re-purchasing). This is because the authenticating server will spill all of the YubiKeys' AES keys and secret IDs. 


If the client is compromised (i.e. the key falls into the hands of an attacker), the attacker could disassemble the device and retrieve the AES key and the secret ID. This would allow them to arbitrarily forge a user's YubiKey authentication. 

An attacker could also perform a live man-in-the-middle attack, by tricking or forcing the user to reveal credentials, and subsequently using them to login to services. This is because the YubiKey does not verify the authenticity of the authentication request before sending a token.


If the procedure to generate the AES keys and secret IDs is not sufficiently random, an attacker could simply start guessing AES key/secret ID pairs and requesting authentication. I am not sufficiently familiar with the procedure for generating the AES keys or IDs, so it may be cryptographically strong (i.e. un-guessable without searching the whole space).

Hardening Techniques

First and foremost, protecting against man-in-the-middle attacks should be very high on the list, as it a very simple attack to perform. This means forcing the YubiKey to authenticate the authenticity of the request before providing credentials at any point. There should be no way to have the YubiKey present an OTP without it first verifying the credentials of a server (e.g. digital signature based challenge/response protocol). 

However, if you're implementing that, why not make it bi-directional (i.e. the server can authenticate the YubiKey using the exact same protocol)? Mostly because doing even single direction challenge/response authentication is very difficult, and breaks the assumption that the YubiKey is only a USB HID.

Secondly, if the server spills the AES keys and secret IDs, it is game over -- time to revoke the keys and force re-issuing or re-burning of the keys. A simple solution to have the YubiKey sign the OTP and send the signature to the server. The server would hold the public-key of the YubiKey. If this was spilt, it would not compromise the security of the system. This would, however, increase the length of the OTP substantially. It would also mean that secret IDs no longer need to be secret. This would not, however, protect against man-in-the-middle attacks.


Overall, the use of a YubiKey, combined with the use of a username and password (i.e. hardware and secret token for authentication) does make an authentication system significantly more secure. However, there is room to significantly increase the security of the YubiKey system, without major impact to the usability of the system.

Given that the YubiKey requires little extra software or hardware, it is a cost-effective and user-friendly method for increasing the amount of time, effort and skill an attacker must have to compromise a system.

Clarification, 2012-10-23 13:00

The hardening technique mentioned in the last paragraph is as follows:

  • The server maintains a list of YubiKey unique IDs/public keys.
  • The YubiKey writes out a message of the following format:
    • Unique ID
    • Session Counter
    • Session Use
    • Timestamp
    • PRNG output
    • Digital Signature of the above fields
  • The server can then verify the OTP by checking the following:
    • The ID is valid,
    • The Session Counter/Use is greater than previously seen counters
    • The digital signature is valid for the fields.

This output could optionally be encrypted using AES-EBC, but there's no need. The power of the system comes from the fact that the only place the private key is kept is the YubiKey (part of the assumption of this slightly modified system)

This would mean that should the server be compromised the unique IDs/keys be spilt, there would be no need to re-issue/re-burn the keys. This is useful when keys are used across multiple (>2 in the case of YubiKey 2.2), disconnected authentication servers (for example, if I used my YubiKey to gain access to my VPS host, to gain access to my banking and several other websites).

The YubiKey would need to also be able to "type" it's public key as part of registering itself with an authentication provider.

The draw backs of this modified system are as follows:

  1. Cost. You'd need to re-issue the keys for any system that already uses the YubiKeys, not to mention that you need more computational power to perform a digital signature -- each YubiKey would be more expensive
  2. You're relying on the digital signature algorithm. Depending on your algorithm chosen, will rely on the discrete logarithm problem or integer factorisation. These are assumptions, not guarantees.
  3. The OTP would be much longer when typed. I don't actually think this is much of a problem, personally. 


  1. Nice summary! Some comments:

    - The company is called "Yubico" not "YubiCo".

    - It is not quite base16, it is base16 with a non-standard alphabet. Yubico calls this "modhex"

    - To validate an OTP, you also need to compare counters against the last counters. Comparing secred id is not enough.

    - What do you refer to in your conclusion that the security can be improved without major impact to the usability of the system? The challenge/response schemes and asymmetric ideas you mention have significant deployment issues (drivers and too long output, respectively).


  2. Thanks for update. We have experimented with longer OTP outputs, and it turns out to be somewhat of an issue. Password prompts are sometimes limited in size (128 and 256 bytes are common limits) although that could in theory be fixed by modifying implementations. The limit that you really run into is however keyboard output pace, it turns out you need to wait a couple of ms between each character for things to work reliably cross platform. And a long OTP will thus result in a 1-3 second output time depending on algorithm and signature size. This is long enough that you run into some issues with other applications poping up windows and stealing keyboard input, or that the user accidentally hit the keyboard or move the mouse.

    Anyway, it is a good idea, and I think something could be built out of this (probably using ECC instead of RSA) but it is not as simple as you'd first think.


  3. ECC is almost certainly the way forward for this; though not from a security stand point, but because it provides shorter signatures.

    Assuming a 160b public key, the signatures would be 320b = 40B, plus the 16B that already make up the token = 56B. I'm not sure how this translates into ModHex, but it's below 128B, and would (assuming a 5ms/byte) take ~300 ms (i.e. 3 tenths of a second) to type. Even if you require two characters per byte (and therefore 10ms/byte), that's still 'only' 600ms.

    A 160b public key means that an attacker would need to see 2^80 signatures to derive the private key. Given that an attacker should not be able to generate keys at will (i f they could, what's the point of the token?) how are they going to find these 10^24 OTPs? Also note that given once the session counter is fixed at 0xFFFF (65536 = 2^16 OTPs), the timestamp is guessable and the session use+PRNG values are well within the scope of enumeration, the only data the encryption is protecting is the AES key and the secret ID. Even the session counter is quite vulnerable to guessing, given reasonable knowledge about the mark.

    It's also not like ECDSA is untested. I am lead to believe that it is what is used to sign transactions in the BitCoin protocol, and it was chosen primarily because it keeps the signature size small.