



Edward Snowden says to trust in encryption, but you still need to worry about the security of the computer systems that run it:

Encryption works. Properly implemented strong crypto systems are one of the few things that you can rely on. Unfortunately, endpoint security is so terrifically weak that NSA can frequently find ways around it.

If you're worried that you're not paranoid enough about your communications security and want to improve your OpSec, it is actually fairly easy to go "full-Snowden" with hardware storage of your PGP secret keys. The Yubico Yubikey-Neo and Neo-N USB tokens are a neat (and cheap) way to keep your keys locked in a hardware device rather than stored as a file on your harddrive. The hardware tokens are compatible with the OpenPGP card protocol, which recent versions of gnupg support out-of-the-box. All of the public-key cryptography happens inside the tamper-proof device, so your secret key is never decrypted in the memory nor stored on disk of your machine.

Software

GPGTools provides a very nice key management GUI as well as a plug-in for Apple Mail.app. It also bundles the commandline version of gnupg 2.0.22, which you will need for doing some specialized functions.

Note that there is a bug in OS X Yosemite related to GPG card tokens not working.

Create your key

Run the GPG Keychain Access tool that the suite installed in /Applications and click the New Key button. Fill in your name and email and select the key type. The older Yubikey devices support up to RSA2048, so the defaults of "RSA and RSA" with length 2048 are correct. Yubikey Nano 4 added support for 4096 bit keys in late 2015 and you can select that if you want longer keys. Both devices also support secure key generation in hardware, but this requires some further steps in the terminal and is beyond the scope of this tutorial.

Expiration dates aren't required, but they are good idea since nothing lasts forever. You can still decrypt old emails and documents, as well as verify signatures, with an expired key, but no one will send you new ones.

You will need to pick a pass-phrase for the key -- make it a good one since it is the only thing that protects your key file while it is on disk. This Passphrase FAQ has some suggestions for picking a memorable one. You'll only need to type it in during these key operations and when you sign other users' keys.

By default GPG Keychain tool create the primary key that has all access and one encryption subkey. For the cards you need to create a second subkey for signing. Double click on your key to bring up the Key Inspector window, select Subkeys and click + to create a new one of type RSA (sign only) and of length 2048.

At this point you should export your key and save it somewhere safely offline. Right click on your key in the main window and select "Export" and check Allow secret key export. As part of moving the keys into the hardware token they will be deleted from your keyring. If you were to lose the Yubikey, you would not be able to recover the keys.

It is also worth creating a key revocation certificate. If you were to lose your keys or your passphrase, a pre-generated revocation certificate allows you to announce to the world that the key is no longer valid and should no longer be trusted. Right click on your key and save the revocation cert offline safely as well.

Lastly, you can also now select to Send public key to Keyserver, which will make your public key available to others. This is how they will be able to encrypt messages that only you will be able to read and how they will be able to verify signatures that you make.

Transfer keys to hardware

At this point we need to switch from the user-friendly GPG Keychain Access window to the gpg program in the terminal. Don't panic! Make note of your key's Short ID -- this is how it will be referenced with the command line utility. In this case mine is 17db29be

Plug in your Yubikey and open Terminal.app (in /Applications/Utilities) and get ready for classic 1990s user interfaces. In these examples, the text you type is in bold, % is the shell prompt and everything else is printed by the gpg program.

First you need to enable the OpenPGP Card / CCID mode. The ykpersonalize program can be downloaded from yubico on github. You only need to do this once and can delete the program once you've run it.

% ~/Downloads/ykpers-1.16.0-mac/bin/ykpersonalize -m82 Firmware version 3.3.0 Touch level 1285 Program sequence 1 The USB mode will be set to: 0x82 Commit? (y/n) [n]: y

Now let's edit your public key:

% /usr/local/bin/gpg --edit-key 17db29be gpg (GnuPG/MacGPG2) 2.0.22; Copyright (C) 2013 Free Software Foundation, Inc. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Secret key is available. pub 2048R/17DB29BE created: 2014-11-16 expires: 2018-11-16 usage: SC trust: ultimate validity: ultimate sub 2048R/FAFFECA6 created: 2014-11-16 expires: 2018-11-16 usage: E sub 2048R/A9057450 created: 2014-11-16 expires: 2018-11-16 usage: S [ultimate] (1). Trammell Hudson <hudson@trmm.net> gpg>

GnuPG is now waiting for another command from you. We need to switch to editing the secret key portion of this key with the toggle command and then select the first non-primary key with the key command.

gpg> toggle sec 2048R/17DB29BE created: 2014-11-16 expires: 2018-11-16 ssb 2048R/FAFFECA6 created: 2014-11-16 expires: never ssb 2048R/A9057450 created: 2014-11-16 expires: never (1) Trammell Hudson <hudson@trmm.net> gpg> key 1 sec 2048R/17DB29BE created: 2014-11-16 expires: 2018-11-16 ssb* 2048R/FAFFECA6 created: 2014-11-16 expires: never ssb 2048R/A9057450 created: 2014-11-16 expires: never (1) Trammell Hudson <hudson@trmm.net>

Now we'll run the keytocard command to copy this key to the card.

gpg> keytocard Signature key ....: none Encryption key....: none Authentication key: none Please select where to store the key: (2) Encryption key Your selection? 2 You need a passphrase to unlock the secret key for user: "Trammell Hudson <hudson@trmm.net>" 2048-bit RSA key, ID FAFFECA6, created 2014-11-16

It will pop up a dialog prompting for the passphrase to unlock the key at this point. You'll need to enter your passphrase. Once your secret key is unlocked, it will need the Admin PIN for the hardware token. The default is 12345678 ; we will change it later. Once you've passed both of these dialogs, gnupg will print out the secret keys and show that key 1 has been copied to the card and no longer resides in the keyring:

sec 2048R/17DB29BE created: 2014-11-16 expires: 2018-11-16 ssb* 2048R/FAFFECA6 created: 2014-11-16 expires: never card-no: 0006 03036660 ssb 2048R/A9057450 created: 2014-11-16 expires: never (1) Trammell Hudson <hudson@trmm.net>

Now we need to deselect key 1, select key 2 and upload the signing key:

gpg> key 1 sec 2048R/17DB29BE created: 2014-11-16 expires: 2018-11-16 ssb 2048R/FAFFECA6 created: 2014-11-16 expires: never card-no: 0006 03036660 ssb 2048R/A9057450 created: 2014-11-16 expires: never (1) Trammell Hudson <hudson@trmm.net> gpg> key 2 sec 2048R/17DB29BE created: 2014-11-16 expires: 2018-11-16 ssb 2048R/FAFFECA6 created: 2014-11-16 expires: never card-no: 0006 03036660 ssb* 2048R/A9057450 created: 2014-11-16 expires: never (1) Trammell Hudson <hudson@trmm.net> gpg> keytocard Signature key ....: none Encryption key....: D04F 94C6 EF86 C150 9486 3F5C 2695 8563 FAFF ECA6 Authentication key: none Please select where to store the key: (1) Signature key (3) Authentication key Your selection? 1 You need a passphrase to unlock the secret key for user: "Trammell Hudson <hudson@trmm.net>" 2048-bit RSA key, ID A9057450, created 2014-11-16

Unlock the key as before. You won't need the admin PIN a second time since the token is unlocked.

sec 2048R/17DB29BE created: 2014-11-16 expires: 2018-11-16 ssb 2048R/FAFFECA6 created: 2014-11-16 expires: never card-no: 0006 03036660 ssb* 2048R/A9057450 created: 2014-11-16 expires: never card-no: 0006 03036660 (1) Trammell Hudson <hudson@trmm.net>

Now both keys are transferred to the card. Save the changes to the secret key on disk and exit gnupg:

gpg> save

Set hardware PINs

Still in the terminal, we'll use GnuPG to edit the card values. Your values might differ slightly.

% /usr/local/bin/gpg --card-edit Application ID ...: D2760001240102000006030366600000 Version ..........: 2.0 Manufacturer .....: unknown Serial number ....: 03036660 Name of cardholder: Trammell Hudson Language prefs ...: [not set] Sex ..............: unspecified URL of public key : https://pgp.mit.edu/pks/lookup?op=get&search=0xB65BFE540DEF86C0 Login data .......: hudson@trmm.net Signature PIN ....: forced Key attributes ...: 2048R 2048R 2048R Max. PIN lengths .: 127 127 127 PIN retry counter : 3 3 3 Signature counter : 12 Signature key ....: 7EBB 6AFB 7B36 B4EE 39AD 2EE1 AC49 5576 A905 7450 created ....: 2014-11-16 04:11:18 Encryption key....: D04F 94C6 EF86 C150 9486 3F5C 2695 8563 FAFF ECA6 created ....: 2014-11-16 04:09:21 Authentication key: 8175 10FD F418 2B9B 50BF DB03 DD20 72FC C749 00F0 created ....: 2014-11-16 03:55:59 General key info..: pub 2048R/A9057450 2014-11-16 Trammell Hudson <hudson@trmm.net> sec 2048R/17DB29BE created: 2014-11-16 expires: 2018-11-16 ssb> 2048R/FAFFECA6 created: 2014-11-16 expires: 2018-11-16 card-no: 0006 03036660 ssb> 2048R/A9057450 created: 2014-11-16 expires: 2018-11-16 card-no: 0006 03036660 gpg/card>

Switch to Admin mode and change the PIN:

gpg/card> admin Admin commands are allowed gpg/card> passwd gpg: OpenPGP card no. D2760001240102000006030366600000 detected 1 - change PIN 2 - unblock PIN 3 - change Admin PIN 4 - set the Reset Code Q - quit Your selection? 1

A dialog box should pop up asking for the current pin; the default is 123456 . The new pin must be at least 6 digits long or it will give you an error:

Error changing the PIN: Conditions of use not satisfied

If you have satisfied the condition, you'll get a success message:

PIN changed.

Repeat for the Admin PIN; this one must be 8 digits or longer.

Test Apple Mail

Quit and restart Apple Mail. There should be a new preferences pane for GPGMail. Encrypting by default is a good idea.

When you create a new message, there should be an OpenPGP flag on the upper corner of the compose window and two new buttons that indicate Encrypted and Signed. If you have the public key for the recipient and have selected to default to encryption, the button should automatically be selected.

gpg-agent and ssh

You can also use the GPG Authentiation key stored in the Yubikey for ssh authentication. gpg-agent can be used in place of ssh-agent ; when you login to a remote host it will prompt you for your PIN (either via a popup or on the terminal). My ~/.gnupg/gpg-agent.conf contains:

pinentry-program /usr/local/MacGPG2/libexec/pinentrymac.app/Contents/MacOS/pinentry-mac enable-ssh-support write-env-file use-standard-socket

And I have added these lines to my ~/.profile to configure ssh to talk to gpg-agent:

if [ -r "~/.gpg-agent-info" ]; then . "~.gpg-agent-info" fi

To extract the public key for adding to ~/.ssh/authorized_keys on the remote side, run ssh-add -L . it should print something like:

ssh-rsa AAAAB3Nza[...] cardno:000603036660

Now What?