Skip to content

Instantly share code, notes, and snippets.

@jaredmichaelwilliams
Last active August 28, 2018 01:28
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save jaredmichaelwilliams/b029c19b928ccc134f1a to your computer and use it in GitHub Desktop.
Save jaredmichaelwilliams/b029c19b928ccc134f1a to your computer and use it in GitHub Desktop.
Setting up a Yubikey for use with SSH
Preparation
Purchase YubiKey NEO
Install X Code and Command Line Tools, if installing anything from source.
X Code can be installed from the App Store.
Command Line Tools are installed from X Code: X Code -> Preferences -> Downloads -> Components -> Command Line Tools.
Install YubiKey reader library libyubikey (aka yubico-c)
Using homebrew:
brew install libyubikey
brew install ykpers
From source code
$ sudo mkdir /usr/local/yubi
$ sudo chown $(id -nru):$(id -nrg) /usr/local/yubi
$ mkdir /usr/local/yubi/src
$ cd /usr/local/yubi/src
$ ftp http://yubico-c.googlecode.com/files/li ... .10.tar.gz
$ tar -xzf libyubikey-1.10.tar.gz
$ cd libyubikey-1.10
$ ./configure --prefix=/usr/local/yubi
$ make && make install
Install YubiKey personalization utilities, ykinfo(1) and ykpersonalize(1)
From source code
$ cd /usr/local/yubi/src
$ ftp http://opensource.yubico.com/yubikey-pe ... 4.0.tar.gz
$ tar -xzf ykpers-1.14.0.tar.gz
$ cd ykpers-1.14.0
$ ./configure --prefix=/usr/local/yubi
$ make && make install
Install GnuPG with native CCID support.
GPG Tools: https://gpgtools.org/
To access the command-line utilities after installation
Open a new Terminal window; or
$ eval $(path_helper)
From source code
I got close but gave up after finding GPG Tools. Some tips:
You need both libusbx and libusb-compat to get native CCID support.
If installing GPG2: yes, you need to install all of those crazy libraries---libgpg-error, libgcrypt, libassuan, and libkbsa.
GPG2 expects the old libusb-compat API, not the updated API. libusb-compat requires libusb-1.0 (aka libusbx), so you must install both.
When compiling libusb-compat, you need to explicitly link against libusb-1.0 by passing LDFLAGS="-lusb-1.0" to configure, otherwise you'll get an error about not finding _libusb_init when running gpg.
YubiKey Setup
The YubiKey NEO has three different device modes.
OTP HID-only device, mode 0x80. The key behaves like a regular YubiKey or YubiKey Nano when inserted. This is the factory setting.
OpenPGP CCID-only device, mode 0x81. The key only operates as an OpenPGP CCID smartcard token when inserted. The button acts to enable/disable the reader.
OTP HID+OpenPGP CCID, mode 0x82. The key is visible both as an HOTP HID device and OpenPGP CCID smartcard. The button functions as on a regular YubiKey.
Most people change the mode to 0x82, judging by various HOWTOs, FAQs, and Q&As.
$ ykpersonalize -m82
May need to give full path: /usr/local/yubi/bin/ykpersonalize -m82
Remove and reinsert card to reboot.
Change the PIN
The PIN numbers can be changed after key generation, if desired.
$ gpg --change-pin
The factory default PINs are 123456 (user) and 12345678 (admin).
Key Generation
Key generation is quite simple. So don't worry about going through the process multiple times at first, in case you want to change something.
$ gpg --card-edit
gpg/card> admin
gpg/card> generate
The factory default PINs are 123456 (user) and 12345678 (admin)
Other than the PIN and expiration times, you'll be asked for three additional pieces of information which are ultimately appended together like "Joe Smith (Comment) <jsmith@gmail.com>".
Real Name
E-mail Address
Comment
gpg/card> quit
Multimachine Usage
For some inexplicable reason, GnuPG cannot extract the public key from a smartcard except during generation. That means that to use the key from another computer, you either have to copy the public key from the original computer's GnuPG keyring, or you need to set the URL attribute to a file which contains the PGP public key block. Otherwise, the token is effectively locked to a single computer, and unuseable if you happen to trash your keyring unless you regenerate a key.
Export Public Key
$ gpg --card-status
Make note of the 4-byte (8 hex character) Signature key identifier. The identifier is the last 4 bytes (8 hex characters) of the Signature key fingerprint.
$ gpg --armor --export XXXXXXXX
XXXXXXXX is the Signature key identifier from Step 1.
Copy the output as a regular text file to a publicly accessible web server. You can re-run this command as many times as necessary.
$ gpg --card-edit
gpg/card> admin
gpg/card> url
Enter the URL from Step 2.
Optionally, set the name, language, and other attributes.
gpg/card> quit
Import Public Key
Presuming you've set the URL attribute on the card, and the URL is visible from your new machine, then
$ gpg --card-status
As long as the URL attribute is configured properly, then GnuPG will fetch and import the public key automatically, and the token will be available for use.
OpenSSH Setup
GnuPG's gpg-agent has native support for the OpenSSH ssh-agent protocol, but it needs to be explicitly enabled.
$ echo "enable-ssh-support" >> ~/.gnupg/gpg-agent.conf
Start and restart gpg-agent.
GPG Tools will have added gpg-agent to your launchd configuration, so it should already be running. Kill it and launchd will restart it.
$ pkill gpg-agent
$ gpg --card-status
Make note of the 4-byte (8 hex character) Authentication identifier. The identifier is the last 4 bytes (8 hex characters) of the Authentication key fingerprint.
$ gpgkey2ssh XXXXXXXX
XXXXXXXX is the Authentication key identifier from Step 3.
Append the output to .ssh/authorized_keys on your remote machines. You can re-run this command as many times as necessary.
$ export SSH_AUTH_SOCK=~/.gnupg/S.gpg-agent.ssh
You don't necessarily need to stop OpenSSH's ssh-agent. What matters is that SSH_AUTH_SOCK points to GnuPG's ssh-agent socket at the time you invoke ssh.
You may or may not want to fiddle with setting SSH_AUTH_SOCK in ~/.profile or similar shell initialization file.
It's possible that your GnuPG installation places the ssh-agent socket elsewhere. To get the path:
$ gpg-connect-agent "getinfo ssh_socket_name" /bye
$ ssh your@machine
You probably want to verify somehow that you're authenticating with your smartcard and not a key under ~/.ssh.
# on OS X with GPGTools, comment out the next line:
if test -f $HOME/.gpg-agent-info && \
kill -0 `cut -d: -f 2 $HOME/.gpg-agent-info | head -n1` 2>/dev/null; then
. "${HOME}/.gpg-agent-info"
else
# No, gpg-agent not available; start gpg-agent
eval `gpg-agent --enable-ssh-support --daemon --no-grab --write-env-file $HOME/.gpg-agent-info`
. "${HOME}/.gpg-agent-info"
fi
GPG_TTY=$(tty)
export GPG_TTY
export GPG_AGENT_INFO
export SSH_AUTH_SOCK
pinentry-program /usr/local/MacGPG2/libexec/pinentry-mac.app/Contents/MacOS/pinentry-mac
enable-ssh-support
write-env-file
use-standard-socket
default-cache-ttl 10800
default-cache-ttl-ssh 10800
max-cache-ttl 10800
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment