If you've followed my article One GPG key pair (to rule them all), you have a GPG primary key with subkeys for encryption, signing, and authentication. The private key for the primary key is safely stored offline, but what about the private keys for the subkeys? In order to actually use the subkeys to sign, encrypt, and authenticate, the private keys need to be available. But if they are stored on your local computer they are subject to compromise by intruders, malware, theft of the computer, etc. The solution to this problem, being able to use your keys while still keeping them secure, is found in a specially-designed piece of hardware called a smartcard. In this article, I'll show you how to secure your private keys by transferring them to a smartcard called a Yubikey.
Smartcards are specialized cryptography devices that hold and allow the use of cryptographic keys. Once written to key slots on a smartcard, private keys can no longer be read or accessed directly. Instead, when a smartcard user performs cryptographic operations like signing and encrypting, the user application (GPG in this case) passes the request to the smartcard. The smartcard authenticates the request - for example, by requiring that a PIN be entered. If authentication is successful, the card performs the requested task itself using its own processor and the private keys stored on its chip. The smartcard then passes the output of the operation back to the requesting user application.
Through this mechanism the smartcard allows the use of the private keys, without providing the user or any applications direct access to the keys themselves. All cryptographic operations are performed on the smartcard, so key data is never held in the system memory or disk storage of the host. Even if the host computer were to be root-level compromised, the keys would remain safe. The only private key files stored on the computer are stub keys that simply tell GPG information about the smartcard where the actual keys are stored. Those stub keys on their own hold no secret information and cannot be used to perform cryptographic operations absent the smartcard.
The use of a smartcard provides an additional factor of security for your GPG keys. With a standard GPG keyring, anyone might use a GPG key if they have a copy of the key file and know the key's passphrase. Key files may be copied or exfiltrated, and are protected only by filesystem-level permissions.
With the smartcard solution, any user who wants to make use of the GPG keys must have not only the authentication PIN for the card, but physical possession of the card itself. Further, the smartcard is designed in such a way as to make it impossible (as far as we know) to copy or clone the contents to a duplicate card. For additional security, many smartcards also have a built-in kill switch: enter the wrong PIN three times, and the smartcard locks itself and/or wipes its key stores. This countermeasure makes brute force attacks against a smartcard impossible, and with a sufficiently long and randomized PIN the chance of correctly guessing the code in three or less tries is astronomically slim.
Yubico is the manufacturer of USB-enabled smartcards called Yubikeys. Traditional smartcards resemble a credit card or ID card, and must be inserted into a specialized reader slot built in to the host computer, or a standalone reader connected to the computer via USB. Built-in smart card readers are uncommon except in business-class laptops (and even then, only on certain models). The USB readers are cumbersome to carry around and awkward to employ if you're not using a traditional workspace (i.e., a desk in an office). Traditional smartcards and the required hardware to program them also tend to be quite expensive, ranging into the hundreds of dollars in cost to get started.
In contrast, Yubikeys resemble a thin USB flash drive in form. When inserted into a standard USB port of a host computer, a Yubikey presents itself as a smartcard reader with a smartcard inserted. Yubikeys are extremely portable - you can keep one on your regular keyring in your pocket. They also draw their power from the USB port they are inserted into, so no battery or external power source is required. And they are relatively cheap, at around US$40.
The Yubikey 4 is the current model from Yubico. It sports some impressive features including multiple operation modes, a touch sensor, and three key slots that can support up to 4096-bit RSA keys - one each for signing, encryption, and authentication.
Before you begin, be sure that you have a backup copy of the private keys for your GPG subkeys. When you transfer your keys to a Yubikey it is a move operation - not a copy. The private keys will be deleted from your private keyring and replaced with stub keys. Once copied to the Yubikey, there is no way to extract or recover your private keys.
To make a backup of your subkeys, use the command:
$ gpg --export-secret-subkeys -a -o <backupfile.asc>
To use your Yubikey with GPG and
gpg-agent you will need to install the GPG smartcard support package
$ sudo apt install scdaemon
You may also want to install the Yubikey personalization tool in order to modify your Yubikey's settings:
$ sudo apt install yubikey-personalization
Before you move your keys to your Yubikey, you should first configure the card. To do so, insert your Yubikey into a USB slot. To verify that GPG can see and use your card, issue the command:
$ gpg --card-status
GPG will print a summary of the card's settings, which should be the defaults. You'll now modify your key to set information fields and PINs. Issue the command:
$ gpg --edit-card
At the prompt, issue the
gpg/card> admin Admin commands are allowed
If you use the
help command, you will see all of the available options you may configure:
gpg/card> help quit quit this menu admin show admin commands help show this help list list all available data name change card holder's name url change URL to retrieve key fetch fetch the key specified in the card URL login change the login name lang change the language preferences sex change card holder's sex cafpr change a CA fingerprint forcesig toggle the signature force PIN flag generate generate new keys passwd menu to change or unblock the PIN verify verify the PIN and list all data unblock unblock the PIN using a Reset Code factory-reset destroy all keys and data
The first thing you should do is change your PINs, by using the
gpg/card> passwd 1 - change PIN 2 - unblock PIN 3 - change Admin PIN 4 - set the Reset Code Q - quit
At a minimum, you will want to change the admin PIN (option 3, default: '12345678') and the user PIN (option 1, default: '123456'). You may also choose to set a reset code (option 4, no default). The reset code (also called the PIN unlock code or 'PUC') is a special admin PIN that can only be used to unblock the user PIN. This option is usually only implemented in corporate environments where Yubikeys are being issued to many users. For personal use, the reset code has limited application. If you do not set the reset code, the admin PIN is used instead to unblock the user PIN.
The user and admin pins are not limited to 6 and 8 digits respectively, and you should feel free to use a longer PIN - particularly for the admin PIN which you should rarely need to use. Record these PINs in your password manager to prevent loss. If the user PIN is incorrectly entered three times, the PIN will become 'blocked' (disabled). Even if correctly entered afterward, the PIN will no longer work until it is unblocked using the reset code (with the
unblock command) or with the admin PIN (using the
passwd command, option 2). If either the admin PIN or the reset code are entered incorrectly three times the Yubikey will reset to factory defaults, wiping any installed keys.
Other settings you may want to change are
url (the URL for the key owner's public key, used by
login (the key owner's login name). You can also set other informational fields such as the key owner's full name, sex, and preferred language (
When you're done setting up the Yubikey, issue the
Now you'll transfer your private keys to key slots on your Yubikey, using the GPG
$ gpg -K sec# rsa4096/0x7CD6ACA4C84DA8B3 2017-10-29 [C] [expires: 2020-10-29] Key fingerprint = 4C64 592C 9611 E531 1A81 8824 7CD6 ACA4 C84D A8B3 uid [ultimate] Rick Demo <firstname.lastname@example.org> ssb rsa4096/0x582CBC299B4C2718 2017-10-29 [S] [expires: 2018-10-29] ssb rsa4096/0x7C97F91B5079A317 2017-10-29 [E] [expires: 2018-10-29] ssb rsa4096/0x88C4DD5D965ABA57 2017-10-29 [A] [expires: 2018-10-29] $ gpg --edit-key email@example.com sec# rsa4096/0x7CD6ACA4C84DA8B3 created: 2017-10-29 expires: 2020-10-28 usage: C trust: ultimate validity: ultimate ssb rsa4096/0x582CBC299B4C2718 created: 2017-10-29 expires: 2018-10-29 usage: S ssb rsa4096/0x7C97F91B5079A317 created: 2017-10-29 expires: 2018-10-29 usage: E ssb rsa4096/0x88C4DD5D965ABA57 created: 2017-10-29 expires: 2018-10-29 usage: A [ultimate] (1). Rick Demo <firstname.lastname@example.org>
Select your first subkey (in this example, the signing key) by using the
gpg> key 1
The subkey will be denoted with a
* to show that it is selected:
sec# rsa4096/0x7CD6ACA4C84DA8B3 created: 2017-10-29 expires: 2020-10-28 usage: C trust: ultimate validity: ultimate ssb* rsa4096/0x582CBC299B4C2718 created: 2017-10-29 expires: 2018-10-29 usage: S ssb rsa4096/0x7C97F91B5079A317 created: 2017-10-29 expires: 2018-10-29 usage: E ssb rsa4096/0x88C4DD5D965ABA57 created: 2017-10-29 expires: 2018-10-29 usage: A [ultimate] (1). Rick Demo <email@example.com>
Now use the
keytocard command to transfer the private key. GPG will ask you for the key slot where the key should be installed. This is a signing key, so we'll take option 1:
gpg> keytocard Please select where to store the key: (1) Signature key (3) Authentication key Your selection? 1
You'll be prompted for the private key passphrase and the admin PIN. After the key is installed, de-select key 1:
gpg> key 1 sec# rsa4096/0x7CD6ACA4C84DA8B3 created: 2017-10-29 expires: 2020-10-28 usage: C trust: ultimate validity: ultimate ssb rsa4096/0x582CBC299B4C2718 created: 2017-10-29 expires: 2018-10-29 usage: S ssb rsa4096/0x7C97F91B5079A317 created: 2017-10-29 expires: 2018-10-29 usage: E ssb rsa4096/0x88C4DD5D965ABA57 created: 2017-10-29 expires: 2018-10-29 usage: A [ultimate] (1). Rick Demo <firstname.lastname@example.org>
Now repeat this process for
key 2 and
key 3, assigning them to the Encryption Key (2) and Authentication Key (3) slots, respectively. When you are done, use the
save command to exit:
If you do
gpg --card-status now, you should see that the keys have been installed on the card. If you do
gpg -K you will see that the subkeys are now denoted with a
> to show that they are located on a smartcard:
$ gpg -K sec# rsa4096/0x7CD6ACA4C84DA8B3 2017-10-29 [C] [expires: 2020-10-29] Key fingerprint = 4C64 592C 9611 E531 1A81 8824 7CD6 ACA4 C84D A8B3 uid [ultimate] Rick Demo <email@example.com> ssb> rsa4096/0x582CBC299B4C2718 2017-10-29 [S] [expires: 2018-10-29] ssb> rsa4096/0x7C97F91B5079A317 2017-10-29 [E] [expires: 2018-10-29] ssb> rsa4096/0x88C4DD5D965ABA57 2017-10-29 [A] [expires: 2018-10-29]
Using GPG with your Yubikey is almost the same as when your keys were stored locally on your computer, except that instead of being prompted for your key passphrase you will now be prompted for your user PIN. If you are running
gpg-agent the PIN will be cached in the same way that your passphrase was cached. If you attempt to use GPG for an operation that requires your keys and your Yubikey is not inserted into the computer at the time,
pinentry will prompt you to insert your Yubikey.
The Yubikey provides additional protection for your GPG keys by requiring the presence of a physical token (the Yubikey) as well as the knowledge of the user PIN. However, if you run
gpg-agent the default settings are to cache the PIN for some period of time after it is entered once. This is convenient, but it also means that your key is subject to unauthorized use if someone were to gain remote access to your computer. If you want to add an additional layer of security, you can require that the Yubikey be touched each time it is used to sign, encrypt, or authenticate, in order to authorize use of the private key. If touch authorization is enabled and you perform a task requiring one of your private keys, you will be prompted to insert the Yubikey (if it is not already inserted), and prompted to enter the PIN (if it has not already been entered and cached by
gpg-agent). Then the Yubikey will blink, prompting you to touch its button before the key operation will be performed. If you don't touch the button within 15 seconds, the operation is cancelled.
This feature provides two key benefits:
To enable touch authorization, use the yubitouch.sh bash script by Alessio Di Mauro.
./yubitouch.sh sig on ./yubitouch.sh dec on ./yubitouch.sh aut on
You will be prompted for the Yubikey's admin PIN for each command. If you want to disable touch authorization, use the same command with the
off option. You may also use
fix instead of
on. This will turn on touch authorization and prevent it from being disabled without resetting the Yubikey to factory defaults.
If you use GPG keys on your Yubikey for batch operations, scripts, etc., enabling touch authorization may present a problem for you. Touch authorization requires a touch each time a key is accessed to perform an operation. If your authentication key is on your Yubikey and you run a script that uses SSH to execute a command on 100 servers, you'll be prompted to touch your Yubikey 100 times - not just once when the script is first run.
The Yubikey 4 has an integrated button used for various functions in different modes. Its default function is to generate one-time password ('OTP') codes for two-factor authentication. This is a useful feature - unless you aren't using it. In which case it becomes an annoying button that you accidentally touch all the time, causing the key to spit out a long string of digits into whatever application you're working in at the time. This is particularly true of the Yubikey Nano, which is a tiny device that barely protrudes from a USB port and whose entire visible surface is a touch interface.
If you aren't using the Yubikey to generate OTP codes for websites or applications, you can disable that feature to prevent the device from spewing text into your editor or IRC client at the most inappropriate moment possible. To do this, you'll use the
ykpersonalize command to set the device's USB mode:
$ ykpersonalize -m1
Will set the device to CCID-only mode, turning off OTP and U2F functionality. The available modes are:
0 OTP device only. 1 CCID device only. 2 OTP/CCID composite device. 3 U2F device only. 4 OTP/U2F composite device. 5 U2F/CCID composite device. 6 OTP/U2F/CCID composite device.
If you change your Yubikey to a non-OTP mode with
ykpersonalizeyou will not be able to change the mode again using the same tool (
ykpersonalizeonly works in OTP mode). If you decide later to re-enable OTP mode, you will need to use the
ykmantool. At this time
ykmanis not packaged in the Debian repos, and will have to be installed from source or via the
pip install yubikey-manager). The
ykmanutility is still in beta and is not very well documented at this time.
You may also enable 'eject' functionality. This feature will allow you to 'eject' the smartcard when the Yubikey is touched, making it appear to be removed even though the Yubikey is still inserted in the USB port. Touching the button again will 're-insert' the smartcard. This feature can be convenient if you like to leave your Yubikey installed most of the time (as is often the case with the Yubikey Nano) but only want it to be available for use when you specifically 'insert' it. When you are done, you immediately 'eject' it to keep your keys from being available unnecessarily.
In order to enable the 'eject' flag, add 80 to the mode value (e.g., 81 for CCID only, plus eject).
Do not enable 'eject' if you are also using touch authorization for signing, decryption, or authentication. The two features are mutually incompatible.
There are a couple of scenarios where you might use multiple Yubikeys that hold the same private keys, and each scenario is handled differently.
You might have one Yubikey that is your primary daily key. You keep it on a lanyard or on your keyring, and you carry it around with you. You might also have a backup Yubikey on which you installed the same keys. You might keep that backup in a safe or locked drawer, and only use it if your primary key becomes lost or destroyed.
When you move your private keys from your local disk to a Yubikey, GPG replaces the private key files with 'stub' keys that contain information about where the real keys are stored. In particular, the stubs contain the unique serial number of the Yubikey to which the key was moved with
keytocard. If you lose your primary Yubikey and insert your backup, you'll have to re-create the stubs in order for GPG to find your private keys on the new Yubikey (which has a different serial number than the primary). Luckily, that's pretty easy to do.
Just delete the private subkeys from your keyring, and then relearn them from the new Yubikey:
$ gpg --delete-secret-subkeys firstname.lastname@example.org $ gpg --card-status
People often use the Yubikey Nano as a "permanent" smartcard, leaving it installed in their computer all the time. If you have multiple desktops or laptops you can have a dedicated Yubikey for each. The setup process just needs to be performed for each Yubikey on each computer, using a local keyring that contains the private subkeys (remember that installing the keys on the smartcard is a 'move' operation, not a 'copy' - you can't setup two Yubikeys with the same keys from the same GPG instance). On each computer, start with a copy of your
.gnupg directory that contains your private subkeys, and perform the
keytocard operations on each machine. This will create stub keys on each computer that point to its dedicated Yubikey.
If you use sync software to keep your GPG keyrings in the same state, be sure to only sync your public keyring. If you sync the private keyring, you'll end up with the same stub keys on every machine and only one will have a card with the correct serial number. For example, if you use Syncthing you might add a line to the
.stignorefile in the root of your home directory that reads
/.gnupg/private-keys-v1.d. This will prevent Syncthing from synchronizing your stub key files.
I hope that this article has removed some of the mystery around GPG and smartcards, and shown how easy it is to provide a whole new level of security for your GPG keys. As always, if you have comments, questions, or corrections, feel free to send me an email. Thanks for reading.