iliana destroyer of worlds —
CVE-2016-0777 describes a vulnerability in the OpenSSH client via an enabled-by-default undocumented option (
UseRoaming) by which a malicious SSH server could steal your private SSH key.
Mitigations and whether or not you’re even vulnerable aside, this is likely not going to be the last private key disclosure vulnerability for every SSH client you will use in the future.
A good way to protect your private key from these sorts of vulnerabilities is to ensure it can never be read into memory.
Smart cards are embedded devices that can be used to provide trusted storage for credentials and other data. Many of them have built-in cryptographic capabilities. It’s possible you carry smart cards all the time without realizing it — the SIM card in your phone, payment cards with chips, and many contactless public transit passes are all based on smart card technology.
Most smart cards have a secure element containing a secret, which can only be accessed with a PIN. If your on-disk private SSH key stored is encrypted with a passphrase, it’s a similar concept, but smart cards go one step further: most implementations make it impossible to extract the key from the card, and often will allow you to generate the key on the card itself, giving you the ability to ensure there is ever only one copy of a private key.
OpenSSH on its own has no idea what a smart card is. It has support for talking to PKCS #11 libraries, but a far easier method is using the OpenPGPCard applet, which allows you to store signing, encryption, and authentication GPG subkeys.
gpg-agent can act as an OpenSSH-compatible
ssh-agent on UNIX-like systems, and Gpg4win can act as a PuTTY-compatible SSH agent on Windows, making your authentication subkey usable by SSH clients.
If you have a smart card reader, you can buy a blank smart card, and compile and install the OpenPGPCard applet. Or you can buy a YubiKey 4 or a YubiKey Neo; both have the OpenPGPCard applet pre-installed. The YubiKey 4 is capable of storing 4096-bit RSA keys; the YubiKey Neo is capable of storing 2048-bit RSA keys, but also has an NFC interface (while I know of no SSH clients that support the OpenPGPCard applet over NFC, if you set up signing and encryption subkeys you can use them for K-9 Mail and Password Store).
Since SSH doesn’t know how to talk to smart cards, but GPG does, and GPG can be an SSH agent, we’ll set up a GPG authentication subkey to use with SSH.
If you would like to use your smart card with all GPG subkey functionality, I recommend following Tom Lowenthal’s excellent GPG-on-a-smart card guide.
Get started by creating a secure environment. Download a live image of an operating system that comes with GnuPG — I recommend Fedora — and verify the download. Burn it to a DVD or
dd it to a USB drive (you can also use the Fedora LiveUSB Creator, even on Windows, but be sure to specify no persistent storage). Whatever you download doesn’t need to have a graphical interface, since we’ll be running terminal commands in this guide (sorry).
Find a computer you trust, and boot this computer with the live media you created and log in (if you used Fedora, the username is
liveuser and there is no password).
We need network access at least temporarily to install a few packages. (Strictly speaking, if you intend to generate the key on the card and not make an off-card backup, you can use any Linux machine you like.)
Fedora 23 (Workstation Edition) Kernel 4.2.3-300.fc23.x86_64 on an x86_64 (tty1) localhost login: liveuser [liveuser@localhost ~]$
If you’re using a YubiKey, plug it in and run
lsusb to determine what mode it’s in.
[liveuser@localhost ~]$ lsusb | grep -i yubi Bus 001 Device 005: ID 1050:0111 Yubico..com Yubikey NEO(-N) OTP+CCID
The last part of the device name is what mode your device is in. It can have one or more of OTP, CCID, or U2F enabled. To use the OpenPGPCard applet, your device needs to have the CCID mode enabled — you can use ykpersonalize to set the mode with the
For Fedora, you’ll need to install
gnupg2-smime pcsc-lite-ccid. (Please let me know if you can provide a package list for other live distributions.)
[liveuser@localhost ~]$ sudo dnf install gnupg2-smime pcsc-lite-ccid [ dnf makes lots of noise ] Complete!
At this point you can disconnect from your network. pcscd needs to be running for GPG to use your card; it’s probably available as a service in the init system.
[liveuser@localhost ~] sudo systemctl start pcscd.service
After ensuring the necessary software is installed and pcscd is started, GPG should be able to talk to your card. (I’m using the
gpg2 command here, because Fedora provides both GPG 1.x and 2.x. You may need to run a slightly different command.)
[liveuser@localhost ~]$ gpg2 --card-edit Application ID ...: D2760001240102000006030136050000 Version ..........: 2.0 Manufacturer .....: Yubico Serial number ....: 03013605 Name of cardholder: [not set] Language prefs ...: [not set] Sex ..............: unspecified URL of public key : [not set] Login data .......: [not set] Signature PIN ....: forced Key attributes ...: rsa2048 rsa2048 rsa2048 Max. PIN lengths .: 127 127 127 PIN retry counter : 3 3 3 Signature counter : 0 Signature key ....: [none] Encryption key....: [none] Authentication key: [none] General key info..: [none] gpg/card>
There’s a lot going on here, but if you see something like this, GPG was successfully able to get information about your card’s emptiness.
Before we load any keys on the card, we need to set the PINs. First we need to turn on admin mode:
gpg/card> admin Admin commands are allowed
The default user PIN is
123456 and the default admin PIN is
12345678. The PIN is really a passphrase, since you can use whatever characters you like; some smart cards can be used with physical PIN pads that only allow numbers, but for the most part we’ll be using keyboards.
Start with the admin PIN; this is used to modify the card, such as changing the keys, user PIN, or other attributes. The
Max. PIN Lengths line in the GPG output tells you how long each PIN can be (in bytes, in case you’re using Unicode characters).
Because the admin PIN can effectively let someone use your private key, it’s important for it to be secure. Because you don’t need to use it every day, you probably don’t have to memorize it. You’ll need it if you lock your card though; every time you mistype your PIN, the PIN retry counter goes down one, and when it hits zero, the card is locked.
12345678 as the current admin PIN.)
gpg/card> passwd gpg: OpenPGP card no. D2760001240102000006030136050000 detected 1 - change PIN 2 - unblock PIN 3 - change Admin PIN 4 - set the Reset Code Q - quit Your selection? 3 PIN changed.
(There isn’t a prompt in the above output — GPG uses the system’s
pinentry command to ask for it, which usually does something incredibly obvious like taking over your entire screen or terminal, to prevent attacks that might trick you into typing your PIN somewhere else.)
Now change the user PIN. This will be the one you enter to use your private key, so remember this one. (Enter
123456 as the current user PIN.)
Your selection? 1 PIN changed.
The user PIN is what you’ll use daily to unlock your card and use it for authentication; your card will (usually) remain unlocked until you kill the GPG agent or remove the card.
If you like, you can set the Reset Code. If set, it allows you to use the
factory-reset admin-mode command, which allows you to use your card again if you’ve locked both the user and admin PINs, with the cost of completely destroying the private keys and other attributes on the card. Most YubiKeys will allow you to use the
factory-reset command if you’ve locked both the user and admin PINs, so it’s unnecessary (they provide a script which will guess your password wrong and reset your card for you).
Let’s exit the
Your selection? Q gpg/card>
Okay, let’s finally generate a key. This will actually generate all three subkeys (with the signature key being the “main” key holding them all together). As discussed, we only care about the authentication subkey.
gpg/card> generate Make off-card backup of encryption key? (Y/n)
Understand that if you lose, damage, or lock your card, and you don’t have an off-card backup, you will not be able to use the key anymore and will need to generate a new one, requiring you to change your
authorized_keys everywhere. Consider whether you want your card to have the only copy of this key in the world.
Upon answering this, you’re asked for both your admin PIN and your user PIN. Then, you’ll be asked the standard GPG questions of “how long should this key last” and “who do you think you are, telling me what to do”. In a world of only using GPG for SSH authentication, these don’t matter too much.
Make off-card backup of encryption key? (Y/n) n Please specify how long the key should be valid. 0 = key does not expire <n> = key expires in n days <n>w = key expires in n weeks <n>m = key expires in n months <n>y = key expires in n years Key is valid for? (0) 0 Key does not expire at all Is this correct? (y/N) y GnuPG needs to construct a user ID to identify your key. Real name: Iliana Weller Email address: firstname.lastname@example.org Comment: You selected this USER-ID: "Iliana Weller <email@example.com>" Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
After answering all this, the card generates random bytes for a while. (On YubiKeys, you can see the light blink while it’s doing this.) It finishes after a couple of minutes.
gpg: /home/liveuser/.gnupg/trustdb.gpg: trustdb created gpg: key 68255940 marked as ultimately trusted gpg: directory '/home/liveuser/.gnupg/openpgp-revocs.d' created public and secret key created and signed. gpg: checking the trustdb gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u gpg/card> quit pub rsa2048/68255940 2016-01-15 Key fingerprint = 89DE 77D8 BA91 CB24 8F89 5D47 A37C 748F 6825 5940 uid [ultimate] Iliana Weller <firstname.lastname@example.org> sub rsa2048/DC2956F2 2016-01-15 sub rsa2048/AE968BCB 2016-01-15 [liveuser@localhost ~]$ gpg2 --card-status Application ID ...: D2760001240102000006030136050000 Version ..........: 2.0 Manufacturer .....: Yubico Serial number ....: 03013605 Name of cardholder: [not set] Language prefs ...: [not set] Sex ..............: unspecified URL of public key : [not set] Login data .......: [not set] Signature PIN ....: forced Key attributes ...: rsa2048 rsa2048 rsa2048 Max. PIN lengths .: 127 127 127 PIN retry counter : 3 3 3 Signature counter : 4 Signature key ....: 89DE 77D8 BA91 CB24 8F89 5D47 A37C 748F 6825 5940 created ....: 2016-01-15 05:07:03 Encryption key....: F698 CB7F C4A8 B805 4363 904F D9CB E15D AE96 8BCB created ....: 2016-01-15 05:07:03 Authentication key: 0982 0907 DB21 548A 8191 6A89 AE2B A54F DC29 56F2 created ....: 2016-01-15 05:07:03 General key info..: pub rsa2048/68255940 2016-01-15 Iliana Weller <email@example.com> sec> rsa2048/68255940 created: 2016-01-15 expires: never card-no: 0006 03013605 ssb> rsa2048/DC2956F2 created: 2016-01-15 expires: never card-no: 0006 03013605 ssb> rsa2048/AE968BCB created: 2016-01-15 expires: never card-no: 0006 03013605
GPG goes ahead and creates all the other subkeys for you as well. As said earlier, if you really intend to use these for non-SSH GPG applications, you should consider following these excellent instructions to make a cold storage GPG key, generate subkeys, and put them on the smart card, as keeping the main key on a smart card is more risky than necessary.
Normally you’d want a copy of the generated public keys. But if you’re just using this for authentication, the card has all the information you need.
(If you’re planning on using this key on only Windows, you might consider completing the Linux SSH agent setup instructions below to see the public key in
We’re done — you can shut down the live OS. Remember to keep your admin PIN in a safe place.
Setting up your day-to-day computers to use your new smart card depends on what OS they’re running.
For Linux, BSD, and the like, we already did this above — ensure you have the CCID component of pcsc-lite installed (sometimes called
pcsc-lite-ccid), and the S/MIME component of GnuPG (sometimes called
gnupg2-smime and sometimes included in the main GnuPG package). Once
pcscd is running.
gpg2 --card-status should show your card.
For Macs, Homebrew seems to provide GnuPG packages. You may find Glenn Rempe’s blog post on using a YubiKey for GPG and SSH on a Mac helpful.
gpg2 --card-status should work with the smart card libraries on the system.
Once you have a working version of GnuPG, we need to configure it to enable SSH agent support.
$ echo "enable-ssh-support" >> ~/.gnupg/gpg-agent.conf
You can ensure
gpg-agent is running with
$ gpg-connect-agent /bye
Because GPG always puts its sockets in the same place, you can simply export
SSH_AUTH_SOCK to the correct value in your shell startup file.
SSH_AUTH_SOCK is exported, you can use
ssh-add -L to view your public key in
authorized_keys format (and to verify that everything is set up right).
$ ssh-add -L ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC8YHaUn3i/yd27wmO4d9if1tNzcpNSW1gkfYiFqX2xShgYAOPG+Vr6WmU6xN43Qx0jpuLfajBkvEyySnyw+XXD4WR+dtEBYrEAMJHLT2wIWRI89TUaMyV7+tiGUGAwD08JKm9vN5e1erdUFVJpejNN0o2fvglDDa3w0sKyhiqPSOjm64tIYys5s38pFp1fbAnEvasVzePBH5vz5ySJyfwqq61SEzefzCjUNF7JzWsP4c4vVKKvzCJnHAEs/5Iv0/3kAoQbHodXu4russXZ6mu4JBO03fzcFH7W69kdsrK4Vba4JjGu2e1Z1izpOK/r4455gxZKMxKY67B+KuQ9DGjB cardno:000603013605
ssh-add shows the key,
ssh is likely to be able to use the key.
If you’d like to kill the agent, you can use
$ gpg-connect-agent killagent /bye
Install Gpg4win, a version of GnuPG built for Windows. It comes in many flavors; any will do, and for the purposes of SSH, the Vanilla version is plenty. (Gpg4win is signed for Authenticode and also has a GPG signature available.)
The equivalent of
~/.gnupg with Gpg4win is
%APPDATA%\gnupg. In there, create a
gpg-agent.conf file, which needs to contain only one line:
enable-putty-support is an extension on top of the normal GnuPG distribution that provides the same interface PuTTY’s Pageant provides, so you can just use PuTTY and anything else that works with Pageant out of the box.
(For Cygwin users, install the
ssh-pageant package, which presents an OpenSSH-compatible agent that passes data back to a Pageant-compatible agent.)
Ensure the agent is running:
$ gpg-connect-agent.exe /bye
I don’t know. I’m not you.
Weigh the cost of the smart card, setting it up, and bootstrapping all your client systems against the cost of having your private SSH key compromised once (which can be very bad if you don’t have a way of disabling your compromised key across your entire fleet of servers). It’s tempting to say “there’s a million-in-one chance that my key will be compromised”, but people still win the Powerball.
On-filesystem SSH keys are still perfectly suitable for automated systems, but just like all stored credentials, you should rotate them once a quarter, and especially after disclosures like CVE-2016-0777.
Another important step in keeping SSH secure is using secure cryptography in transit. Read stribika’s analysis and guide on securing SSH.