Last updated October 05, 2019
You may be the sort of person who needs to SSH into remote machines. And you may also be the sort of person who doesn’t like the idea of SSH private keys laying around on your computer(s). If so, here’s how you can generate a PGP key on a YubiKey plugged into a USB port of a Mac, and then use that key with SSH. This way the private key lives its entire life on the YubiKey and is never placed on a disk in your computer.
The below instructions use Homebrew for installing software purely to simplify the instructions. Determining whether or not using Homebrew to install software on your computer is compatible with your threat model is left as an exercise for you, dear reader. You can certainly acquire the software via other means if you wish.
Install the YubiKey Manager CLI (
ykman); alternative installation
options can be found
% brew install ykman
Install GPG >= 2.1. Version 2.1 simplified the running of
gpg-agent. The version isn’t a hard requirement, but it might
make your life easier.
% brew install gpg
(Optional) Install GPGTools’s
pinentry-mac GUI for password entry:
% brew install pinentry-mac
Add the following lines to
pinentry-program line is optional):
enable-ssh-support pinentry-program /usr/local/bin/pinentry-mac
Add the following lines to your
~/.zshrc or whatevs. The second line will
gpg-agent if required.
export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket) gpg-connect-agent /bye
If it’s running you should disable
launchctl stop com.openssh.ssh-agent sudo launchctl disable system/com.openssh.ssh-agent
Acquire a YubiKey. I like the YubiKey 5 Nano which can live inside a USB-A port on a laptop.
Insert the YubiKey into your Mac. You can verify it’s working via:
% ykman info Device type: YubiKey 5 Nano Serial number: _________ Firmware version: _____ Form factor: Nano (USB-A) Enabled USB interfaces: OTP+FIDO+CCID Applications OTP Enabled FIDO U2F Enabled OpenPGP Enabled PIV Enabled OATH Enabled FIDO2 Enabled %
At the time of writing (2019-10) Yubico is in the process of rolling out firmware version 5.2.3 to its various YubiKey 5 products. Among other things this new firmware version allows you to generate ECC or RSA keys using the OpenPGP app on the YubiKey. Older versions only support RSA keys. Since you can’t upgrade the firmware on a YubiKey, and they don’t label which version you’re getting on the packaging, you won’t know what you’re getting until you use it. For this example we’ll stick to RSA keys.
Change some defaults for the OpenPGP app on the YubiKey. Even though it refers to a “PIN”, alphanumeric and special characters are supported. Here are the default values:
Default PIN: 123456
Default Admin PIN: 12345678
% gpg --card-edit gpg/card> admin Admin commands are allowed gpg/card> passwd gpg: OpenPGP card no. _________ detected 1 - change PIN 2 - unblock PIN 3 - change Admin PIN 4 - set the Reset Code Q - quit Your selection? 1 PIN changed. 1 - change PIN 2 - unblock PIN 3 - change Admin PIN 4 - set the Reset Code Q - quit Your selection? 3 PIN changed. 1 - change PIN 2 - unblock PIN 3 - change Admin PIN 4 - set the Reset Code Q - quit Your selection? 4 Reset Code set. 1 - change PIN 2 - unblock PIN 3 - change Admin PIN 4 - set the Reset Code Q - quit Your selection? q gpg/card> key-attr Changing card key attribute for: Signature key Please select what kind of key you want: (1) RSA (2) ECC Your selection? 1 What keysize do you want? (2048) 4096 The card will now be re-configured to generate a key of 4096 bits Changing card key attribute for: Encryption key Please select what kind of key you want: (1) RSA (2) ECC Your selection? 1 What keysize do you want? (2048) 4096 The card will now be re-configured to generate a key of 4096 bits Changing card key attribute for: Authentication key Please select what kind of key you want: (1) RSA (2) ECC Your selection? 1 What keysize do you want? (2048) 4096 The card will now be re-configured to generate a key of 4096 bits gpg/card> list <...> Key attributes ...: rsa4096 rsa4096 rsa4096 <...> Signature key ....: [not set] Encryption key....: [not set] Authentication key: [not set] <...> gpg/card>
Generate new keys directly on the YubiKey:
gpg/card> generate Make off-card backup of encryption key? (Y/n) n
Don’t bother backing up the key when prompted; you won’t get the full key anyway and it can’t be used to restore to a new YubiKey. You’ll get a standard set of PGP key creation prompts for your key settings, then your YubiKey’s light (if it has one) will flash for a while while it generates keys. After about 5 minutes you should see:
public and secret key created and signed. gpg/card> list <...> Signature key ....: <key fingerprint> Encryption key....: <key fingerprint> Authentication key: <key fingerprint> <...> gpg/card> q %
(Optional) Set the YubiKey to require a physical touch before using the keys you just created:
% ykman openpgp set-touch aut on Enter admin PIN: Set touch policy of authentication key to on? [y/N]: y % ykman openpgp set-touch enc on Enter admin PIN: Set touch policy of encryption key to on? [y/N]: y % ykman openpgp set-touch sig on Enter admin PIN: Set touch policy of signature key to on? [y/N]: y %
ssh, and your YubiKey are all playing along
nicely. The following should print out your SSH public key;
cardno should be the YubiKey’s serial number:
% ssh-add -L ssh-rsa <...> cardno:_________ %
Use the above SSH public key in
~/.ssh/authorized_keys on your target
machine or however you would normally use it.
Verify everything works. SSH to a host, enter your YubiKey’s OpenPGP PIN when prompted, then tap the YubiKey. Try a slightly longer press if it doesn’t work the first time.