YubiKey-Guide/README.md

1010 lines
34 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
# 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
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>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) <heinrichh@duesseldorf.de>"
Real name: Doctor Duh
Email address: drduh@users.noreply.github.com
Comment:
You selected this USER-ID:
"Doctor Duh <drduh@users.noreply.github.com>"
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 <drduh@users.noreply.github.com>
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 <drduh@users.noreply.github.com>
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 <drduh@users.noreply.github.com>"
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 <drduh@users.noreply.github.com>
### Signing key
gpg> addkey
Key is protected.
You need a passphrase to unlock the secret key for
user: "Doctor Duh <drduh@users.noreply.github.com>"
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
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>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 <drduh@users.noreply.github.com>
### Encryption key
gpg> addkey
Key is protected.
You need a passphrase to unlock the secret key for
user: "Doctor Duh <drduh@users.noreply.github.com>"
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
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>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 <drduh@users.noreply.github.com>
### Authentication key
gpg> addkey
Key is protected.
You need a passphrase to unlock the secret key for
user: "Doctor Duh <drduh@users.noreply.github.com>"
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
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>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 <drduh@users.noreply.github.com>
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 <drduh@users.noreply.github.com>
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 <drduh@users.noreply.github.com>
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 <drduh@users.noreply.github.com>
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 <drduh@users.noreply.github.com>
### 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 <drduh@users.noreply.github.com>"
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 <drduh@users.noreply.github.com>
### 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 <drduh@users.noreply.github.com>
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 <drduh@users.noreply.github.com>
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 <drduh@users.noreply.github.com>"
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 <drduh@users.noreply.github.com>
### 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 <drduh@users.noreply.github.com>
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 <drduh@users.noreply.github.com>
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 <drduh@users.noreply.github.com>"
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 <drduh@users.noreply.github.com>
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 <drduh@users.noreply.github.com>
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 <drduh@users.noreply.github.com>
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 <drduh@users.noreply.github.com>
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 <drduh@users.noreply.github.com>
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 <drduh@users.noreply.github.com>
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 <drduh@users.noreply.github.com>"
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
<https://developers.yubico.com/yubikey-personalization/>
<https://developers.yubico.com/PGP/Card_edit.html>
<https://blog.josefsson.org/2014/06/23/offline-gnupg-master-key-and-subkeys-on-yubikey-neo-smartcard/>
<https://www.esev.com/blog/post/2015-01-pgp-ssh-key-on-yubikey-neo/>
<https://blog.habets.se/2013/02/GPG-and-SSH-with-Yubikey-NEO>
<https://trmm.net/Yubikey>
<https://rnorth.org/8/gpg-and-ssh-with-yubikey-for-mac>
<https://jclement.ca/articles/2015/gpg-smartcard/>
<https://github.com/herlo/ssh-gpg-smartcard-config>
<http://www.bootc.net/archives/2013/06/09/my-perfect-gnupg-ssh-agent-setup/>
<https://help.riseup.net/en/security/message-security/openpgp/best-practices>