GPG, Smartcards and SSH

I haven't been safe/paranoid enough with my digital security. A component of which is how I use SSH keys. The short version... fucking badly. Problem, realization of said problem, possible solution.

I’ve landed on a simple equation for what’ll remedy my current fear levels:

  • Abandon my SSH keys
  • Replace them with GPG keys + gpg-agent
  • Keep my secret GPG keys on a smartcard

3 things, NBD, but oh, the details. I’ll start from the bottom.

I picked up a Yubikey a couple of weeks ago. When I bought it, I didn’t really know what it was, but it looked security-ish. Turns out it is both a GPG smartcard and a hardware factor for multi-factor authentication. Cool.

Now, Yubikey as a hardware factor is peazy. I’m using it with LastPass, and it’s simply a matter of sticking it in a USB slot and touching the metal bit.

Using Yubikey as a smartcard is a bit trickier. This isn’t implicit to Yubikey, but smartcards in general. Additionally, using GPG keys to SSH places is kinda face-numbing. Since I’m new to GPG, I of course inadvertently opted to take the most-face-numbing-est path.

Some of the sights along the way:

  • Install GnuPG
  • Configure GnuPG
  • Configure gpg-agent
  • Generate a GPG master key (revocation certs, text backup, etc.)
  • Generate subkeys for authentication, signing and encryption
  • Publish keys to a keyserver
  • Move secret keys to Yubikey

If you, dear reader, would also like to use a Yubikey for SSH, then read on.

Installing Stuff

Regardless of where you’ll be generating your keys (Tails maybe?), you’ll need gpg2 and a few other packages on your daily computer.

  # mac
  $ brew install gnupg2 pinentry-mac

  # ubuntu
  $ sudo apt-get install gnupg2 scdaemon pcscd pcsc-tools pinentry-gnome3

Configuring Stuff

Next, you’ll need to configure gpg2 and gpg-agent. Read through this and this, then download them to ~/.gnupg. Both will need a bit of modification afterwards.

  # look at this before you download it, duh

  # yea, these are long, and look like shit when they wrap.

  # ~/.gnupg/gpg.conf
  $ curl https://raw.githubusercontent.com/ioerror/duraconf/master/configs/gnupg/gpg.conf > ~/.gnupg/gpg.conf

  # ~/.gnupg/gpg-agent.conf
  $ curl https://gist.githubusercontent.com/killtheliterate/e05ab738948cd00fcf35/raw/596b4b5a0dae98da496529fc35ebb365436f056a/gpg-agent.conf > ~/.gnupg/gpg-agent.conf

You’ll need to set up gpg-agent.conf to use a relevant pinentry program. For mac, I’m using pinentry-mac. For Ubuntu, I’m using pinentry-gnome3. Don’t use pinentry, which caused me so much grief that I’ll call it out again later in this post. You’ll also need to download the certificate described in gpg.conf and modify gpg.conf to point at wherever you decide to put the certificate.

Generating Keys

Now you’ll need to generate keys:

  • A master key
  • A subkey for encrypting things
  • A subkey for authentication (this’ll be for SSH)
  • A subkey for signing things

A lot of folks recommend generating these keys in an environment like Tails. If you use a Tails that has never been online, it’s less likely that your master key will become compromised. Bonus-mode, Tails has a feature to persist keys. This means you can have a secure copy of Tails on a USB flash drive, with an encrypted partition that contains your keys.

If you opt to go this route, you’ll need to move your subkeys from Tails to an OS that works with smartcards. Basically, export your subkeys, your public keys, and then put them on another USB drive. Plug that in to your daily computer and import your keys.

To export keys:

  $ gpg2 --export-secret-subkeys -a  > private.asc
  $ gpg2 --export -a  > public.asc

To import keys:

  $ gpg2 --import private.asc
  $ gpg2 --import public.asc

Publish Public Keys

Now that you’ve got some public keys, you should publish them to a keyserver. People will then be able to look you up and encrypte messages for you. If you’ve configured gpg.conf correctly, you can publish your keys to https://sks-keyservers.net. There are some good alternatives of course, such as http://keys.gnupg.net and https://pgp.mit.edu. From what I understand, publishing to one should propagate to the others.

My public key is available here.

Send your public keys:

  $ gpg2 --send-keys YOUR KEY ID

Set Up Yubikey

Alright… Finally, Yubikey. The gist is to configure your Yubikey, and then move your secret subkeys to it.

You’ll need to enable the smartcard interface of your Yubikey using ykpersonalize. This is pretty painless, and Yubico wrote a nice post about it here.

Now, configure the Yubikey. This means setting an admin password, a key password, and other optional pieces of information like your name. Of particular interest is URL of public key, as you can use that to fetch your keys should you ever need to (say you need to use someone else computer).

Both passwords you set up on the card should be strong. They key password is what you’ll be prompted for when using your Yubikey to encrypt/decrypt/authenticate.

  $ gpg2 --card-edit
  gpg/card> admin
  gpg/card> passwd
  # etc.

Hell Is scdaemon

Configuring my Yubikey is where this process became especially hellacious. I encountered many errors that basically amounted to scdaemon not working/running. scdaemon, as I understand it, is how gpg-agent connects to smartcards. If it’s not running, or is for-any-reason fucked up, smartcards won’t work. On Ubuntu, this was resolved by explicitly installing scdaemon and a few other packages. If you followed the install steps spelled out near the top, you should be good. For both Mac and Ubuntu I had to edit gpg.conf to use a pinentry program that was not pinentry, namely pinentry-mac or pinentry-gnome3. This bums me out, but it bums me out less than gpg-agent not working.

First and foremost, make sure gpg-agent is running.

  # this will say everything is chill-mode if it's running, and start it
  # otherwise
  $ gpg-agent 

Move Your Secret Subkeys

Alright, ready to move your subkeys to the Yubikey? Yup.

  $ gpg2 --edit-key YOUR KEY ID
  gpg> toggle # so we're working with secret keys
  gpg> key 1 # select the key you want to move
  gpg> keytocard 
  # Then select the slot to move it to. There should only be one option for
  # each subkey if you've made single-purpose keys.
  gpg> save 

If everything is legit, running gpg2 --card-status will print out a display that contains some info about your subkeys. Additionally, gpg2 -K will generate a little readout that displays your secret subkeys with a > preceding them.

SSH

As mentioned right up top, I mostly wanted to use a Yubikey for SSH. That requires a bit of configuration in .zshrc, .bash_profile, or whatever shell configuration file is relevant to you.

  if [ -f "${HOME}/.gpg-agent-info" ]; then
    . "${HOME}/.gpg-agent-info"
    export GPG_AGENT_INFO
    export SSH_AUTH_SOCK
  fi
  export GPG_TTY=$(tty)

Now, you’ll need an SSH compatible public key to add to, say, github, or authorized_keys. Get it by running:

  # copy/paste the relevant key
  $ ssh-add -L

Perfect. You now have a GPG key you can use for SSH, and it’s on a Yubikey. Paranoia abatement successful.

Further reading: