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
here:
% 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 ~/.gnupg/gpg-agent.conf
(the
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
start 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 ssh-agent
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
%
Verify gpg-agent
, 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.