Categories: Security
Introduction
Yubico is a company which produces a number of hardware authenticator devices, ie small physical tokens that can be used to authenticate (log in) to IT systems.
I recently purchased a Yubikey4, and found the technical documentation very lacking; there is lots of info on the website, but most of it is pure marketing-level. Even the developer pages are either marketing-oriented or extremely detailed. Therefore this article contains results of some research I did myself on the topic. I’m a software architect, developer, and sometimes sysadmin - and that is the level at which this article discusses the Yubikey.
The content here is mostly Linux-specific; I’m using my Yubikey4 on Linux and MacOS.
The Yubico devices have versions from 1 to 4 (currently). Frankly, the set of available features, options, and the supporting applications are a mess. There is good functionality buried in there, but it takes some effort to find. Similarly, the management apps for them have lots of options that only apply to specific versions of keys and are rather confusing to use.
I hope this article helps you decide whether to buy a Yubikey4, and how to use it.
UPDATE: The Yubikey-5 is now available (since late September 2018). This includes support for FIDO2/WebAuthn.
Summary
To save you a lot of reading, here are my conclusions up front..
In my opinion, the coolest feature of the Yubikey4 is its OpenPGP support. This allows configuring multiple keys for logging in to SSH servers via a private key on the device, encrypting/signing emails, and signing files (eg Docker images).
Probably the most practical feature, however, is its support for up to 28 OATH TOTP credentials. TOTP is not the best authentication protocol, but is widely supported eg as Google login, and by many online banking sites.
The award for “most promising authentication” goes to FIDO2/WebAuthentication. The FIDO2 and associated WebAuthentication protocols are pretty new at this point in time (mid 2018). This appears to be an excellent solution, but currently only a few tools and websites support them. Hopefully at some time in the near future, FIDO2/WebAuthentication will become widespread and then most of the (rather confusing) options presented on the Yubikey website and in this article will become obsolete - instead, “just use FIDO2/WebAuthentication” will be the advice.
Sadly the Yubikey4 does not currently support CTAP2 (needed for FIDO2/WebAuthentication). The (cheaper) Yubico Security Key does support this, but does not support OATH or OpenPGP. Currently very few sites support FIDO2/WebAuthentication; hopefully by the time it is more widely used the Yubikey4 will have been enhanced (though existing keys are not upgradeable).
Despite the lack of FIDO2 on my Yubikey4, the somewhat high price, and the rather clumsy software, I don’t regret having bought it; the TOTP and OpenPGP support is cool and useful. The device has also proven pretty robust so far.
Why use a Hardware Authentication Device?
Just quickly, here are some very good reasons why a hardware authenticator device such as a Yubikey is a very good idea:
- Predictable Password Blamed for Gentoo Account Takeover
- Account Takeover and New Account Fraud Spike in 2017
- Lists of passwords leaked from various companies
At a personal level, dealing with passwords is a nuisance. Wouldn’t it be nice to:
- not have to invent and record a new password for each site you create an account with?
- to know that regardless of how incompetent that site is, they simply cannot leak your credentials (for some protocols)?
- to know that your login simply cannot be used without access to that device hanging on your key-ring (unless your credentials have been stolen from the target site)?
- to know that your credentials cannot be stolen by malware on your mobile phone?
At a company level, passwords are not only a nuisance for users (whether employees, customers or partners), but also open up a number of potentially costly and inconvenient security holes. Supporting authenticators instead of passwords can save a company a lot of trouble. With a Yubikey or similar device:
- a user cannot choose a bad password
- a user cannot be tricked into revealing their password
- malware on the user’s device can never steal the password (though an existing session can be “hijacked”)
- and it is actually more convenient for users
Some protocols require a shared secret between authenticator device and server (eg OATH, Yubico-OTP, Challenge/Response). Because these secrets must be stored on the target site (and cannot be hashed like passwords), they can potentially be stolen. However these credentials are only random values and are not reused between sites (like passwords often are). A server can potentially store its copy of the secrets in an HSM (Hardware Security Module) in which case the credentials are also almost unstealable server-side too.
Protocols using public/private key pairs (FIDO1/U2F, FIDO2/WebAuthentication, OpenPGP) are completely immune to leaks at the server side; the server side has only a public key component which is not confidential.
Yubico Products and Protocols
The Yubikey4 supports all of the following authentication protocols:
- static passwords
- challenge/response
- OATH-TOTP
- OATH-HOTP
- Yubico-OTP
- FIDO1/U2F
- PIV (Personal Identity Verification) smartcard protocol
- OpenPGP
The following is currently supported in the “Security Key by Yubico” but not the Yubikey4:
- FIDO2 and WebAuthentication
Hopefully later versions of the generic Yubikey4 will support FIDO2/WebAuthentication in the near future; sadly existing Yubikey devices cannot be upgraded with new firmware.
Note that OATH is not related to the very similarly named OAUTH protocol. OAUTH is not (directly) relevant for authentication tokens.
Yubico provide a number of desktop applications for configuring their devices. All applications are available on Linux, MacOS and Windows:
- Manager (configures most protocols, plus extended features)
- Personalization tool (configure the first 5 protocols above in two “slots”; check firmware type; set extended features; etc)
- Authenticator (for OATH HOTP and TOTP with named credentials)
- PIV Manager (for managing private keys accessed via the PIV smartcard protocol)
These applications are discussed in more detail later.
All Yubikeys have a button which can be pressed to confirm operations; some authentication operations require a button-press while others do not, and for some protocols each credential can be configured to require button or not. Obviously, requiring a button-press is more secure but also more annoying.
Product “FIDO U2F Key” supports only CTAP1 (ie the FIDO1/U2F protocol). Product “Security Key by Yubico” supports only CTAP2 (ie the FIDO2/WebAuthentication protocol). The NFC-enabled Yubikey Neo can be used with phones that do not have a USB port - but has limited processing capability and therefore does not support all protocols and can store less data.
Yubico may release Bluetooth-enabled devices in the future, or maybe not - they are not convinced Bluetooth is sufficiently secure. Presumably Bluetooth-based devices would require an internal battery.
Interestingly, Google announced in July 2018 that it has created its own authenticator device. The online docs are vague, but as far as I can tell, they sadly only support FIDO1 aka U2F - no OATH, FIDO2 or OpenPGP.
Data Transfer between Client Device (PC or Phone) and Yubikey
While it is not absolutely necessary to understand how a PC or phone actually exchanges data with a connected Yubikey device, I personally find it helpful to understand tech “one level below” the one I am using. Knowing the underlying details often helps when something goes wrong. This section can be skipped if you really don’t care.
There are two communication paths needed during authentication (except in the case of “one touch” authentication; see later):
- client to server
- client to authenticator device
where client is software running on the desktop/laptop/phone that a user is physically interacting with.
In general:
- the client somehow determines that the server needs authentication information, and optionally obtains authentication parameters (eg a challenge value)
- the client sends a request over USB (or NFC or Bluetooth) to the Yubikey as a sequence of bytes
- the Yubikey does some processing (usually including reading or writing data stored in its persistent memory)
- the Yubikey sends a response (as sequence of bytes) over USB (or NFC or Bluetooth) to the client
- the client builds an authentication request from the Yubikey response (wrapping it however the server expects) and sends it to the server
The client-server interaction is usually defined in some official standard. The following sections discuss the client-authenticator interaction for various protocols.
When a Yubikey4 is attached to a USB port, it announces itself as a “compound USB device” with up to 3 components:
- a USB HID device used for the basic/older protocols referred to as “OTP Mode” (see below)
- another USB HID device used for FIDO1/U2F and referred to as “FIDO mode” (see below)
- a USB CCID “smartcard reader” (with smartcard present) - also referred to as “CCID mode”
The Yubikey can be configured to present a subset of these interfaces if desired (ie to disable some encryption protocols).
USB devices announce their “class” (eg HID) when they attach. They also have “subclasses” and other attributes that can be used to further identify them.
USB HID
One of the available USB device classes is HID - meant to represent Human Interaction Devices such as keyboards, mice, and game controllers. The USB spec defines which message-types HID devices can send or receive; these include “mouse movement event”, “keyboard press event” and similar. HID devices are expected to be “low data rate” (compared for example to external graphical displays or external disk drives).
The two HID devices registered by a Yubikey4 are used for separate purposes:
- the first one is used to provide what is known in the Yubico documentation as “OTP mode”, and what I refer to as “one touch mode”, where pressing the Yubikey button generates emulated keyboard output. Data is actually bidirectional, and the host-to-device direction is used to configure the Yubikey “OTP-mode” settings (“slots”).
- the second one is used for bidirectional communication between a client app and the Yubikey using the CTAP1 (FIDO 1.0) protocol. This is known in the Yubico documentation as (fairly obviously) “FIDO mode”.
When support for CTAP2 is added (to support FIDO2/WebAuthentication) then presumably either the existing HID device for CTAP1 will be used, or the Yubikey4 will register yet another HID device.
USB CCID
Another available USB class is “CCID” - meant to represent “smart cards” with their own (low-power) processing units on them. A CCID cannot act as a keyboard or similar.
Until recently it was common for desktops/laptops to come with a built-in “smart card reader”. These are becoming rarer now; if support for smart-cards is needed then this is usually done via an external smart-card reader device which attaches to the host via USB. The Yubikey registers itself as such a USB-based smartcard-reader (and immediately indicates that it has a smart-card inserted into it).
The CCID specification defines how a “smart card” attached to a USB port should interact with its host system. This is an extremely low-level specification; it basically just covers how a generic request can be sent to the card, and how a generic response comes back, at the byte level.
See also standard ISO7816-4 for smartcards. Sadly, ISO standards are not published free-of-charge.
CCID defines several possible message types, including BULK_IN
which has a 4-byte header followed by a length-byte and variable-length data that depends on the request-type in the header. The header fields are:
- CLA – class
- INS – instruction id (eg PUT, DELETE, etc for OATH)
- P1 – param1 (depends on INS)
- P2 – param2 (depends on INS)
- Lc – length of variable data
- .. – variable data
The meaning of different values for class and instruction are not defined in the CCID specification; those are covered in higher-level standards.
A smartcard announces over CCID which “applications it is running”, eg in the case of a Yubikey:
- OATH HOTP/TOTP (using named credentials)
- OpenPGP
- PIV (Personal Identity Verification)
Note that these are not necessarily “applications” in the usual sense - probably more like an endpoint/subsystem/module. Each “application” then has its own protocol built on top of the basic CCID operations (in particular, BULK_IN
and BULK_OUT
).
USB HID/OTP Mode
The first USB HID device interface is used in bidirectional manner:
- a proprietary Yubico protocol (presumably built on top of the HID protocol) is used to configure “slot-related” functionality on the Yubikey and to query its status
- and when the button is pushed, the device emulates a keyboard and sends credentials (passwords, HOTP/TOTP codes, etc) to the host
This proprietary protocol is used only for credential setup/configuration; no custom software is needed for the Yubikey to emulate a keyboard.
The “slots” can support static passwords, challenge/response, Yubico-OTP, and slot-based HOTP/TOTP credentials. In other words, all the “older” Yubikey functionality (that stuff accessed via the Yubico personalization app) is done with this protocol.
I could find no documentation on the protocol used over this HID device, but it doesn’t really matter for this article; the protocol will be something like CTAP1. In any case, the point is that custom software on the client sends a request to the attached Yubikey and gets back a response.
Note that there are two separate implementations of OATH in the Yubikey - one for the old “slots” mechanism (HID-based), and one supporting “named” credentials (CCID-based).
Yubico does provide documentation for the server-to-yubico-authentication-server calls, but that is nothing to do with interaction with the Yubikey device itself.
USB HID/FIDO Mode
The second USB HID device interface is used in bidirectional manner to transfer CTAP1 (and maybe later CTAP2) messages to configure the Yubikey, query its status, and request authentication results (eg the next OATH-TOTP code for a named credential).
CTAP stands for Client to Authenticator Protocol (where a Yubikey is an example of an Authenticator). The FIDO1 protocol includes the CTAP1 specification, and the FIDO2 protocol includes the CTAP2 specification. You can read about CTAP1 here and CTAP2 here if you wish. However I think the main point is that (like other protocols):
- requests are sent over USB (or NFC or Bluetooth) from client software to the Yubikey as a sequence of bytes
- the Yubikey does some processing (usually including reading or writing data stored in its persistent memory), and returns a response (as sequence of bytes)
CCID/OATH
Setting up and using OATH features of a Yubikey is done by sending messages using (AFAICT) a Yubico-specific protocol built on top of the lower-level CCID protocol. Communication is mostly (exclusively?) done using the BULK_IN
and BULK_OUT
CCID messages addressed to “the OATH app on the smartcard”; the Yubikey site defines the different CCID header values and data-payloads used in the OATH developer page.
CCID/OpenPGP
An open-source group built their own smart-card for authentication and cryptography purposes. The card defines its own higher-level protocol (request and response messages) for registering keys, performing authentication, etc. on top of the base CCID protocol. Code interacting with this card sends CCID messages addressed to “the OpenPGP app on the smartcard”. The open-source GnuPG suite of applications includes an implementation of this protocol; the Yubikey4 also supports this protocol and is thus compatible with GnuPG applications.
The PKCS series of specifications define various protocols and data formats related to encryption and digital signatures. These specifications are not official standards (they are produced by the company RSA Security), but are respected and widely supported. PKCS#11 defines a software API for client applications to interact with an authenticator token. The GNU scute library implements the PKCS#11
API for the above smartcards (ie maps PKCS#11
api calls into CCID messages that transfer OpenPGP-smart-card data packets). A number of applications support the PKCS#11
API, including the Thunderbird email client (for signing and encrypting emails) and gpg-agent
for logging in to an SSH server. These applications can therefore interact with either an OpenPGP smart-card or a Yubikey.
See later in this article for more details on OpenPGP and SSH with Yubikey.
CCID/PIV
Some software (eg OpenPGP clients, and login for Apple MacOS) supports “PIV” (Personal Identity Verification) smartcards. The PIV protocol is also layered on top of CCID as an “application” on the smartcard.
Number of Credentials Supported by a Yubikey
As documented (briefly), the Yubikey4 supports:
- two “slots”, each of which can hold one of:
- static password
- HMAC-SHA1 challenge-response
- Yubico-OTP challenge-response
- OATH-HOTP
- OATH-TOTP
- 4 PIV slots which together represent one identity plus 20 additional slots (use not entirely clear)
- 28 “named” OATH-TOTP codes
- “unlimited” FIDO1/U2F keys
The “slots” functionality has been inherited from older Yubikey devices, and supports the older protocols. The more modern FIDO1/U2F, FIDO2/WebAuthentication and OpenPGP protocols are not stored in the two “slots”.
It isn’t clear from the documentation how many OpenPGP credentials are supported; maybe in the “20 PIV slots”, or maybe they share the “unlimited” U2F storage space?
One-touch Authentication (Yubikey Slots)
As noted earlier, a software application normally runs on the client machine (phone or desktop) which interacts with the Yubikey device.
Yubikeys have a button and support the ability to define a protocol and credential for “slot1” or “slot2” (only some protocols supported). When the button is pressed then the Yubikey acts like a USB keyboard and generates some text output that will end up in whatever text input fields are active at the time (whether commandline or GUI). A short press activates “slot1” and a long press activates “slot2”. This allows a Yubikey to be used to output credentials without needing any client-side software at all.
Yubikey devices with NFC support can be configured to use one of the two slots when activated via NFC (in particular, to send text output to a mobile phone when tapped against it).
This “auth without client software” feature only works for protocols that take no input parameters; the supported protocols are:
- static password
- challenge-response
- OATH-HOTP
- Yubico-OTP
Note that OATH-TOTP is not supported because the Yubikey does not have an internal clock (that would require a battery) and so the current time must be an input parameter.
Because input params are not accepted, the output cannot be site-specific, ie the “one touch” functionality cannot support a different password per site being logged into. This functionality is therefore not very useful for authentication on the internet in general. However it may be useful for specific purposes, eg a Yubikey device dedicated to authentication in a work environment, or one dedicated to a specific bank account.
Slot1 is factory-preset with Yubico-OTP credentials. This consists of a unique “public identity” (randomish 12-char sequence), unique “private identity” (bytes) and a unique AES key (16 random bytes). These values are pre-registered in Yubico’s own authentication server in order to support “self-provisioning”: when a server has integrated with Yubico’s own authentication servers, then it is only necessary to link the key’s ID to the user’s personal account. No setup of a shared “secret” (key) is needed as there is already a shared secret between the Yubikey itself and Yubico. The values in “slot1” can be overridden if desired. A company can also run its own Yubico-OTP servers if desired (though FIDO2 is probably a better option now).
The “settings” part of the Yubico-personalization app allows partial control over the keyboard-emulation that the Yubikey does when its button is pressed to generate “one-touch” output. By default, it produces the key sequence <tab>{public-id}<tab>{code}
, ie can also fill in “user-id” and “password” in a form.
In general, this concept of “one-touch” and slots is (IMO) ugly and becoming obsolete. The FIDO2/WebAuthentication approach is far more elegant - that supports a large number of unique keys, each with its own “name”. The server indicates which “named credential” it is expecting, and provides a random challenge, and the Yubikey effectively returns a digital signature of the challenge that the server can verify. This does, however, require software on the client device (which in the case of WebAuthentication is part of the browser itself). Even with HOTP/TOTP, it is (in my opinion) more elegant to just run the relevant client application and copy/paste the codes into the login fields when needed (which is not often).
Despite my personal opinion on the ugliness of the one-touch approach, the Yubico website documentation relies heavily on this. For example, the how to login to Linux information assumes that the user logs in with a “short press” on the Yubikey, thus activating the factory default credentials configured for “slot1”, and the server is set up to verify these credentials by making a request to Yubico’s authentication system. As an admin and architect with interest in security my opinion is that this is madness; I would never set up login on my servers like this. The Yubikey hardware itself is good, and can be set up to provide secure access - but the configuration advice on the website is not optimal for security (presumably presented like that so it looks simple for marketing purposes). Using the preset credentials might be an option when providing a lightweight service to customers over the internet (ie not login to a server commandline or similar).
Settings for “slot1” and “slot2” can be defined via the “Yubico Manager” application (aka ykman
) or the “Yubico Personalization” application (aka yubikey-personalization-gui
).
It is actually possible to disable the “OTP mode” (what I call one-touch authentication) completely via the Yubico Manager app. This is useful if the Yubikey is only used for OpenPGP/named-OATH/PIV/U2F functionality.
Touch Confirmation
When a credential is loaded into a Yubikey at some location other than slot1/slot2 (eg a named TOTP credential), a “require touch” flag can be specified. When this is set to true, then any attempt to use that credential for authentication will require the user to physically confirm by pressing the button on the Yubikey device (the device will not return its response to an authentication request until the press occurs). This is a minor inconvenience for the user, but ensures that rogue software on the client system cannot perform authentication without the user’s knowledge and cooperation.
This is a different use of the button than for “one-touch authentication”.
Device Security (unlocking a protocol)
For most supported authentication protocols, a “pin code” or password can optionally be set to prevent all use of that protocol (ie all keys of that type) until the pin is entered to “unlock” the protocol. After attaching to a USB port, the device is in locked mode. Each protocol that supports “unlocking” requires some kind of network message be sent by a software app.
This functionality requires software on the client system in order to send the unlock code to the authenticator device.
Of course, because the PIN is entered via software on the client, it is vulnerable to interception if the host system contains malware. However it does protect against physical theft of the key (the thief cannot use the device without knowing the pin).
Unlocking the OATH protocol (OATH credentials)
Each OATH credential (except those in slot1/slot2) has a “name” (bytearray).
Before using named OATH credentials, client software must send a CCID SELECT command to the Yubikey device, specifying the OATH protocol (application). When locking is not enabled, or the device is already unlocked, a simple “success” response is returned. When the device is locked, a challenge value (challenge1) is returned. The client app and Yubikey device then do a typical challenge/response algorithm:
- client sends a VALIDATE message consisting of
somefn(pin, challenge1)
together with another unique challenge value (challenge2) - Yubikey verifies this message (using its own copy of pin)
- Yubikey sends a response consisting of
somefn(pin, challenge2)
- client verifies this message (using its own copy of pin)
This message exchange allows both client and Yubikey to be sure the other knows the shared pin without it ever being directly transmitted. The client software can therefore be certain that the Yubikey (or whatever is on the USB bus) really knows the shared secret.
The client/Yubikey protocol for accessing OATH functionality is unfortunately somewhat “stateful”, ie two applications communicating concurrently with the key are not supported. The “get remaining data” instruction is the most obvious one; this supports “paging through” results from a previous instruction which produced lots of output. This statefulness is probably part of the (somewhat old) CCID standard; in practice it is unlikely to be a problem.
Unlocking the PIV Protocol
With PIV authentication, there are effectively three codes: PIN, PUK and Management Key. Unlocking PIV functionality is done with the PIN (each time the key is inserted into a USB port). If the PIN is entered incorrectly three times, then all PIV functionality is locked until the PUK “master id” is entered. Both PIN and PUK are 6-8 characters (digits recommended). When using PIV mode, you should set a PUK value and save it somewhere safe. All of these codes can be set with the Yubico PIV Manager application pivman
. Because PIN entry is part of the PIV standard, non-Yubico PIV software can also be used to change the PIN - but this will have bad consequences if the key has been set up with “use PIN as Management Key”. If you choose to use an explicit management key, then make sure you save that somewhere, as it will be needed when making any future changes as well as the PIN. See the PIV docs for more info.
With PIV authentication, there are effectively three codes: PIN, PUK and Management Key. Both PIN and PUK are 6 or 8 characters (digits recommended); the management key is a 24-byte 3DES key. There are two different ways of setting up security:
- Define a PIN and a separate management key. In this mode:
- the PIN is used only for unlocking the PIV functionality for use (encrypt, sign, authenticate) each time the key is inserted into a USB port
- the management key must be provided to reconfigure the key (including adding certificates and changing the PIN)
- the PUK is disabled
- Define a PIN and derive the management key from it. In this mode:
- the PIN is used for unlocking PIV “for use” and for reconfiguration
- the PUK “master PIN” can be used if the PIN is incorrectly entered multiple times
- the management key is not explicitly set (derived from PIN)
There are different tradeoffs:
- Having an explicit management key is a nuisance if you regularly add/change certificates, etc: it is a very long string that needs to be stored somewhere.
- Having a derived management key means that:
- there is no PUK as backup; if you enter the PIN wrong three times then the PIV module must be reset, losing all PIV credentials
- you must never use external PIV-compatible software to change the PIN (as they do not update the management key); use Yubico apps only.
See the PIV docs for more info.
Unlocking Other Protocols (other credential types)
I don’t have any details on the “unlock” messages for CTAP1/CTAP2, OpenPGP, etc. Presumably the necessary data-formats are defined in the standards somewhere.
Authentication Protocols
This section provides more detail on the different kinds of authentication that the Yubikey supports.
Static Passwords
A Yubikey can store static passwords, though this is not a good use of a Yubikey.
The Yubikey4 supports a maximum of two static passwords, one in each “slot”. The passwords can be set via the Yubico Manager commandline application or the Yubico Personalization GUI application. With a short or long button press on the Yubikey, the password is then emitted by the Yubikey as if typed on a keyboard.
Due to inconsistencies in the ways various operating systems and computers react to USB keyboards, there are some problems with a Yubikey replaying stored passwords as text. There are therefore two modes supported:
- Scancode mode, in which the Yubikey stores exactly the USB keycodes typed when the password was defined. This unfortunately can result in incorrect password playback when used on a different system (eg one set up with a different default keyboard layout).
- Modhex mode, in which the password must consist of only 16 specific lowercase letters; as such passwords are hard to create manually a Yubico tool is usually used to auto-generate them. Unfortunately modhex passwords are not compatible with sites which mandate non-alphabetic chars in a password. There are various workarounds, though the details were not entirely clear from the Yubico documentation.
A better way to manage login via static password (IMO) is to use one of the available password manager applications for desktop or mobile phone, and then to secure login to this application with the Yubikey. There are instructions on the Yubikey site for integrating with various applications - and the authentication will use one of the properly secure protocols.
Challenge-Response
In this approach, a “shared secret” is configured between the Yubikey and the target system. Authentication then works as follows:
- the server needing user authentication generates a “challenge value” (usually a random block of data)
- a client application on the desktop or phone forwards the challenge to the Yubikey
- the Yubikey creates some response based on
fn(challenge, secret)
and returns it - the client forwards the response to the server
- the server uses its own copy of the same shared secret to verify that
fn(challenge, secret)
gives the same value that it received.
When the value received by the server matches what it has computed on its own, then the client (actually the Yubikey) must know the secret, and is therefore valid. The nice benefit of this approach is that:
- the secret itself never passes across the network (except once during account setup)
- the challenge value, and thus the response value, is different for each login (resistent to replay attacks)
A Yubikey4 supports a maximum of 2 different challenge/response secrets (slot1 and slot2).
The challenge-response protocol uses the standard HMAC algorithm to compute fn(challenge, secret)
.
The HOTP and Yubico-OTP protocols are similar to challenge-response, except that the Yubikey generates the challenge itself rather than accepting one from the system it is authenticating to; the challenge is simply an incrementing integer (ie a counter) stored on the Yubikey and thus no client software is needed. TOTP also works similarly; the Yubico authenticator app provides the challenge value to the Yubikey - the current timestamp from the host system. See the sections on these specific protocols for more details.
OATH TOTP (Time-based One Time Password)
TOTP is a design-pattern for authenticating using an underlying secret that is never passed over the network. It is essentially a challenge/response protocol where the challenge is an implicit value (the current time). The Initiative for Open Authentication (OATH) has published a specification for TOTP, which Yubico implements
A Yubikey can be configured with up to 28 named credentials (secrets) for TOTP. A command can then be sent to the Yubikey with a timestamp value, and the device returns a 6-digit pin number which is effectively HMAC(secret, timestamp). This 6-digit pin can be submitted to some other system which also has access to the same secret and thus can verify the response.
Usually, the timestamp used is the current time rounded to the nearest 30 seconds. This approach is pretty secure, as:
- an intercepted code is only valid for 30 seconds
- a very large number of codes would need to be intercepted to even start to deduce the shared secret
The Yubico authenticator application is needed to communicate with a Yubico key in order to generate TOTP codes. This is available for all major desktops (Linux, Windows, Mac) and for Android.
The Yubico manager application is needed to configure the Yubikey with credentials. One of the disadvantages of TOTP (when compared to public/private key algorithms such as U2F or FIDO2/WebAuthentication) is that both ends need to have the same secret configured.
Optionally, a credential can be configured to require a keypress on the Yubikey before returning a code. This prevents rogue software on the client system from interacting with the Yubikey to generate TOTP codes without the user’s knowledge.
Optionally, the entire OATH subsystem on the Yubikey can be protected with authentication, requiring Yubikey OATH functionality to be “unlocked” (via a pin entered into the Yubico authenticator app) each time the key is inserted.
The TOTP protocol is very popular; lots of secure systems support TOTP codes (eg by requiring the user to type in the code in a field of an html login form). In fact, some banks have offered dedicated hardare tokens for TOTP for many years; they are credit-card-like (or USB-stick-like) devices with a small LED screen that shows a code that changes every 30 seconds; the Yubikey TOTP support is just a more flexible version of these tokens (but does require client software capable of communicating with the Yubikey device to be installed).
The 6-digit (or 8-digit) pins returned from the Yubikey (eg via the Yubico Authenticator app for desktop, or the Yubico Authenticator app for Android) are 100% compatible with pins returned from the Google Authenticator application. Google Authenticator is an Android app which also generates TOTP codes, but does not require a physical key - it just stores the secret and does the computation directly on the phone. The Google Authenticator app is less secure than using a Yubikey for two reasons:
- when the phone is stolen (and unlocked), the thief can use Google Authenticator but cannot use Yubikey Authenticator without the matching Yubikey device
- malware on the phone can potentially steal Google Authenticator secrets; this is not possible with Yubikey Authenticator (particularly when keypress-required is enabled for the credentials).
TOTP can also be used for logging into operating systems. PAM modules for Linux and MacOS can be configured with the same shared secret, and the TOTP pin-code then used as the password (or appended to it). Ths requires client and server clocks to be approximately in sync. The interactions are:
- user uses Yubico authenticator application to generate a 6-digit pin
- user enters username as usual for login
- user copy/pastes or retypes the 6-digit pin from Yubico authenticator into login password field
- user submits login request
- server retrieves shared secret for user
- server takes current server-side timestamp and truncates it to nearest 30 seconds
- server computes HMAC(secret, timestamp) and compares it to submitted password
As an example, the process for enabling TOTP-based login at dropbox.com is:
- create an account with the usual name + password
- go to account settings and select “enable two-step verification”
- dropbox then generates a “secret” for your account. It presents this value as a QCode on the screen; if running an OATH client app on a mobile phone then you can start that app and scan the code to import the code. Alternatively you can select “enter manually” then copy the code text (a string of 25 chars) and paste that into the Yubico Manager application as an OATH credential.
OATH HOTP (HMAC-based One Time Password)
HOTP is a design-pattern for authenticating using an underlying secret that is never passed over the network. It is essentially a challenge/response protocol where the challenge is an implicit value (a counter that both ends of the authentication keep approximately in sync). The Initiative for Open Authentication (OATH) has published a specification for HOTP, which Yubico implements.
There are two separate HOTP implementations within the Yubikey:
- for “one-touch authentication” (OTP mode), limited to the two “slots”
- up to 28 “named” credentials (CCID mode)
Once a Yubikey is configured with HOTP credentials, a command can then be sent to the key with no parameters, and the key returns a 6-digit pin number which is effectively HMAC(secret, counter). This 6-digit pin can be submitted to some other system whch also has access to the same secret and an approximately synchronized counter. The Yubikey internally maintains a counter which it increments each time it generates a pin (password).
Both client and server need the shared secret and counter. The server must keep the “last counter received from client” (ie per-client state), and never accept any pins less than this counter (to block replay attacks). When a login attempt from a client does not match the expected counter, the server can try expected+1 up to expected+n in case it missed some client login attempts, but N should be low.
Because no input parameters are required (the counter is implicit), HOTP credential can be used in the “one-touch” slots, in which case pressing the button on a Yubikey causes it to emit the 6-digit pin as a string of characters, as if typed on a keyboard. This makes it possible to fill out password fields in web forms or applications without needing any custom software on the client machine at all (though configuring the Yubikey does require using the Yubico manager software at some time). This no-software approach might be particularly useful when using public PCs (eg at a library). Because pins are “one-time” codes, intercepting them is not useful. Note however that using public PCs still makes the user vulnerable to many attacks.
Interacting with named HOTP credentials requires using the Yubico Authenticator application.
The HOTP protocol can be used as a replacement for the “one time password lists” that are sometimes used by banks for authenticating financial transactions (as long as the bank server side uses the official HOTP algorithm for generating the passwords/pins, and the shared secret is loaded in to the Yubikey).
Sharing secrets with QR codes
Both TOTP and HOTP require having the same “secret” on both ends of the authentication. During account setup, websites often auto-generate the shared secret and present it to the user as a QR code image (a graphical 2-dimensional barcode).
When the user is running an OATH client app on a mobile phone, the client app scans the internal graphics buffer to find the QR code and extracts the shared secret from it (even though the content is in a window belonging to another app - eg a web browser).
When running an OATH application on a PC/Laptop, then some apps on some operating systems can also scan the currently displayed graphics buffer for QR codes. However other operating systems forbid apps from accessing content in other windows; in particular Wayland on Linux prevents such arbitrary access for security reasons.
Most websites which offer QR codes for OATH secret setup also have a button that shows the underlying text for the shared secret; when QR code scanning does not work then this text can be copy/pasted into the Yubico OATH application.
After this setup step has been run once, all other authentication is done with TOTP/HOTP which does not need to pass the secret over the network, and which generates codes that cannot be reused by an attacker if they are intercepted.
Yubico-OTP
Yubico OTP is a Yubico-specific authentication scheme (a variant on OATH HOTP).
Like HOTP, the “challenge” is an implicit integer counter which must be kept approximately in sync on both client and server. The primary difference from HOTP is that the Yubico algorithm embeds the “private identity” identifier of the Yubikey into the response. This allows a server to use just the response alone to perform authentication, rather than require a (userid, response) pair.
Yubico-OTP authentication requires the server-side to either:
- run an instance of the Yubico-OTP authentication software, or
- make calls to a Yubico-hosted authentication server.
As with HOTP, a Yubico-OTP credential stored in “slot1” or “slot2” is output as if typed on a keyboard when the button is pressed, allowing a Yubikey to be used without any client software.
The generated id can be used instead of a password, or in addition to one.
The terms “public id” and “private id” occur in the configuration settings for Yubico-OTP. As far as I can tell:
- public id is the “username” with which you log in to some app or site
- private id is the id under which the shared secret is registered in the back-end authentication server
Yubico provides “plugins” for various systems that allow integration of Yubico-OTP into other apps as a replacement for standard passwords. Supported systems include Windows login, PAM, and FreeRADIUS.
Each Yubikey comes with a factory-preset id in “slot 1”, meaning that systems which simply integrate with Yubico’s authentication servers do not need to set up any secrets on the device. This is called “self-provisioning” in the Yubico documentation. Depending on an external server for authentication has obvious reliability and privacy implications; if these are not acceptable then you can run your own Yubico-OTP server and overwrite slot1 with new (public-id, private-id, secret) values.
FIDO 1.x (U2F, UAF)
U2F is an authentication protocol from the FIDO Alliance; it was really designed to be a “second factor” for logins, ie (username, password, u2f-code) are required for login. UAF is a similar spec, intended for “passwordless logins”. Together U2F/UAF are effectively “FIDO 1.0”.
The U2F standard (aka FIDO1) defines a USB protocol for communicating with Authenticators (security devices such as Yubikey) which register as USB HID devices; the specification is here. This protocol is also known as CTAP1 (Client To Authenticator Protocol 1).
Unlike other protocols discussed so far, the client-software part of U2F was designed to be built in to a web-browser, making the transfer of the “challenge” data from server to authenticator, and the transfer of the authenticator output to the remote webserver transparent to the user. The result is that the user just needs to enter a user-id (and “unlock” the authenticator with a pin if that is configured and has not yet been done); the remaining authentication steps happen automatically.
Browser support for U2F is uneven:
- Chrome supports U2F fully
- Firefox supports U2F partially (sufficient for login, but not for registering new accounts)
- No other browser supports U2F as far as I know
Firefox U2F support is not enabled by default; you need to set property security.webauth.u2f
in about:config
. Firefox does not support the “key registration” flow; keys need to be registered via Chrome. However once the Yubikey has been “paired” with an account using Chrome, Firefox is able to use the Yubikey to log in to that account.
U2F never really got popular. There was one major authenticator-side supporter (Yubico), and one major server-side supporter (Google) - no surprise, as Yubico and Google invented U2F together. A hundred or so other sites support U2F (server-side) - but there is no guarantee that any browser other than Chrome works with them (Firefox tests its U2F support mostly against Google’s authentication services).
It is also possible to use U2F for login other than to websites. Yubico provides a Linux PAM module which authenticates local logins to a Linux server by using the CTAP1 protocol to communicate with an attached Authenticator. If you have a Yubikey4, then in my opinion using the PIV (smartcard) functions would be a better (more standard) choice.
FIDO2/WebAuthentication
Following U2F (aka FIDO1), the FIDO Alliance defined an updated standard, FIDO2. The Yubico FIDO2 page is actually quite well written, and I recommend reading it. The FIDO Alliance page is also good. However for completeness of this article, this section describes FIDO2 in my own words.
FIDO2 works similarly to FIDO1 (U2F):
- uses public/private keys
- expects the server to provide a random challenge
- uses the Authenticator device to generate a digital signature of the challenge for the server to verify with the user public key
The FIDO2 specification has multiple parts:
- WebAuthn - a javascript API for interacting with an authenticator, and for performing authentication steps; the specs is actually defined by W3C
- CTAP2 - the client/authenticator-device protocol for interacting with external authenticators such as a Yubikey
- A way of interacting with “built-in” authenticators
The FIDO2 standard aims to support both (username, password, code) and just (username, code) for login.
FIDO2 includes backwards-compatibility for U2F credentials (ie U2F public/private keys).
There are two parts to authenticating a user:
- client interacting with server (FIDO2)
- client interacting with auth-device (CTAP2)
The client/server interaction also has two use-cases:
- registration of shared credentials with a server
- authentication using the shared credentials
The FIDO2 spec defines the wire protocol used to communicate with key-storage devices, known as CTAP2 (FIDO2 Client To Authenticator Protocol). A client therefore only needs to implement this protocol once, and should be compatible with all USB-based, NFC-based or Bluetooth-based “security key” devices. The “Security Key by Yubico” is CTAP2-compliant, and hopefully a future version of the Yubikey4 will also implement this. FIDO2 authentication support for PAM, RADIUS, etc. will hopefully be available soon.
The FIDO2 specification also requires support for the W3C-defined WebAuthn
low-level API for javascript to interact with an authenticator device; web-browsers are expected to provide an implementation of this API which maps function calls to CTAP2 messages. At the current date, the most widely-used web-browsers have implemented WebAuthn support.
The way the protocol works is that the site provides its id (usually its base url). A public/private key pair is then generated and stored within the Yubikey; the public part is also sent to the site. When the browser later connects to that website, it gets an “authentication required” message back, with the site-id and a random “challenge” value. The browser then forwards (site-id, challenge) to the Yubikey together with the webserver origin (server host/port, not full url) and some other connection info. The Yubikey uses the site-id to select the matching private-key then generates a digital signature of (challenge, origin, other-stuff). That signature is then forwarded by the browser to the server, which validates the signature using the public key of the user. The challenge ensures that replay attacks cannot be used, and the origin plus other info protects against man-in-the-middle attacks.
It isn’t quite clear how many FIDO2 keys a Yubikey4 device supports; the documentation just says “unlimited”…
Note that no Yubico software is used when configuring a new key (unlike HOTP/TOTP, where Yubico Manager must be used); the browser provides all the necessary client-side logic.
FIDO2-compatible software includes:
- Chrome Browser (since v67, May 2018)
- Firefox Browser (since v60, May 2018)
- Microsoft Edge Browser (since May 2018)
- Microsoft Windows Hello plugins
- Probably more..
Windows Hello is part of Windows 10 and later; it is most widely known for allowing login via an image of the user’s face. However internally, Windows Hello effectively integrates the FIDO2 authentication flow into the standard windows login process, allowing any FIDO2-compliant system to be used to authenticate a user (kind of like a limited PAM for MS-Windows). The result is that the Yubikey can be used to log in to Windows; when the Yubikey has a PIN set for FIDO2, then login requires both device and pin (2 factors) and when no pin is set then login just requires the device only.
A browser can support WebAuthentication without an external authenticator; the FIDO2 authentication mechanisms are still better than using passwords even when the credentials (private keys) are stored on local disk by the browser. When the operating-system provides a central FIDO2 authenticator in software, that is better (eg Windows 10 provides this). And a dedicated Authenticator device is even more secure.
It is not yet clear whether Apple will support FIDO2 in their browser (Safari) and their web services.
PIV (Personal Identity Verification) Smartcard Authentication Protocol
A NIST standard defines a protocol for client software to talk to smartcard devices for the purpose of authentication. Yubico implements this protocol.
This protocol is used reasonably widely within the US Government. A moderate amount of additional software also supports PIV, including MacOS login.
OpenPGP (Pretty Good Privacy)
OpenPGP is a public/private key system for signing and encrypting data. OpenPGP is an official standard, derived (with permission) from the proprietary PGP suite of applications. The GNU Privacy Guard project (aka GnuPG or GPG) provides an open-source implementation of the OpenPGP standard.
The most common uses for OpenPGP are:
- to encrypt emails
- to digitally sign emails
- to digitally sign files (eg docker images)
- to authenticate against an SSH server
As mentioned in section CCID/OpenPGP, the open-source GnuPG suite implements a protocol for talking to authentication tokens; this protocol is not part of the OpenPGP standard but has nevertheless become a “defacto standard”. The Yubikey4 supports this protocol and can therefore be used together with GnuPG (or any other compatible client software) to do key setup, encryption and signature-creation. Yubico does not provide its own software for OpenPGP; you just use GnuPG or any compatible alternative.
The PKCS#11 standard defines how a “smart card cryptography token” should interact with a system (over USB or other), and a Yubikey4 announces itself as a smart card
when connected. Any software designed to work with such a smart card therefore works with a Yubikey. The GNU scute library is one such tool. And fortunately, a number of applications support PKCS#11
including the Thunderbird email client (for signing and encrypting emails) and gpg-agent
for logging in to an SSH server.
A Yubikey contains four OpenPGP “slots” for different purposes (sign, encrypt, authenticate, card-authenticate); each slot may contain a single OpenPGP key. In practice, some (or all) of these keys will be subkeys of other keys. The “card-authenticate” slot is not often used. PGP keys themselves have “usage flags” embedded into them which limit what they can do - Sign, Encrypt, Authenticate, Certify; the first three correspond to the first three slot-types within the Yubikey. The “certify” flag is used on keys that can sign other keys.
The public parts of the keys loaded into the Yubikey should be placed somewhere internet-accessible, eg on your own webserver or uploaded to a public keyserver. The easiest solution is to use the GPG command gpg --send-keys ..
to publish the public parts of these generated keys to the standard OpenPGP keyservers (indirectly, by publishing DNS records).
Configuring OpenPGP Keys
The simplest approach to configuring a Yubikey for OpenPGP is to get the Yubikey to create OpenPGP keys within the device. These keys can be used for signing, encrypting, and authenticating - but because the private keys can never be extracted from the Yubikey, if the Yubikey is lost or damaged then you lose access to all encrypted data, must publish a new signature, and must reconfigure all servers you authenticate against with the new public key.
A slightly more complex approach to setting up OpenPGP keys is to use a desktop system to create a single key with certify and encrypt abilities, and subkeys with sign and authenticate abilities. Back this key up somewhere secure (eg a USB stick in a bank safe). Then load the three keys (master, and two subkeys) into the appropriate slots in the Yubikey. If the Yubikey is lost or damaged, you can reload everything from the backup into a new Yubikey device. You can also potentially load the same keys into multiple Yubikey devices, eg as backups or for team use.
The most secure approach is to create a master key with just the certify usage enabled, create a subkey for each purpose you need (sign, encrypt, authenticate), and load just the subkeys (and not the master key) into the Yubikey device. The master can then be kept safely backed up and offline, just in case new subkeys need to be created. The master key is really your identity; even though Yubikeys are designed to make it extremely difficult to extract keys from it, having the master safely offline is even better. As with the previous approach, the same subkeys (or different subkeys of the same master key) can be loaded into multiple Yubikey devices if desired. When the entire master key is not in the Yubikey, then at least the public key part must be loaded into the Yubikey in order to provide a full chain of authentication for the subkeys.
The first two approaches are documented by Yubico. The offline-master approach is documented by Eric Severance (esev) here. The scute documentation also has some examples of how to set up PGP keys in a hardware token.
It is recommended that the master key be created on a PC, and kept on a USB stick or similar which is stored somewhere very safe. It is also recommended that subkeys be created on a PC and stored in safe offline storage like the master (possibly on the same device), and then the subkeys be loaded into the Yubikey. Potentially the same subkey can be loaded into multiple Yubikey devices.
Here is a brief summary of the (most complex) process as recommended by esev; it takes a while (maybe an hour the first time), but only needs to be done once for a Yubikey.
# Temporarily disable standard keyring
mv .gnupg .gnupg-orig
# Make a clean, configured keyring
mkdir .gnupg
chmod 0700 .gnupg
echo "cert-digest-algo SHA512" >> .gnupg/gpg.conf
echo "default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed" >> .gnupg/gpg.conf
# Make a backup dir (ideally on a mounted USB key)
export backupdir=...
mkdir ${backupdir}
chmod 0700 ${backupdir}
# Create master certification key
gpg --expert --full-generate-key
# choose "RSA - set own capabilities"
# change permissions so that only "certify" is enabled for this key
# accept all other defaults
# Get created key id
gpg --list-keys
export keyid=... # appropriate id
# Create a revocation certificate for the master, just in case
gpg --gen-revoke ${keyid} > ${backupdir}/${keyid}-revocation-cert.asc
# Create an encryption subkey of the master key
gpg --edit-key ${keyid}
# > addkey
# choose kind = RSA encrypt only
# > save
# Export the master key (and its encryption subkey) to backup storage
gpg --export-secret-key ${keyid} > ${backupdir}/${keyid}-secret.pgp
# Create signing and authentication subkeys (inside Yubikey, directly in appropriate slot)
# using the specified master key as the created key "parent"
gpg --edit-key ${keyid}
# > addcardkey
# select type = signature
# > addcardkey
# select type = authentication
# save
# And finally, load the manually-created encryption subkey into the Yubikey too
# Command "key 1" selects the first subkey (which is the encryption key, marked with an E) - and
# marks it in the output with an asterisk
gpg --edit-key ${keyid}
# > key 1
# > keytocard
# select type = encryption
# > save
# Add a keyserver URL to the master key, and push the master public key to the keyserver
# As keyserver, you can use the full path to a file on your webserver, eg 'https://yourwebserver/keys/{keyid}.asc'
# or you can use the hkps protocol plus path to a host, eg 'hkps://hkps.pool.sks-keyservers.net'.
#
# Note that because the backup has been made before this change, you will need to redo this if reloading the master key from backup
gpg --edit-key ${keyid}
# > keyserver
# Enter path to a keyserver (your server via https:// or public one via hkps://)
# > save
gpg --armor --export ${keyid} > /tmp/${keyid}.asc
# then do one of the following..
scp /tmp/${keyid}.asc ... # copy to your own server, then ensure it is accessible at the specified {keyserver-url}
gpg --keyserver {hkps-serverurl} --send-key ${keyid} # publish to public openpgp keyservers
# Remove the temporary key-dir and restore the default dir (if any)
rm -rf .gnupg
mv .gnupg-orig .gnupg
# Various final tasks..
gpg --card-edit ${keyid}
# > admin
# > forcesig # ensures keypress on Yubikey is required for each generated signature
# > url
# Enter keyserver url from earlier
# > fetch # fills local filesystem-based GPG keyring with public key from above URL plus "stubs" pointing to keys on the card
# > quit
# And if you have not changed the Yubikey PIN values, do so now..
gpg --change-pin
GPG normally expects keys to be stored on the local filesystem under ~/.gnupg
. When an authenticator (eg a Yubikey) is used, then the local keyring instead holds “stubs” that tell GPG to delegate to the authenticator device; the “fetch” command creates stubs for each key on the authenticator. The fetch
command also appears to import the default SSH key ~/.ssh/id_rsa
(if it exists) into the GPG keyring.
Why is the encryption subkey created on the PC and backed-up, but the signing and authentication subkeys are created on the Yubikey where they cannot be backed up? Simply because a new signing key can be created when needed; recipients will accept a signature as valid when signed with any valid subkey. Similarly, a new authentication key can be created when needed. Getting the Yubikey to create these subkeys itself is the cleanest solution; the keys then never exist outside of the Yubikey protected memory. However encrypted data can only be decrypted with exactly the correct subkey, so it should be created on a PC so that it can be backed up (despite the very slightly higher security risk).
Ideally the system on which the keys are created is transient (eg a PC booted from a live CD for security), so that no trace of the created keys exist outside of the Yubikey and the backup.
If addcardkey
, keytocard
or gpg --card-status
give you “No SmartCard daemon” then (for Ubuntu) run sudo apt install scdaemon
.
You will need the Yubikey openpgp PIN code and the admin PIN code; the defaults are 123456 and 12345678. The pin can be changed with gpg --change-pin
and the whole OpenPGP module on the Yubikey can be reset with ykman openpgp reset
.
The details of using OpenPGP for SSH login are described later.
Software Authenticators on Mobile Phones
There are several “software authenticator” applications available for mobile phones which support HOTP/TOTP. These do not use an external hardware key (like a Yubikey); they are better than using a plain password for authentication but not as secure as a Yubikey. The site being logged into prompts for a code; the user then uses the authenticator app to get a code and paste it into the site’s login window.
Probably the best-known software authenticator application is Google Authenticator.
Other software authenticator apps for mobile phones include:
The three tools above are “cloud based”, ie the secret is actually stored on a remote server, not on the device. Security then relies on secure login to that site, ie relies on the fact that only your phone can log in to retrieve credentials. However this is not usually true; such systems provide multiple ways to get access to your stored secrets. Remember that the point of two factor authentication is:
- something you know
- something you have
If authentication to your store of secrets is also based on “something you know” then that is “two things you know”, and not real two factor authentication. However at least all of these systems ensure that there is a unique secret per site/account, rather than tempting users to reuse passwords across multiple sites.
Possibly the best of both worlds is to use a password-service such as one of the above, but authenticate to it using a Yubikey.
As noted earlier, the HOTP and TOTP protocols require both the client and server sides to share a common secret (key). The use of QR codes to do this is discussed earlier in this article.
Google Authentication
Overview
As Google’s GSuite services (including GMail) are so widely used, the specific authentication options supported by Google are discussed here. Other sites may use some of the same approaches. Much of this content repeats info already presented earlier - but in the specific context of login to Google.
The currently-supported two-factor authentication options for logging in to Google are:
- Authentication codes via SMS (user must be online)
- Google Authenticator/TOTP (code-generator may be offline), or compatible (eg Authy app)
- Google Prompt
- Backup Codes
- U2F via Web-browser
SMS
SMS has a number of weaknesses; in particular attackers regularly persuade phone companies to “port” an existing mobile phone number to a new device and therefore get access to the SMS texts. There are other ways to intercept SMS messages too - they are an old technology that was not designed with high security in mind.
Google Authenticator / Yubico Authenticator
The Google Authenticator App for Android/IOS/etc is simply a TOTP code generator; click on it to get a current time-based code that can be copy/pasted into a login field. The Google Authenticator app stores the shared secret used to generate codes locally on the phone, which is not ideal. The Yubico Authenticator app works identically to Google Authenticator, but the secret is stored in a Yubikey device which is much safer. Various applications for desktop computers also exist for generating TOTP codes from locally-stored secrets.
Google login via time-based authentication codes (OATH-TOTP):
- basically, each side (Google and you) compute hash(key, now % 30 secs)
- locally, you use a TOTP application (Google Authenticator, Yubico Authenticator, or other)
- then paste the output of authenticator into the Google login field
Google Prompt
Google Prompt is a mobile phone app which supports “push messages”, where a remote server sends a message to a phone. The application then prompts the user to confirm login to the server, and sends some kind of confirmation to the originator of the push message. This supports an elegant 2FA login to the Google site:
- user visits site and enters username/password
- site looks up phone id from username
- site sends push message to phone
- authenticator asks user “do you wish to login?”
- authenticator sends TOTP value to Google site
- Google site detects valid response for user and links it to the (recent) login attempt
- login attempt is authorized
There is no Yubico equivalent to Google Prompt.
Various companies provide similar apps for login to their sites (eg Microsoft, Blizzard).
I cannot find any details on the protocol used to communicate between server and Google Prompt app, ie it is not clear how the server side ensures that it is talking to the correct phone.
The Google Prompt application provides some kind of API which allows other sites to also validate login via the Google Prompt application on the user’s phone. I don’t currently have any details on that, and it is out of scope for this article.
Backup Codes
The security configuration settings within Google allow a user to generate a list of a few dozen “backup codes” for login. These can be printed out and stored somewhere safe - an excellent emergency fallback. This is of course google-specific, ie these codes cannot be used on other sites. Creating backup codes for every site you have an account with is not so convenient.
U2F
Google login via U2F (ie FIDO1 authentication) is fairly easy to set up, and very easy to use - provided you have compatible software.
When registering your U2F token (eg Yubikey4) against your account, it is necessary to use a Chrome browser; no other browser correctly supports the U2F registration flow as far as I know.
When logging in to Google using a U2F-enabled browser, a user-id and password must be entered as usual; the “2FA” component is then silently provided by the attached token without any further steps on the user side.
Google Chrome is obviously a U2F-enabled browser. Firefox U2F support works sufficiently for login, but U2F support must be explicitly enabled first: go into “about:config” and set security.webauth.u2f
to true. Neither Safari nor Internet Explorer support U2F, and are not likely to ever support U2F - instead, they are implementing FIDO2/WebAuthentication.
Note that if you have previously logged in with 2FA eg via phone, and selected “dont ask again on this device”, then clear all “*google*
” cookies first to force 2FA login.
General Notes
Mobile phones with access to Google accounts (eg Google mail) are a security problem, as the “second factor” for login is actually the phone itself. A separate key (Yubikey etc) is therefore a good idea. However plugging a key into a USB port does not work for mobile phones (no ports). The Yubikey-neo supports NFC, and can be “tapped” against an android phone to have the same effect. Doesn’t currently work with Apple.
One of the greatest advantages of a Yubikey over an “auth app” on a mobile phone is that the key is simple. It does not run any apps, does not run a separate embedded “baseband processor” with software from the phone manufacturer, etc. It is thus much more difficult to corrupt the software. Of course, it is also smaller! And has no battery, so is always available.
SSH Authentication
Via OpenPGP
The best way to set up SSH login appears to be to create an OpenPGP key, load the secret part into the Yubikey, deploy the public part to the target machine, and then ensure that SSH can start gpg-agent when needed. As long as the GPG keyring contains “stubs” pointing at the Yubikey (see OpenPGP setup above), the key will be used to authenticate.
The process of creating an OpenPGP key and loading it into the Yubikey is documented under PGP above.
To install the relevant public key into the target system:
# Find the id of the subkey with type="A" (authentication)
gpg -k --with-subkey-fingerprint
# export as ssh public key
gpg --export-ssh-key {subkeyid} > /tmp/yubikey.pub
# install it (-f is needed because the private-key part is not available)
ssh-copy-id -f -i /tmp/yubikey.pub {user}@{host}
On the client side, you need to run something that knows how to interact with the Yubikey to fulfil the SSH login protocol; fortunately many tools are compatible with the OpenPGP smartcard, and the Yubikey emulates an OpenPGP smartcard. The standard ssh
command uses environment-variables to find the port on which a “key agent” program is running, and delegates to that. The ssh-agent
tool is one such program, but it does not handle GPG keyrings; instead gpg-agent
is needed.
The usual way to start gpg-agent
is just to ensure that a few environment variables are defined (usually in ~/.bashrc
or similar); when SSH finds the vars are defined but the background service is not running then it is auto-started. A gpg-agent process is never shared between users, ie the background process is per-user. In fact, all the gpg ..
commands used earlier to configure the Yubikey are simply forwarding data to a gpg-agent
daemon.
On my Ubuntu-18.04 system, environment var GPG_AGENT_INFO
is already set to /run/user/1000/gnupg/S.gpg-agent:0:1
(where 1000 is my userid), and this is sufficient. The gpg-agent may need to prompt for a PIN at some stages, and therefore needs to be configured with a suitable pinentry-program
; again, my Ubuntu system is appropriately set up to show a simple but effective graphical dialog for pin entry.
SSH does try to talk to its standard ssh-agent by default; this can be changed by setting env-vars SSH_AGENT_PID
and SSH_AUTH_SOCK
.
# Terminate the gpg agent (occasionally useful)
gpgconf --kill gpg-agent
# The following script-commands will set up SSH to talk to gpg-agent. These can be defined in a script that is sourced when needed, or can be
# added directly to ~/.bashrc if you always want to use gpg-agent instead of ssh-agent. The call to gpgconf also starts gpg-agent if not already
# running..
unset SSH_AGENT_PID
if [ "${gnupg_SSH_AUTH_SOCK_by:-0}" -ne $$ ]; then
export SSH_AUTH_SOCK="$(gpgconf --list-dirs agent-ssh-socket)"
fi
# ssh commands
ssh-add -l # lists all keys in the GPG keyring (now that ssh/gpg connectivity has been set up by above ENV-vars)
ssh {user@host}
Note that the Yubikey supports only one OpenPGP authentication key, so there is no need to specify which key you want (unlike ssh-agent), ie no need to use ssh-add {key}
to enable specific keys before authenticating.
The cool part of all this is: remove the Yubikey from the USB slot, and “ssh user@host” no longer works.
With Yubico-OTP
An alternative is to install a PAM module on each target system, configure a list of allows Yubico token ids per user, and then integrate PAM with a Yubico authentication server that has the shared secret in the Yubico keys of all users who may log in. When using the factory-set credentials in “slot1” of each key, then PAM can be set to use Yubico’s own authentication servers - that is easy to set up, but has obvious drawbacks. As alternative, a sysadmin can configure each Yubikey user with a credential and enter that into a company-hosted Yubico authentication server.
This is two-factor authentication in that the user must enter their usual password and provide the Yubikey credentials too. I believe that the credentials are appended to the user’s password, and the pam module then splits the password field into the two parts before verification.
Personally, I find the OpenPGP-based approach far more elegant and secure.
MacOS Login
Using Smartcard Integration
On mac, you can log in with (key + pin) rather than password (“smartcard integration”). The MacOS login itself recognises when a PIV-compatible device is present and the selected user has a registered PIV public key credential (ie a PIV device has been paired with this account in the past). MacOS then changes the login screen to prompt for username/pin rather than username/password; the pin is then used to unlock the authenticator device, and a challenge/response algorithm is used to verify that the device contains a private key that matches the public key associated with the user. Only one private key is supported.
Sadly, this integration is not a major advantage in useability - you still need to enter a pin instead of a password. It can be a useability benefit in companies where IT forces password changes on a regular basis; there is no need to force changes in the key or pin!
With the standard Mac PIC integration, if the key is not in the laptop then you can still log in with password. Users who choose poor passwords, or reuse passwords, are therefore still a danger. Given that users do not enter their password directly, it would be possible to require long and complicated passwords.
One significant benefit is that “shoulder surfers” can only observe the pin during login, which is not useful without the Yubikey itself.
Using PAM
It is supposedly possible to install a Yubico-provided authentication module onto the MacOS system, and configure it to use this module during authentication. This makes it possible to prevent any login without the Yubikey being present. I haven’t tried this myself.
Mobile Devices
Mobile phones with access to accounts (eg Google mail) are a security problem, as the “second factor” for login is actually the phone itself. A separate key is therefore a good idea. However plugging a key into a USB port does not work for mobile phones (no ports). The Yubikey-neo supports NFC, and can be “tapped” against an android phone to have the same effect. Doesn’t currently work with Apple.
Backing Up Credentials
What if your Yubikey gets lost or damaged? Well, that is a big problem. A Yubikey device is explicitly intended to be a “write-only” device, where credentials can be sent to it but never retrieved.
- credentials generated on the device are very secure, but cannot be backed up
- credentials generated outside the device can be loaded into the device.
- includes public/private keypairs (PGP)
- includes challenge/response protocols (static password which is never revealed by the key)
Possible strategies to handle key loss:
- buy two Yubikeys, link both with each critical account, carry one and keep the other very safe
- enable “backup codes” (if supported) for each account you link the Yubikey to, and keep the downloaded codes very safe
- enable the “account recovery” feature (if supported) for the account
- eg another mobile phone (probably best when it is not yours, to avoid losing it at the same time)
If you enter HOTP/TOTP credentials manually, then the secret can just be written into a text document and stored somewhere safe. If you use the QR-code entry method, then the secret is written to the Authenticator logfile, from which they can be extracted and saved safely. If you click “generate” to create the credentials in the Authenticator app, they are also logged.
Dealing with backing up of PGP credentials is described in the articles linked to in the relevant sections - in general, allocate credentials on very secure PC (perhaps booted from “live Linux image”), back up, then install them into key.
While FIDO2/WebAuthentication looks very promising, one major concern is backups of credentials; lots of keys will be generated (one for each account created on each site), and these keys will be generated automatically within the Yubikey. That makes the traditional Yubico-recommended approach of having a “backup Yubikey” practically useless; you would need to have the backup available all the time, so each new site could be registered with both keys - but the point of the backup key is to have it somewhere safe (long-term storage). It would be great if the Yubikey supported an “export keys” option where the exported keys were encrypted with some master key that the user can load explicitly (eg an OpenPGP key, or just a special FIDO2 key). That approach would seem to nicely protect user security while also allowing at least periodic backups; unfortunately I have seen no indication that such functionality exists or is planned. The alternative seems painful and insecure - activating an “alternative login” of some kind for each site.
Some useful references regarding backups:
- Yubico Blog: Backup and Recovery Plan - the solutions recommended here are useful only when the Yubikey has a small number of credentials, eg a single Yubico-OTP or a single PGP id. The suggestions in this page do not work well for users of U2F or FIDO2.
Yubico Applications
For Android
The Yubico Authenticator for Android is apparently a fork of the Google Authenticator code (which is open-source), with additional support for communicating with a Yubico authenticator device to actually generate the TOTP code (rather than storing the TOTP account secret directly in the local filesystem and computing the code directly in the app).
For Linux Desktops
It would appear that all Yubikey desktop software is written in Python (currently v2.x), with graphics depending on Qt. The software is therefore cross-platform (though not pretty).
The desktop applications are, frankly, extremely ugly and clumsy to use. Clearly the Yubico company is full of electronic engineers and not software developers.
A number of Yubikey applications are available in the standard Ubuntu package repository. However the Ubuntu ones are extremely old; Yubico recommends enabling a custom package archive (PPA) and the following information is based on the current apps from that PPA.
The packages in that PPA provide the following tools:
-
ykman
(commandline) andykman-gui
(graphical) yubikey-personalization-gui
-
yubioath
(commandline) andyubioath-desktop
(graphical) pivman
Yes, that is a fairly chaotic naming standard there…
These are all (currently) implemented in Python, using the QT library for graphics. The graphical interfaces are fairly primitive.
App ykman
provides a commandline with the ability to:
- set a password for global configuration settings (“configuration lock code”)
- turn off specific authentication protocols you are not using
- configure credentials for slot1 and slot2 (“one touch”) - password, challenge/response, Yubico-OTP, or OATH.
- enable/disable “button press required” for openpgp authentication (but not manage keys)
- list, add, delete and use named OATH TOTP/HOTP credentials, and to set a password for access to named OATH functionality (duplicates some functions in yubioath/yubioath-desktop)
- create/import the (single) credential for PIV authentication, export certificates, etc. (duplicates some functions in pivman)
Strangely, ykman-gui
provides access to just slot1/slot2 config and enable/disable protocols (aka modes). The other functionality of the ykman commandline tool is not currently available in graphical form.
App yubikey-personalization-gui
provides detailed info and settings for the overall key, and (like ykman) allows configuration of slot1 and slot2. Most users will never need this app. If you do, the guide is very useful as the inteface is extremely hard to use.
App yubioath/yubioath-desktop
provides the ability to configure named HOTP and TOTP credentials. It also is the main app that a user interacts with to obtain HOTP/TOTP output which can be pasted into input fields in other apps/websites. And when running on a mobile phone, the application emulates Google Authenticator, supporting the simple “click ok to login” flow (which sends a TOTP code in the background). As TOTP is widely used (eg login to Google), most Yubikey owners will use this app on a daily basis.
App pivman
is used for viewing and deleting smartcard-based credentials (public/private keys). If you are using smartcard-based login (eg with MacOS) then you will need pivman once to set up an initial key and pin (or possibly ykman will be sufficient). In most cases, you will not need pivman after initial setup.
The U2F (FIDO1) and FIDO2 algorithms do not need any dedicated admin applications; the necessary support is built in to client applications (web-browsers etc).
The PGP support in Yubikey does not need a dedicated admin app; the standard OpenPGP-compatible tools are all that is needed.
Yubico also provides software for server-side support: pam plugins, various libararies, and an authentication server for the Yubico-OTP protocol. Yubico also provides server-side credential store hardware (“HSM Modules”), and associated software - but that is not in scope for this article.
Secrets in a Yubikey cannot be read, only written. Nevertheless, a Yubikey can be reconfigured using the personalization application. By default, this can be done without a password - ie anyone with access to the Yubikey can reconfigure it. The personalization tools allow setting a separate password that is needed for reconfiguration of each (obsolete) protocol.
The Open Source Controversy
The original Yubikey devices were developed “in the open” and all source-code in the devices was published as open source for inspection. Later they changed their minds and developed later code in private. This disappointed many open-source supporters, and also those who supported “open review” for security purposes. However at the current time there are no completely open competitors (except for the OpenPGP card, which is in smartcard format and does not support as many features).
Defense against Phishing
One of the claims about FIDO1/U2F and FIDO2/WebAuthentication are that they prevent “Phishing attacks”. The point is: if a user can give someone else their authentication credentials, then at least some users will. Users can (sadly often easily) be persuaded to give out passwords. Users can also potentially be tricked into giving out HOTP codes (valid for one use only) and TOTP codes (valid for one use within the next 30 seconds only) - better than passwords, but still not perfect.
Because FIDO1/FIDO2 credentials (private keys) are effectively large random numbers, it is extremely difficult for a user to hand them over at all. Of course, the credentials must also be useable - ie they require client-side software support to be useable.
Additional benefits of complex random keys (in place of passwords) are:
- no need to regularly change them; they are not vulnerable to brute-force attacks
- no need to worry about users choosing “weak” passwords
- no need to worry about passwords being shared across sites - usually one keypair per site is used, and sites have only the public-key part anyway.
Defence against Malware on the Desktop/Phone
Malware on a device (or possibly a MITM attack) can hijack a session. The user logs into the site as usual; because the credential is not passed over the network, the attacker cannot intercept it - but can intercept any “session cookie” that the server returns which then allows the malware to perform operations during the lifetime of that session. It is therefore a good idea for a server to prompt for yet another authentication code at critical points, eg before changing account credentials or making a financial transfer. The user must then actively approve the operation. This will not stop all attacks, but helps.
Alternatives to Yubikey
Your Phone
Google have recently added a feature to the Android mobile phone OS to allow it to act as a bluetooth-connected security key. When a PC user connects to a website using a browser and is prompted for 2FA login, the PC communicates directly with the phone via Bluetooth and retrieves the necessary one-time-only credential. AFAICT, there is no need for the phone to be online. Both phone and PC must of course be bluetooth-enabled.
AFAICT, this new feature has been back-ported to earlier versions of Android, and is useable from Android 7.0 (Nougat) - released in March 2016.
Most phones simply implement the key-storage in software, presumably meaning that software on the phone which has root privileges could extract the underlying secret from which the one-time-only credentials are derived. However Google’s Pixel3 phones actually include a Titan chip, the same one as in Google’s Titan USB security key - meaning that extraction of the underlying secret is impossible. In FIDO/FIDO2, new secrets are generated on the security token itself, meaning that these can also not be intercepted even by root-level software on the phone. Uploading of new secrets would be vulnerable to malware running at root level, eg uploading keys for SSH or similar purposes where they were generated outside of the embedded hardware token.
Unfortunately it appears that only FIDO-1 is supported at the current time - a protocol that is already obsolete, and used almost exclusively to log into Google online services.
However the idea is very good IMO; if future phones come with an embedded cryptographically secure key storage module, and FIDO2-capable interfaces then this could be an excellent alternative to a separate physical security token. The separate token will always be slightly superior, just because it does not run arbitrary software, but the convenience of a phone-based solution might make this a good solution for most users.
One concern is the “Cloud-assisted Bluetooth Low Energy” protocol - does this require internet access from the phone? I can’t currently find any hits with a search on that expression even though the referenced article states that this protocol has been “submitted to FIDO”.
See also this article for more details. This states that the software supports FIDO2 - not sure this is the case!
Theoretically, any phone could act as an authentication token over NFC; the FIDO spec for U2F explicitly supports this.
One of the original developers commented on slashdot; the comments are worth reading.
There is also an amusing article on the complications of logging in to your Google online account from an Apple device using an android device as the 2FA.
Alternatve Security Tokens
The following hardware tokens aka security tokens may be interesting as alternatives to Yubikey:
- Google Titan
- Onlykey - how it works, userguide and user forum (thanks to Kent H. for the tip).
- NitroKey
- Trezor - actually a “secure digital coin wallet”, but can also be used for credentials
- Feitian - security key from China
- Librem Key - supports OpenPGP signing and HOTP/TOTP, but not (yet) FIDO2/U2F
- Solokeys - a fully open-source project funded via Kickstarter. Hardware and software source is available in their Github projects and docs on their docs site.
The Solo is similar to the Yubikey in many ways (USB-A or USB-C with NFC coming in mid-2019; button for press-to-confirm). I have written a separate article on Solokeys.
Further Reading
- Lorgor: Yubikeys demystified – an excellent article on Yubikey details; sadly I found this only after writing most of this article. Nevertheless, the content of this article owes a significant debt to lorgor’s post. I think the content in my article is still significantly different enough to be worth posting in addition to Lorgor’s.
- LWN: Smartcard Features on Yubikey NEO – from 2014 (when the Yubikey still ran open software)
- Joseffson: setting up keys on yubikey
- Archlinux: Yubikey – a surprisingly complete overview of the Yubikey (comparable to this article)
- Parlante: The Unofficial U2F FAQ
- FIDO Alliance Official FAQs
- Why U2F is better than Google Authenticator
- NIST Digital Identity Guidelines
- Bid Farewell to SMS Authentication
- Authy One-Touch
- Krebs: Google Authenticator
- Google Authenticator Source Code
- FreeOTP
- Python library for FIDO2
- Security Architect: FIDO2
- RSA Conference: FIDO2
- FIDO Alliance Specifications Download
- Yubikey 4 series GPG and SSH setup guide
- Yubico: Fido2
- Yubico developer videos on FIDO2