To start, i wanted to store my gnu keys on an secured external USB drive, such that i could lock the original keys in a safe, and they store the private key on an YubiKey 5Ci. First, i needed a USB drive, which i setup as an encrypted filesystem on my mac.
Of note, i'm borrowing a bit from "Dr. Duh" on github, and they have a great guide for the very paranoid here: https://github.com/drduh/YubiKey-Guide , Additionally the Free Software founding has a great guide here, and they have a bot setup to help you test your setup!
Setup on your usb drive a folder for your GunPGP keys and configuration.
additionally I will setup my bash environment so that all of my configurations will end up on the usb drive and not on my system. Also I'm assuming you have made the folder on usb drive already
$ export GNUPGHOME=$(pwd)
Despite the fact I'm using an encrypted usb drive, we should also ensure the permissions on the folder do not allow anyone else to take a peek while it's mounted.
$ chmod og=,u=rwX $GNUPGHOME
$ chmod og=,u=rwX $GNUPGHOME/*
Setup your gpg.conf, (store this in the $GNUPGHOME folder)
Generate your Master Key
Be sure to use a strong password, and one you can store in a secure location, as this is NOT RECOVERABLE!
$ gpg --expert --full-generate-key
gpg (GnuPG) 2.2.16; Copyright (C) 2019 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.
gpg: keybox '/Volumes/Ogg_Rescue/gnupg/pubring.kbx' created
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)
(7) DSA (set your own capabilities)
(8) RSA (set your own capabilities)
(9) ECC and ECC
(10) ECC (sign only)
(11) ECC (set your own capabilities)
(13) Existing key
Your selection? 8
Possible actions for a RSA key: Sign Certify Encrypt Authenticate
Current allowed actions: Sign Certify 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 Certify Encrypt Authenticate
Current allowed actions: Sign Certify
(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 Certify Encrypt Authenticate
Current allowed actions: Certify
(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
GnuPG needs to construct a user ID to identify your key.
Real name: Dr. Ogg
Email address: ogg@sr375.com
Comment:
You selected this USER-ID:
"Dr. Ogg <ogg@sr375.com>"
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
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: /Volumes/Ogg_Rescue/gnupg/trustdb.gpg: trustdb created
gpg: key 0x585C80B653416059 marked as ultimately trusted
gpg: directory '/Volumes/Ogg_Rescue/gnupg/openpgp-revocs.d' created
gpg: revocation certificate stored as '/Volumes/Ogg_Rescue/gnupg/openpgp-revocs.d/9A53E6A0DC152759E944D557585C80B653416059.rev'
public and secret key created and signed.
pub rsa4096/0x585C80B653416059 2019-11-16 [C]
Key fingerprint = 9A53 E6A0 DC15 2759 E944 D557 585C 80B6 5341 6059
uid Dr. Ogg <ogg@sr375.com>
Export you're key id:
$ export KEYID=0x585C80B653416059
Sub Keys (yes, you need them)
Now that we have our master key setup, we can generate sub keys for the year, so we can rotate keys for better security..
I'm going to create 2 different types of keys, one i can use to sign with and one i can encrypt with.
Signing key
$ gpg --expert --edit-key $KEYID
gpg> addkey
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)
(10) ECC (sign only)
(11) ECC (set your own capabilities)
(12) ECC (encrypt only)
(13) Existing key
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) 1y
Key expires at Sun Nov 15 12:32:11 2020 PST
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.
sec rsa4096/0x585C80B653416059
created: 2019-11-16 expires: never usage: C
trust: ultimate validity: ultimate
ssb rsa4096/0xA5A3330518BEE712
created: 2019-11-16 expires: 2020-11-15 usage: S
[ultimate] (1). Dr. Ogg <ogg@sr375.com>
gpg> save
Encryption Key
$ gpg --expert --edit-key $KEYID
gpg> addkey
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)
(10) ECC (sign only)
(11) ECC (set your own capabilities)
(12) ECC (encrypt only)
(13) Existing key
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) 1y
Key expires at Sun Nov 15 12:33:22 2020 PST
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.
sec rsa4096/0x585C80B653416059
created: 2019-11-16 expires: never usage: C
trust: ultimate validity: ultimate
ssb rsa4096/0xA5A3330518BEE712
created: 2019-11-16 expires: 2020-11-15 usage: S
ssb rsa4096/0x0D4B6E2A567C9EA3
created: 2019-11-16 expires: 2020-11-15 usage: E
[ultimate] (1). Dr. Ogg <ogg@sr375.com>
gpg> save
Prepare your Yubikey for use
First we need to see if gpg can talk with your key...
$ gpg --card-status
Reader ...........: 1050:0407:X:0
Application ID ...: D2760001240103040006111562730000
Version ..........: 3.4
Manufacturer .....: Yubico
Serial number ....: 11156273
Name of cardholder: Dr. Ogg
Language prefs ...: en
you should get something back that looks like that... if not, your configuration or system may require more help than I'm addressing here.
Let's reset the key to factory settings (yes, this will erase the key)
Download and install YubiKey Manager.
$ ykman openpgp reset
WARNING! This will delete all stored OpenPGP keys and data and restore factory settings? [y/N]: y
Resetting OpenPGP data, don't remove your YubiKey...
Success! All data has been cleared and default PINs are set.
PIN: 123456
Reset code: NOT SET
Admin PIN: 12345678
If there are issues you can find additional help on the official YubiKey support site.
notice after you have reset your Yubikey it the card-status command will no longer show the cardholder name or any other details...
$ gpg --card-status
Reader ...........: Yubico YubiKey OTP FIDO CCID
Application ID ...: D2760001240103040006111562730000
Version ..........: 3.4
Manufacturer .....: Yubico
Serial number ....: 11156273
Name of cardholder: [not set]
Language prefs ...: [not set]
Sex ..............: unspecified
At this point, we are back at factory defaults, YOU SHOULD SET A NEW PIN on your Yubikey at this point.
$ gpg --card-edit
Reader ...........: Yubico YubiKey OTP FIDO CCID
Application ID ...: D2760001240103040006111562730000
Version ..........: 3.4
gpg/card> admin
Admin commands are allowed
gpg/card> passwd
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? q
gpg/card> quit
And if you so desire, not required... however you can set the cardholder name.
$ gpg --card-edit
Reader ...........: Yubico YubiKey OTP FIDO CCID
Application ID ...: D2760001240103040006111562730000
Version ..........: 3.4
Manufacturer .....: Yubico
Serial number ....: 11156273
Name of cardholder: [not set]
Language prefs ...: [not set]
Sex ..............: unspecified
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: not forced
Key attributes ...: rsa2048 rsa2048 rsa2048
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 0
KDF setting ......: on
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
General key info..: [none]
gpg/card> admin
Admin commands are allowed
gpg/card> name
Cardholder's surname: Shufflebottom
Cardholder's given name: Dr. Ogg
Import keys to your Yubikey...
WARNING: the following operation will have a destructive effect on your gpg keys, you should make a backup of your $GNUPGHOME before proceeding..
NOTE: How do you know what key you can use for what purpose? Look for the Usage label on the key list, "C" is a Key Certificate, "S" is used for signing, E is for Encryption, and A is for Authentication.
backup your keys:
$ tar -czvf gpg-backup.tgz $GNUPGHOME
Now that we have a backup we can proceed to import our sub-keys
gpg --edit-key $KEYID
gpg (GnuPG) 2.2.16; Copyright (C) 2019 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.
sec rsa4096/0x585C80B653416059
created: 2019-11-16 expires: never usage: C
trust: ultimate validity: ultimate
ssb rsa4096/0xA5A3330518BEE712
created: 2019-11-16 expires: 2020-11-15 usage: S
ssb rsa4096/0x0D4B6E2A567C9EA3
created: 2019-11-16 expires: 2020-11-15 usage: E
[ultimate] (1). Dr. Ogg <ogg@sr375.com>
Let's transfer our signing key first:
gpg> key 1
sec rsa4096/0x585C80B653416059
created: 2019-11-16 expires: never usage: C
trust: ultimate validity: ultimate
ssb* rsa4096/0xA5A3330518BEE712
created: 2019-11-16 expires: 2020-11-15 usage: S
ssb rsa4096/0x0D4B6E2A567C9EA3
created: 2019-11-16 expires: 2020-11-15 usage: E
[ultimate] (1). Dr. Ogg <ogg@sr375.com>
Note, when i select key 1, it will add an asterisk "*" next to the key you are selecting.
gpg> keytocard
Please select where to store the key:
(1) Signature key
(3) Authentication key
Your selection? 1
sec rsa4096/0x585C80B653416059
created: 2019-11-16 expires: never usage: C
trust: ultimate validity: ultimate
ssb* rsa4096/0xA5A3330518BEE712
created: 2019-11-16 expires: 2020-11-15 usage: S
ssb rsa4096/0x0D4B6E2A567C9EA3
created: 2019-11-16 expires: 2020-11-15 usage: E
[ultimate] (1). Dr. Ogg <ogg@sr375.com>
When you run this command, it will transfer the key, but it will ask for your the key passphrase then it will ask for the pin you have set on the Yubikey.
Type key 1
again to de-select and key 2
to select the next key:
gpg> key 1
sec rsa4096/0x585C80B653416059
created: 2019-11-16 expires: never usage: C
trust: ultimate validity: ultimate
ssb rsa4096/0xA5A3330518BEE712
created: 2019-11-16 expires: 2020-11-15 usage: S
ssb rsa4096/0x0D4B6E2A567C9EA3
created: 2019-11-16 expires: 2020-11-15 usage: E
[ultimate] (1). Dr. Ogg <ogg@sr375.com>
gpg> key 2
sec rsa4096/0x585C80B653416059
created: 2019-11-16 expires: never usage: C
trust: ultimate validity: ultimate
ssb rsa4096/0xA5A3330518BEE712
created: 2019-11-16 expires: 2020-11-15 usage: S
ssb* rsa4096/0x0D4B6E2A567C9EA3
created: 2019-11-16 expires: 2020-11-15 usage: E
[ultimate] (1). Dr. Ogg <ogg@sr375.com>
gpg> keytocard
Please select where to store the key:
(2) Encryption key
Your selection? 2
sec rsa4096/0x585C80B653416059
created: 2019-11-16 expires: never usage: C
trust: ultimate validity: ultimate
ssb rsa4096/0xA5A3330518BEE712
created: 2019-11-16 expires: 2020-11-15 usage: S
ssb* rsa4096/0x0D4B6E2A567C9EA3
created: 2019-11-16 expires: 2020-11-15 usage: E
[ultimate] (1). Dr. Ogg <ogg@sr375.com>
then exit and save the gpg program
gpg> save
Let's check to see if our keys have been moved:
$ gpg --list-secret-keys
gnupg/pubring.kbx
-------------------------------------
sec rsa4096/0x585C80B653416059 2019-11-16 [C]
Key fingerprint = 9A53 E6A0 DC15 2759 E944 D557 585C 80B6 5341 6059
uid [ultimate] Dr. Ogg <ogg@sr375.com>
ssb> rsa4096/0xA5A3330518BEE712 2019-11-16 [S] [expires: 2020-11-15]
ssb> rsa4096/0x0D4B6E2A567C9EA3 2019-11-16 [E] [expires: 2020-11-15]
Note: A ">" after these tags(sec,ssb,pub,sub) indicate that the key is stored on a smartcard/Yubikey.
And if your curious on what the tag meanings are:
sec => 'SECret key'
ssb => 'Secret SuBkey'
pub => 'PUBlic key'
sub => 'public SUBkey'
NOTE: after you're done setting up your Yubikey, you should restore the backup so your keys are restored on your USB drive.
After you have restored your backup, you can eject your USB drive, and store it in a secure location!
Setup your workstation...
export KEYID=0x585C80B653416059
export KEYSERVER=keyserver.ubuntu.com
bash <(curl -s https://gist.githubusercontent.com/DoctorOgg/d1b6a25108968b890b959e8bee7ee366/raw/2a53aa970e661fc6f26385deb3b9a7397888c96a/setupgpg.sh)
Dr. Ogg