YubiKey for SSH
There aren’t too many great articles out there about how to set up a YubiKey simply for SSH access. I will be showing you how to:
Generate a GPG key
Move the keys over to your YubiKey
Enable SSH on GPG so that your SSH authenticates with GPG
YubiKey implements the smart card interface for GPG, which means you shouldn’t need any external libraries specific to YubiKey. However you still need an up-to-date version of GPG and
gpg-agent to allow SSH. You can check if your version of
gpg-agent is recent by running the command below.
$ gpg-agent --help | grep ssh --enable-ssh-support enable ssh support
--enable-ssh-support ssh flag exists, you can continue, otherwise, download the latest versions of GPG and
gpg-agent from your package manager of choice.
First, let’s plug in the blank YubiKey and make sure you can edit it with GPG.
$ gpg --card-edit Application ID ...: D2760001240102010006061566540000 Version ..........: 2.1 Manufacturer .....: unknown Serial number ....: 06156654 Name of cardholder: [not set] Language prefs ...: [not set] Sex ..............: unspecified URL of public key : [not set] Login data .......: [not set] Private DO 1 .....: [not set] Private DO 2 .....: [not set] Signature PIN ....: not forced Key attributes ...: 2048R 2048R 2048R Max. PIN lengths .: 127 127 127 PIN retry counter : 3 0 3 Signature counter : 0 Signature key ....: [none] Encryption key....: [none] Authentication key: [none] General key info..: [none]
If your YubiKey already has data on it and you want to reset it, I’ve created this little script you can use to reset it. The hex values to reset the device I got off a GPG forum, but but you can probably find them elsewhere:
Once you have a clean slate, we can get started! I’ll wait…ok that’s enough.
Generate a GPG Key
Open a terminal an type:
$ gpg --gen-key
Now it should ask for at least a full name, email and password. DO NOT leave your password blank. If your GPG password is blank, anyone who gains access to your computer or the key itself, will be able to use it without authentication. This will generate an RSA 2048 bit key for you without an expiration. If you’d like to have more options, strengthen the key or add an expiration, you can use the expert flag like so:
$ gpg --expert --gen-key
RSA 2048 might not be as secure as other bit lengths, but it’s perfectly fine for most use cases. Once you have the key, you can validate it like so:
$ gpg --list-keys pub rsa2048/D0B4CE63 2017-12-28 [SC] uid [ultimate] Ryan Canty <[firstname.lastname@example.org](mailto:email@example.com)> sub rsa2048/157D0431 2017-12-28 [E]
GPG Core Concepts
Let’s talk a bit about this output. If you don’t care, feel free to skip to the next section. As a disclaimer, these are learnings I picked up from doing this and reading a few articles, so if I’m missing something, please leave a comment letting me know where I’m wrong.
The first column is the descriptor, you’ll notice
sub. One of the core pieces of GPG I didn’t know before doing this, is that a single GPG key can have multiple sub-keys that can potentially handle different things, such as encryption, authentication, etc. The first two lines in the output give the public key portion of the master key and the user identifier.
The next column is the key identifier (I’m making up terms here, so again correct me if I’m wrong). The first portion (before the slash) is the type of key and the portion after the slash is the actual unique id for that key. You’ll need this later when you want to edit a key.
Finally the flags in the brackets are capabilities of the key. Here is a good post detailing all the flags, which is where I got this:
Creating an Authentication and Signature Key
To get SSH to work you mainly just need to create an authentication and signature sub-key since we already have an encryption sub-key created for us. We also don’t want to move the primary key to the card since the private key will be unusable by other keys. To do this you’ll want to plug in your YubiKey and then edit the master key you just created. As I mentioned previously, you’ll need the key identifier to do this. So with my example above:
$ gpg --edit-key D0B4CE63
You’ll now be dropped into the GPG shell, where you can do many magical things that are out of the scope of this tutorial, but I’d encourage you to look at the options in
help and find out for yourself.
So with our card plugged in, within the GPG shell you can either create a subkey and transfer it to the YubiKey OR you can create a key directly on the device. We’re going to be doing both, but let’s start with adding a key directly to the card:
gpg> addcardkey Signature key ....: [none] Encryption key....: [none] Authentication key: [none] Please select the type of key to generate: (1) Signature key (2) Encryption key (3) Authentication key
As I mentioned above, the only type of key we don’t currently have is an Authentication key, so just type
3 to create one of those. You’ll have to enter both the user and admin PIN on your YubiKey as well as your GPG password. As mentioned in the script above, the defaults are
12345678 respectively. You’ll want to change those once we’re done adding keys. Just repeat this process for the signature key.
Moving Encryption Key to the YubiKey
At this point we have only one key on the card. You can verify this by running
gpg --card-edit and noticing the key in the spot for authentication. Now let’s move the existing keys to the YubiKey. Still within the GPG shell, let’s try to switch the key we’re working with. By default, the current key is the primary or master key, with an index of 0. If you want to change the current key, simply run:
gpg> key 1
This should give you an output similar to this:
gpg> key 1 sec rsa2048/D0B4CE63 created: 2017-12-28 expires: never usage: SC trust: ultimate validity: ultimate ssb* rsa2048/157D0431 created: 2017-12-28 expires: never usage: E ssb rsa2048/8E6FAB0A created: 2017-12-28 expires: never usage: A card-no: 0006 06156654 ssb rsa2048/16BA1B45 created: 2017-12-28 expires: never usage: S card-no: 0006 06156654 [ultimate] (1). Ryan Canty <[firstname.lastname@example.org](mailto:email@example.com)>
* next to the Encryption key? Ok now that the encryption key is selected, we can move it to the card using the command:
You’ll be asked what key slot you want to place this key into, and be give a single option of
Encryption which you should select with it’s corresponding number. At this point you can exit out of the GPG shell by typing
quit. Make sure you type y to save your changes or you’ll have to start all over.
Exporting the SSH Key
You should now be able to export the SSH public key to be used with whatever server you have. I’ll show you how to export the SSH key as well as the PGP public key so you can use it to sign code into GitHub with the same key.
First, to export as an ssh key, just run:
$ gpg --export-ssh D0B4CE63
Second, to get the PGP key ASCII armored, run:
$ gpg --export --armor D0B4CE63
Save these two outputs somewhere safe!
Enable SSH and GPG
This part might be the trickiest to wrap your head around unless you’re familiar with Unix Sockets. I’m not an expert either so bare with me. SSH has an authentication socket (or file) that it uses to communicate with the key chain on your computer. This file is referenced by the
SSH_AUTH_SOC environment variable. What we’re doing here is enabling gpg-agent to run with SSH support and telling SSH where to find the authentication data it needs, as opposed to the standard
~/.ssh/id_rsa files. So first, you’ll need to kill your running
gpg-agent if you have one running:
$ pkill gpg-agent
Then just restart it with the
$ gpg-agent --enable-ssh-support --daemon SSH_AUTH_SOCK=/home/ryan/.gnupg/S.gpg-agent.ssh; export SSH_AUTH_SOCK;
The output here is what you need to run in order to let SSH know about your GPG private key. You’ll either need to copypasta this onto your shell or add it into your
.bashrc (or whatever fancy shell you’re using). Be careful though, if you have other SSH keys in your
.ssh directory once you have that line in your
.bashrc, SSH will ONLY authenticate with GPG and if your YubiKey isn’t inserted, you’ll get a “permission denied” error.
Changing Your PINs
Now for the final step before hooking your YubiKey to your key ring, strapping on your messenger bag, and riding your bike to a coffee shop: Please, please, please change your PINs. This is super simple using the same method we used earlier.
$ gpg --card-edit ... gpg/card> admin Admin commands are allowed gpg/card> passwd 1 - change PIN 2 - unblock PIN 3 - change Admin PIN 4 - set the Reset Code Q - quit Your Selection? 1
Once you open up the card edit shell, you’ll need to switch to admin mode and the run the
passwd command. You’ll need to run this twice: once for the admin and once for the user. I’d highly recommend making the keys different. Once this is done, you’re off to the races.
GPG is a fantastic tool that has myriad uses that can help protect your sensitive information during communications. This use not only protects you from fallout of a compromised machine, but it gives you the ability to have a single centralized authentication key for all your devices and logins. Let me know if I missed anything or you’d like help.