BXG Blog

Improving Private Key Security with a Yubikey: Intro

The current trend (not so new any more) in improving the security of one’s private GnuPG (gpg) and/or ssh keys is to move them onto a hardware token. This way the private key is not stored on one’s computer where it can get physically stolen or exfiltrated by a hacker. Even if the hardware token itself is stolen, it should enforce rate limiting on an attacker’s ability to guess the key’s PIN by forcing attempts to go through its public interface instead of directly getting access to the encrypted key.

A few months ago, I bought a Yubikey NEO to try out this idea. I (mostly successfully) migrated my gpg key onto the Yubikey and generated a new ssh key. It’s been working well enough that I wanted to expand my use to all my computers, so I bought a couple of Yubikey 4 nanos. There were a few things that I had set up poorly in my original gpg key, so this didn’t go as smoothly. This series is going to be an attempt to document what I’ve learned after going through this process a couple of times.

Yubikey isn’t the only hardware token that can be used for this. I picked them because they are well-known, moderately priced, come in all the form factors I need, and are flexible enough to also be used for OTP or U2F later if desired.

Basic requirements:

  • I want to store the master key offline. The master key should be used for issuing/revoking subkeys regularly, but should not be used for day-to-day operations. The private part of the master key should not end up on my Yubikeys.
  • I use Linux desktops (USB), a Mac laptop (USB), Android devices (NFC), and a Chromebook (USB-C). The keys generated need to work on all of these.

This leads to these keys to purchase:

  • One Yubikey NEO to be used with my Android devices via NFC.
  • One Yubikey nano to be left permanently in my laptop.
  • One Yubikey nano to be left permanently in the KVM switch attached to my desktops. If having access on only one machine at a time becomes a pain, I can eventually get enough nanos to leave one in each desktop directly.
  • One Yubikey 5C nano to be left permanently in my Chromebook.

Keys to generate:

  • I want a master key that I reuse for many years (perhaps forever). NIST recommends 3072-bit for keys that need to last beyond 2030. I don’t know if my key needs to last that long, but since it’s not used for day-to-day operations, it shouldn’t hurt to make it that big. It’s also possible to use RSA-4096 or even bigger, but there doesn’t seem to be any practical increase in security.
  • All my devices should share a single encryption subkey so that people don’t have to guess which one to choose when they send me messages.
  • All my devices should share a single signing subkey so that I don’t expose unnecessary information about which computer I was using when I signed a message.
  • Each device should have its own authentication key. This way, if a device is lost or stolen, I only have to revoke and replace the single subkey.

This can be achieved with these basic steps:

  1. Generate the master key, signing key, and encryption key on a secure computer.
  2. Set up each yubikey to support CCID.
  3. Copy the signing and encryption keys to each yubikey.
  4. Generate a fresh authentication key on each yubikey and extract the public part.
  5. Fix up other security settings for each yubikey.
  6. Set up other machines to use the yubikeys.

I’ll cover each of these steps in a subsequent article.