This is a guide to using YubiKey as a SmartCard for storing GPG keys. An authentication key can also be created for SSH using gpg-agent. Keys stored on a smartcard like YubiKey seem more difficult to steal than ones stored on disk, and are convenient for everyday use. Instructions written on Debian GNU/Linux 8 (jessie) using YubiKey 4 in OTP+CCID mode. Debian live install images are available from [here](https://www.debian.org/CD/live/) and are suitable for writing to USB keys. If you have a comment or suggestion, please open an [issue](https://github.com/drduh/YubiKey-Guide/issues) on GitHub. - [Purchase YubiKey](#purchase-yubikey) - [Install required software](#install-required-software) - [Creating keys](#creating-keys) - [Create temporary working directory for GPG](#create-temporary-working-directory-for-gpg) - [Create configuration](#create-configuration) - [Create master key](#create-master-key) - [Save Key ID](#save-key-id) - [Create revocation certificate](#create-revocation-certificate) - [Back up master key](#back-up-master-key) - [Create subkeys](#create-subkeys) - [Signing key](#signing-key) - [Encryption key](#encryption-key) - [Authentication key](#authentication-key) - [Check your work](#check-your-work) - [Export subkeys](#export-subkeys) - [Back up everything](#back-up-everything) - [Configure YubiKey](#configure-yubikey) - [Configure smartcard](#configure-smartcard) - [Change PINs](#change-pins) - [Set optional card information](#set-optional-card-information) - [Transfer keys](#transfer-keys) - [Signature key](#signature-key) - [Encryption key](#encryption-key-1) - [Authentication key](#authentication-key-1) - [Check your work](#check-your-work-1) - [Export public key](#export-public-key) - [Using keys](#using-keys) - [Insert YubiKey](#insert-yubikey) - [Import public key](#import-public-key) - [Trust master key](#trust-master-key) - [GnuPG](#gnupg) - [Create configuration](#create-configuration-1) - [Encryption/decryption](#encryptiondecryption) - [Signing](#signing) - [SSH](#ssh) - [Update configuration](#update-configuration) - [Replace ssh-agent with gpg-agent](#replace-ssh-agent-with-gpg-agent) - [Copy public key to server](#copy-public-key-to-server) - [Connect with public key authentication](#connect-with-public-key-authentication) - [Notes](#notes) - [References](#references) # Purchase YubiKey https://www.yubico.com/products/yubikey-hardware/ https://www.yubico.com/store/ https://www.amazon.com/Yubico/b/ref=bl_dp_s_web_10358012011?ie=UTF8&node=10358012011 Consider purchasing a pair and programming both in case of loss or damage to oneof them. # Install required software $ sudo apt-get install gnupg-agent pinentry-curses scdaemon pcscd yubikey-personalization If on Tails, you also need to install libykpers-1-1 from the testing repository. This is a temporary fix suggested on [securedrop issues page](https://github.com/freedomofpress/securedrop/issues/1035). $ sudo apt-get install -t testing libykpers-1-1 # Creating keys ## Create temporary working directory for GPG $ export GNUPGHOME=$(mktemp -d) ; echo $GNUPGHOME /tmp/tmp.EBbMfyVDDt ## Create configuration $ cat > $GNUPGHOME/gpg.conf use-agent personal-cipher-preferences AES256 AES192 AES CAST5 personal-digest-preferences SHA512 SHA384 SHA256 SHA224 default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed cert-digest-algo SHA512 s2k-digest-algo SHA512 charset utf-8 fixed-list-mode no-comments no-emit-version keyid-format 0xlong list-options show-uid-validity verify-options show-uid-validity with-fingerprint ^D (Press Control-D) ## Create master key $ gpg --gen-key Please select what kind of key you want: (1) RSA and RSA (default) (2) DSA and Elgamal (3) DSA (sign only) (4) RSA (sign only) Your selection? 4 RSA keys may be between 1024 and 4096 bits long. What keysize do you want? (2048) 4096 Requested keysize is 4096 bits Please specify how long the key should be valid. 0 = key does not expire = key expires in n days w = key expires in n weeks m = key expires in n months y = key expires in n years Key is valid for? (0) 0 Key does not expire at all Is this correct? (y/N) y You need a user ID to identify your key; the software constructs the user ID from the Real Name, Comment and Email Address in this form: "Heinrich Heine (Der Dichter) " Real name: Doctor Duh Email address: drduh@users.noreply.github.com Comment: You selected this USER-ID: "Doctor Duh " Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o You need a Passphrase to protect your secret key. We need to generate a lot of random bytes. It is a good idea to perform some other action (type on the keyboard, move the mouse, utilize the disks) during the prime generation; this gives the random number generator a better chance to gain enough entropy. gpg: /tmp/tmp.eBbMfyVDDt/trustdb.gpg: trustdb created gpg: key 0x47FE984F98EE7407 marked as ultimately trusted public and secret key created and signed. gpg: checking the trustdb gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u pub 4096R/0x47FE984F98EE7407 2016-01-30 Key fingerprint = 044C ABD0 9043 F1E0 3785 3979 47FE 984F 98EE 7407 uid [ultimate] Doctor Duh Note that this key cannot be used for encryption. You may want to use the command "--edit-key" to generate a subkey for this purpose. ## Save Key ID $ KEYID=0x47FE984F98EE7407 ## Create revocation certificate $ gpg --gen-revoke $KEYID > $GNUPGHOME/revoke.txt sec 4096R/0x47FE984F98EE7407 2016-01-30 Doctor Duh Create a revocation certificate for this key? (y/N) y Please select the reason for the revocation: 0 = No reason specified 1 = Key has been compromised 2 = Key is superseded 3 = Key is no longer used Q = Cancel (Probably you want to select 1 here) Your decision? 1 Enter an optional description; end it with an empty line: > Reason for revocation: Key has been compromised (No description given) Is this okay? (y/N) y You need a passphrase to unlock the secret key for user: "Doctor Duh " 4096-bit RSA key, ID 0x47FE984F98EE7407, created 2016-01-30 ASCII armored output forced. Revocation certificate created. Please move it to a medium which you can hide away; if Mallory gets access to this certificate he can use it to make your key unusable. It is smart to print this certificate and store it away, just in case your media become unreadable. But have some caution: The print system of your machine might store the data and make it available to others! ## Back up master key $ gpg --armor --export-secret-keys $KEYID > $GNUPGHOME/master.key ## Create subkeys $ gpg --expert --edit-key $KEYID Secret key is available. pub 4096R/0x47FE984F98EE7407 created: 2016-01-30 expires: never usage: SC trust: ultimate validity: ultimate [ultimate] (1). Doctor Duh ### Signing key gpg> addkey Key is protected. You need a passphrase to unlock the secret key for user: "Doctor Duh " 4096-bit RSA key, ID 0x47FE984F98EE7407, created 2016-01-30 Please select what kind of key you want: (3) DSA (sign only) (4) RSA (sign only) (5) Elgamal (encrypt only) (6) RSA (encrypt only) (7) DSA (set your own capabilities) (8) RSA (set your own capabilities) Your selection? 4 RSA keys may be between 1024 and 4096 bits long. What keysize do you want? (2048) 4096 Requested keysize is 4096 bits Please specify how long the key should be valid. 0 = key does not expire = key expires in n days w = key expires in n weeks m = key expires in n months y = key expires in n years Key is valid for? (0) 0 Key does not expire at all Is this correct? (y/N) y Really create? (y/N) y We need to generate a lot of random bytes. It is a good idea to perform some other action (type on the keyboard, move the mouse, utilize the disks) during the prime generation; this gives the random number generator a better chance to gain enough entropy. .....+++++ .+++++ pub 4096R/0x47FE984F98EE7407 created: 2016-01-30 expires: never usage: SC trust: ultimate validity: ultimate sub 4096R/0xE8E7855AA5AE79A7 created: 2016-01-30 expires: never usage: S [ultimate] (1). Doctor Duh ### Encryption key gpg> addkey Key is protected. You need a passphrase to unlock the secret key for user: "Doctor Duh " 4096-bit RSA key, ID 0x47FE984F98EE7407, created 2016-01-30 Please select what kind of key you want: (3) DSA (sign only) (4) RSA (sign only) (5) Elgamal (encrypt only) (6) RSA (encrypt only) (7) DSA (set your own capabilities) (8) RSA (set your own capabilities) Your selection? 6 RSA keys may be between 1024 and 4096 bits long. What keysize do you want? (2048) 4096 Requested keysize is 4096 bits Please specify how long the key should be valid. 0 = key does not expire = key expires in n days w = key expires in n weeks m = key expires in n months y = key expires in n years Key is valid for? (0) 0 Key does not expire at all Is this correct? (y/N) y Really create? (y/N) y We need to generate a lot of random bytes. It is a good idea to perform some other action (type on the keyboard, move the mouse, utilize the disks) during the prime generation; this gives the random number generator a better chance to gain enough entropy. .+++++ ...........+++++ pub 4096R/0x47FE984F98EE7407 created: 2016-01-30 expires: never usage: SC trust: ultimate validity: ultimate sub 4096R/0xE8E7855AA5AE79A7 created: 2016-01-30 expires: never usage: S sub 4096R/0x39988E0390CB4B0C created: 2016-01-30 expires: never usage: E [ultimate] (1). Doctor Duh ### Authentication key gpg> addkey Key is protected. You need a passphrase to unlock the secret key for user: "Doctor Duh " 4096-bit RSA key, ID 0x47FE984F98EE7407, created 2016-01-30 Please select what kind of key you want: (3) DSA (sign only) (4) RSA (sign only) (5) Elgamal (encrypt only) (6) RSA (encrypt only) (7) DSA (set your own capabilities) (8) RSA (set your own capabilities) Your selection? 8 Possible actions for a RSA key: Sign Encrypt Authenticate Current allowed actions: Sign Encrypt (S) Toggle the sign capability (E) Toggle the encrypt capability (A) Toggle the authenticate capability (Q) Finished Your selection? s Possible actions for a RSA key: Sign Encrypt Authenticate Current allowed actions: Encrypt (S) Toggle the sign capability (E) Toggle the encrypt capability (A) Toggle the authenticate capability (Q) Finished Your selection? e Possible actions for a RSA key: Sign Encrypt Authenticate Current allowed actions: (S) Toggle the sign capability (E) Toggle the encrypt capability (A) Toggle the authenticate capability (Q) Finished Your selection? a Possible actions for a RSA key: Sign Encrypt Authenticate Current allowed actions: Authenticate (S) Toggle the sign capability (E) Toggle the encrypt capability (A) Toggle the authenticate capability (Q) Finished Your selection? q RSA keys may be between 1024 and 4096 bits long. What keysize do you want? (2048) 4096 Requested keysize is 4096 bits Please specify how long the key should be valid. 0 = key does not expire = key expires in n days w = key expires in n weeks m = key expires in n months y = key expires in n years Key is valid for? (0) 0 Key does not expire at all Is this correct? (y/N) y Really create? (y/N) y We need to generate a lot of random bytes. It is a good idea to perform some other action (type on the keyboard, move the mouse, utilize the disks) during the prime generation; this gives the random number generator a better chance to gain enough entropy. +++++ .....+++++ pub 4096R/0x47FE984F98EE7407 created: 2016-01-30 expires: never usage: SC trust: ultimate validity: ultimate sub 4096R/0xE8E7855AA5AE79A7 created: 2016-01-30 expires: never usage: S sub 4096R/0x39988E0390CB4B0C created: 2016-01-30 expires: never usage: E sub 4096R/0x218BCF996C7A6E31 created: 2016-01-30 expires: never usage: A [ultimate] (1). Doctor Duh gpg> save ## Check your work $ gpg --list-secret-keys /tmp/tmp.eBbMfyVDDt/secring.gpg ------------------------------- sec 4096R/0x47FE984F98EE7407 2016-01-30 Key fingerprint = 044C ABD0 9043 F1E0 3785 3979 47FE 984F 98EE 7407 uid Doctor Duh ssb 4096R/0xE8E7855AA5AE79A7 2016-01-30 ssb 4096R/0x39988E0390CB4B0C 2016-01-30 ssb 4096R/0x218BCF996C7A6E31 2016-01-30 ## Export subkeys $ gpg --armor --export-secret-keys $KEYID > $GNUPGHOME/mastersub.key $ gpg --armor --export-secret-subkeys $KEYID > $GNUPGHOME/sub.key ## Back up everything Once keys are moved to hardware, they cannot be extracted again (otherwise, what would be the point?), so make sure you have made an *encrypted* backup before proceeding. To use a USB drive, attach it and check its label: $ dmesg | tail [ 7667.607011] scsi8 : usb-storage 2-1:1.0 [ 7667.608766] usbcore: registered new interface driver usb-storage [ 7668.874016] scsi 8:0:0:0: USB 0: 0 ANSI: 6 [ 7668.874242] sd 8:0:0:0: Attached scsi generic sg4 type 0 [ 7668.874682] sd 8:0:0:0: [sde] 62980096 512-byte logical blocks: (32.2 GB/30.0 GiB) [ 7668.875022] sd 8:0:0:0: [sde] Write Protect is off [ 7668.875023] sd 8:0:0:0: [sde] Mode Sense: 43 00 00 00 [ 7668.877939] sde: sde1 [ 7668.879514] sd 8:0:0:0: [sde] Attached SCSI removable disk Check the size to make sure it's the right drive: $ sudo fdisk -l | grep /dev/sde Disk /dev/sde: 30 GiB, 32245809152 bytes, 62980096 sectors /dev/sde1 2048 62980095 62978048 30G 6 FAT16 Erase and create a new partition table: $ sudo fdisk /dev/sde Welcome to fdisk (util-linux 2.25.2). Changes will remain in memory only, until you decide to write them. Be careful before using the write command. Command (m for help): o Created a new DOS disklabel with disk identifier 0xeac7ee35. Command (m for help): w The partition table has been altered. Calling ioctl() to re-read partition table. Syncing disks. Remove and reinsert the USB drive, then create a new partition: $ sudo fdisk /dev/sde Welcome to fdisk (util-linux 2.25.2). Changes will remain in memory only, until you decide to write them. Be careful before using the write command. Command (m for help): n Partition type p primary (0 primary, 0 extended, 4 free) e extended (container for logical partitions) Select (default p): p Partition number (1-4, default 1): 1 First sector (2048-62980095, default 2048): Last sector, +sectors or +size{K,M,G,T,P} (2048-62980095, default 62980095): Created a new partition 1 of type 'Linux' and of size 30 GiB. Command (m for help): w The partition table has been altered. Calling ioctl() to re-read partition table. Syncing disks. Use LUKS to encrypt the new partition: $ sudo cryptsetup luksFormat /dev/sde1 WARNING! ======== This will overwrite data on /dev/sde1 irrevocably. Are you sure? (Type uppercase yes): YES Enter passphrase: Verify passphrase: Mount the partition and create a filesystem: $ sudo cryptsetup luksOpen /dev/sde1 encrypted-usb Enter passphrase for /dev/sde1: $ sudo mkfs.ext4 /dev/mapper/encrypted-usb -L encrypted-usb mke2fs 1.42.12 (29-Aug-2014) Creating filesystem with 7871744 4k blocks and 1970416 inodes Superblock backups stored on blocks: 32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208, 4096000 Allocating group tables: done Writing inode tables: done Creating journal (32768 blocks): done Writing superblocks and filesystem accounting information: done Mount the filesystem: $ sudo mkdir /mnt/usb $ sudo mount /dev/mapper/encrypted-usb /mnt/usb Finally, copy files to it: $ sudo cp -avi $GNUPGHOME /mnt/usb Make sure the files were copied, then disconnected the USB drive: $ sudo umount /mnt/usb $ sudo cryptsetup luksClose encrypted-usb ## Configure YubiKey $ ykpersonalize -m82 Firmware version 4.2.7 Touch level 527 Program sequence 4 The USB mode will be set to: 0x82 Commit? (y/n) [n]: y > The -m option is the mode command. To see the different modes, enter ykpersonalize –help. Mode 82 (in hex) enables the YubiKey NEO as a composite USB device (HID + CCID) and allows OTPs to be emitted while in use as a smart card. Once you have changed the mode, you need to re-boot the YubiKey – so remove and re-insert it. https://www.yubico.com/2012/12/yubikey-neo-openpgp/ ## Configure smartcard $ gpg --card-edit Application ID ...: D2760001240102010006055532110000 Version ..........: 2.1 Manufacturer .....: unknown Serial number ....: 05553211 Name of cardholder: [not set] Language prefs ...: [not set] Sex ..............: unspecified URL of public key : [not set] Login data .......: [not set] Private DO 1 .....: [not set] Private DO 2 .....: [not set] Signature PIN ....: not forced Key attributes ...: 2048R 2048R 2048R Max. PIN lengths .: 127 127 127 PIN retry counter : 3 3 3 Signature counter : 0 Signature key ....: [none] Encryption key....: [none] Authentication key: [none] General key info..: [none] ### Change PINs The default PIN codes are `12345678` and `123456` gpg/card> admin Admin commands are allowed gpg/card> passwd gpg: OpenPGP card no. D2760001240102010006055532110000 detected 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 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? q ### Set optional card information gpg/card> name Cardholder's surname: Duh Cardholder's given name: Dr gpg/card> lang Language preferences: en gpg/card> login Login data (account name): drduh@users.noreply.github.com gpg/card> Application ID ...: D2760001240102010006055532110000 Version ..........: 2.1 Manufacturer .....: unknown Serial number ....: 05553211 Name of cardholder: Dr Duh Language prefs ...: en Sex ..............: unspecified URL of public key : [not set] Login data .......: drduh@users.noreply.github.com Private DO 4 .....: [not set] Signature PIN ....: not forced Key attributes ...: 2048R 2048R 2048R Max. PIN lengths .: 127 127 127 PIN retry counter : 3 3 3 Signature counter : 0 Signature key ....: [none] Encryption key....: [none] Authentication key: [none] General key info..: [none] gpg/card> quit ## Transfer keys Transfering keys to YubiKey is a one-way operation only: make sure you've made a backup before proceeding! $ gpg --edit-key $KEYID Secret key is available. pub 4096R/0x47FE984F98EE7407 created: 2016-01-30 expires: never usage: SC trust: ultimate validity: ultimate sub 4096R/0xE8E7855AA5AE79A7 created: 2016-01-30 expires: never usage: S sub 4096R/0x39988E0390CB4B0C created: 2016-01-30 expires: never usage: E sub 4096R/0x218BCF996C7A6E31 created: 2016-01-30 expires: never usage: A [ultimate] (1). Doctor Duh gpg> toggle sec 4096R/0x47FE984F98EE7407 created: 2016-01-30 expires: never ssb 4096R/0xE8E7855AA5AE79A7 created: 2016-01-30 expires: never ssb 4096R/0x39988E0390CB4B0C created: 2016-01-30 expires: never ssb 4096R/0x218BCF996C7A6E31 created: 2016-01-30 expires: never (1) Doctor Duh gpg> key 1 sec 4096R/0x47FE984F98EE7407 created: 2016-01-30 expires: never ssb* 4096R/0xE8E7855AA5AE79A7 created: 2016-01-30 expires: never ssb 4096R/0x39988E0390CB4B0C created: 2016-01-30 expires: never ssb 4096R/0x218BCF996C7A6E31 created: 2016-01-30 expires: never (1) Doctor Duh ### Signature key gpg> keytocard Signature key ....: [none] Encryption key....: [none] 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: "Doctor Duh " 4096-bit RSA key, ID 0xE8E7855AA5AE79A7, created 2016-01-30 sec 4096R/0x47FE984F98EE7407 created: 2016-01-30 expires: never ssb* 4096R/0xE8E7855AA5AE79A7 created: 2016-01-30 expires: never card-no: 0006 05553211 ssb 4096R/0x39988E0390CB4B0C created: 2016-01-30 expires: never ssb 4096R/0x218BCF996C7A6E31 created: 2016-01-30 expires: never (1) Doctor Duh ### Encryption key Type `key 1` again to deselect and `key 2` to switch to the next key. gpg> key 1 sec 4096R/0x47FE984F98EE7407 created: 2016-01-30 expires: never ssb 4096R/0xE8E7855AA5AE79A7 created: 2016-01-30 expires: never card-no: 0006 05553211 ssb 4096R/0x39988E0390CB4B0C created: 2016-01-30 expires: never ssb 4096R/0x218BCF996C7A6E31 created: 2016-01-30 expires: never (1) Doctor Duh gpg> key 2 sec 4096R/0x47FE984F98EE7407 created: 2016-01-30 expires: never ssb 4096R/0xE8E7855AA5AE79A7 created: 2016-01-30 expires: never card-no: 0006 05553211 ssb* 4096R/0x39988E0390CB4B0C created: 2016-01-30 expires: never ssb 4096R/0x218BCF996C7A6E31 created: 2016-01-30 expires: never (1) Doctor Duh gpg> keytocard Signature key ....: 04CB BB4B 1D99 3398 A0B1 4C4B E8E7 855A A5AE 79A7 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: "Doctor Duh " 4096-bit RSA key, ID 0x39988E0390CB4B0C, created 2016-01-30 sec 4096R/0x47FE984F98EE7407 created: 2016-01-30 expires: never ssb 4096R/0xE8E7855AA5AE79A7 created: 2016-01-30 expires: never card-no: 0006 05553211 ssb* 4096R/0x39988E0390CB4B0C created: 2016-01-30 expires: never card-no: 0006 05553211 ssb 4096R/0x218BCF996C7A6E31 created: 2016-01-30 expires: never (1) Doctor Duh ### Authentication key gpg> key 2 sec 4096R/0x47FE984F98EE7407 created: 2016-01-30 expires: never ssb 4096R/0xE8E7855AA5AE79A7 created: 2016-01-30 expires: never card-no: 0006 05553211 ssb 4096R/0x39988E0390CB4B0C created: 2016-01-30 expires: never card-no: 0006 05553211 ssb 4096R/0x218BCF996C7A6E31 created: 2016-01-30 expires: never (1) Doctor Duh gpg> key 3 sec 4096R/0x47FE984F98EE7407 created: 2016-01-30 expires: never ssb 4096R/0xE8E7855AA5AE79A7 created: 2016-01-30 expires: never card-no: 0006 05553211 ssb 4096R/0x39988E0390CB4B0C created: 2016-01-30 expires: never card-no: 0006 05553211 ssb* 4096R/0x218BCF996C7A6E31 created: 2016-01-30 expires: never (1) Doctor Duh gpg> keytocard Signature key ....: 04CB BB4B 1D99 3398 A0B1 4C4B E8E7 855A A5AE 79A7 Encryption key....: 8AB0 607B A1C1 0F19 2627 6EA6 3998 8E03 90CB 4B0C Authentication key: [none] Please select where to store the key: (3) Authentication key Your selection? 3 You need a passphrase to unlock the secret key for user: "Doctor Duh " 4096-bit RSA key, ID 0x218BCF996C7A6E31, created 2016-01-30 sec 4096R/0x47FE984F98EE7407 created: 2016-01-30 expires: never ssb 4096R/0xE8E7855AA5AE79A7 created: 2016-01-30 expires: never card-no: 0006 05553211 ssb 4096R/0x39988E0390CB4B0C created: 2016-01-30 expires: never card-no: 0006 05553211 ssb* 4096R/0x218BCF996C7A6E31 created: 2016-01-30 expires: never card-no: 0006 05553211 (1) Doctor Duh gpg> save ## Check your work $ gpg --list-secret-keys /tmp/tmp.eBbMfyVDDt/secring.gpg ------------------------------- sec 4096R/0x47FE984F98EE7407 2016-01-30 Key fingerprint = 044C ABD0 9043 F1E0 3785 3979 47FE 984F 98EE 7407 uid Doctor Duh ssb> 4096R/0xE8E7855AA5AE79A7 2016-01-30 ssb> 4096R/0x39988E0390CB4B0C 2016-01-30 ssb> 4096R/0x218BCF996C7A6E31 2016-01-30 `ssb>` indicates a stub to the private key on smartcard. ## Export public key $ gpg --armor --export $KEYID > /mnt/public-usb-key/ # Using keys ## Insert YubiKey $ gpg --card-status Application ID ...: D2760001240102010006055532110000 Version ..........: 2.1 Manufacturer .....: unknown Serial number ....: 05553211 Name of cardholder: Dr Duh Language prefs ...: en Sex ..............: unspecified URL of public key : [not set] Login data .......: drduh@users.noreply.github.com Signature PIN ....: not forced Key attributes ...: 4096R 4096R 4096R Max. PIN lengths .: 127 127 127 PIN retry counter : 3 3 3 Signature counter : 0 Signature key ....: 04CB BB4B 1D99 3398 A0B1 4C4B E8E7 855A A5AE 79A7 created ....: 2016-01-30 16:36:40 Encryption key....: 8AB0 607B A1C1 0F19 2627 6EA6 3998 8E03 90CB 4B0C created ....: 2016-01-30 16:42:29 Authentication key: 3B81 E129 B7C3 26F4 2EA1 2F19 218B CF99 6C7A 6E31 created ....: 2016-01-30 16:44:48 General key info..: pub 4096R/0xE8E7855AA5AE79A7 2016-01-30 Doctor Duh sec# 4096R/0x47FE984F98EE7407 created: 2016-01-30 expires: never ssb> 4096R/0xE8E7855AA5AE79A7 created: 2016-01-30 expires: never card-no: 0006 05553211 ssb> 4096R/0x39988E0390CB4B0C created: 2016-01-30 expires: never card-no: 0006 05553211 ssb> 4096R/0x218BCF996C7A6E31 created: 2016-01-30 expires: never card-no: 0006 05553211 `sec#` indicates master key is not available (as it should be stored encrypted and offline). ## Import public key $ gpg --import < /mnt/public-usb-key/pubkey.txt ## Trust master key $ gpg --edit-key $KEYID Secret key is available. pub 4096R/0x47FE984F98EE7407 created: 2016-01-30 expires: never usage: SC trust: unknown validity: unknown sub 4096R/0xE8E7855AA5AE79A7 created: 2016-01-30 expires: never usage: S sub 4096R/0x39988E0390CB4B0C created: 2016-01-30 expires: never usage: E sub 4096R/0x218BCF996C7A6E31 created: 2016-01-30 expires: never usage: A [ unknown] (1). Doctor Duh gpg> trust pub 4096R/0x47FE984F98EE7407 created: 2016-01-30 expires: never usage: SC trust: unknown validity: unknown sub 4096R/0xE8E7855AA5AE79A7 created: 2016-01-30 expires: never usage: S sub 4096R/0x39988E0390CB4B0C created: 2016-01-30 expires: never usage: E sub 4096R/0x218BCF996C7A6E31 created: 2016-01-30 expires: never usage: A [ unknown] (1). Doctor Duh Please decide how far you trust this user to correctly verify other users' keys (by looking at passports, checking fingerprints from different sources, etc.) 1 = I don't know or won't say 2 = I do NOT trust 3 = I trust marginally 4 = I trust fully 5 = I trust ultimately m = back to the main menu Your decision? 5 Do you really want to set this key to ultimate trust? (y/N) y pub 4096R/0x47FE984F98EE7407 created: 2016-01-30 expires: never usage: SC trust: ultimate validity: unknown sub 4096R/0xE8E7855AA5AE79A7 created: 2016-01-30 expires: never usage: S sub 4096R/0x39988E0390CB4B0C created: 2016-01-30 expires: never usage: E sub 4096R/0x218BCF996C7A6E31 created: 2016-01-30 expires: never usage: A [ unknown] (1). Doctor Duh Please note that the shown key validity is not necessarily correct unless you restart the program. gpg> quit ## GnuPG ### Create configuration $ cat > ~/.gnupg/gpg.conf use-agent personal-cipher-preferences AES256 AES192 AES CAST5 personal-digest-preferences SHA512 SHA384 SHA256 SHA224 default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed cert-digest-algo SHA512 s2k-digest-algo SHA512 charset utf-8 fixed-list-mode no-comments no-emit-version keyid-format 0xlong list-options show-uid-validity verify-options show-uid-validity with-fingerprint ^D (Press Control-D) ### Encryption/decryption $ echo "$(uname -a)" | gpg --encrypt --armor -r $KEYID | gpg --decrypt --armor Please enter the PIN gpg: encrypted with 4096-bit RSA key, ID 0x39988E0390CB4B0C, created 2016-01-30 "Doctor Duh " Linux workstation 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt20-1+deb8u3 (2016-01-17) x86_64 GNU/Linux ### Signing $ echo "$(uname -a)" | gpg --encrypt --armor --sign -r $KEYID gpg: signatures created so far: 0 Please enter the PIN [sigs done: 0] -----BEGIN PGP MESSAGE----- hQIMAzmYjgOQy0sMAQ//bG8YyEinTOFzL/aL/BN54/PAFzBZj6B//dEFXYu5NlHJ [...] sjLN5ZhJkQKJeUWIVdGeuZN+pIeIRWQHeKD7xRUgij6/nC7qCfPPkHFYxQ== =jztu -----END PGP MESSAGE----- ## SSH ### Update configuration $ cat > ~/.gnupg/gpg-agent.conf enable-ssh-support pinentry-program /usr/bin/pinentry-curses default-cache-ttl 60 max-cache-ttl 120 write-env-file use-standard-socket ^D (Press Control-D) ### Replace ssh-agent with gpg-agent $ pkill ssh-agent ; \ eval $(gpg-agent --daemon --enable-ssh-support --use-standard-socket \ --log-file ~/.gnupg/gpg-agent.log --write-env-file) ### Copy public key to server $ ssh-add -L ssh-rsa AAAAB4NzaC1yc2EAAAADAQABAAACAz[...]zreOKM+HwpkHzcy9DQcVG2Nw== cardno:000605553211 ### Connect with public key authentication $ ssh git@github.com -vvv [...] debug2: key: cardno:000605553211 (0x1234567890), debug1: Authentications that can continue: publickey debug3: start over, passed a different list publickey debug3: preferred gssapi-keyex,gssapi-with-mic,publickey,keyboard-interactive,password debug3: authmethod_lookup publickey debug3: remaining preferred: keyboard-interactive,password debug3: authmethod_is_enabled publickey debug1: Next authentication method: publickey debug1: Offering RSA public key: cardno:000605553211 debug3: send_pubkey_test debug2: we sent a publickey packet, wait for reply debug1: Server accepts key: pkalg ssh-rsa blen 535 debug2: input_userauth_pk_ok: fp e5:de:a5:74:b1:3e:96:9b:85:46:e7:28:53:b4:82:c3 debug3: sign_and_send_pubkey: RSA e5:de:a5:74:b1:3e:96:9b:85:46:e7:28:53:b4:82:c3 debug1: Authentication succeeded (publickey). [...] # Notes - Don't write to drduh@users.noreply.github.com, open an issue on GitHub instead. - Programming YubiKey for GPG keys still lets you use its two slots - OTP and static password modes, for example. - If you encounter problems, simply try unplugging and re-inserting your YubiKey, and restarting the `gpg-agent` process. - ECC may be preferred to RSA 4096, but the 1.4.x branch of GnuPG does not support it. - Try installing and using the newer, more feature-rich [GnuPG 2.x](https://superuser.com/questions/655246/are-gnupg-1-and-gnupg-2-compatible-with-each-other) with `sudo apt-get install gnupg2` # References