This guide is a compilation of four other guides. It instructs how to create a set of GnuPG keys which the master key is offline and the actual subkeys only live inside your YubiKey (acting as a smartcard). What ends up in your (online) daily machine are only the stubs of the subkeys.
$ sudo pacman -Syu gnupg pcsc-tools ccid libusb-compat hopenpgp-tools yubikey-personalization
Ideally these steps are performed on an offline machine. Consider creating a live ISO that already has the required packages plus these instructions. In case of creating the live ISO, tmux is also recommended so the steps can be performed in a split pane side by side with these instructions.
$ export GNUPGHOME=$(mktemp -d); echo $GNUPGHOME
/tmp/tmp.<some temp value>
Based on this recommended one.
$ cat << EOF > $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
s2k-cipher-algo AES256
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
EOF
$ gpg --full-generate-key
Values:
- Kind: 4 - RSA (sign only)
- Keysize: 4032 - arbitrary number to break the usual power of two key size (recommended here
- Expiration: 1yr
- Passphrase: use a strong one you already had in mind or run
shuf -n10 /usr/share/dict/cracklib-smallr
for generating random words from which you can pick to use as a passphrase. IMPORTANT: you have to memorize this.
$ KEYID=<id shown in the previous step>
$ gpg --edit-key $KEYID
gpg> addphoto
It needs to be stored in a safe place, separate from the Master key itself. It is to be used in case your offline Master key is compromised.
$ export VOLATILE=$(mktemp -d); echo $VOLATILE
/tmp/tmp.<some temp value>
$ gpg --gen-revoke $KEYID > $VOLATILE/<[email protected]>.gpg-revocation-certificate.txt
Values:
- Reason: 1
- Description: Generated during key creation, emergency use only.
IMPORTANT: Don't forget to print it or copy it to a safe place; remember
$VOLATILE
is currently located in memory and it will be lost after system
reboot.
This is the target folder for saving key exports.
$ mkdir -p $GNUPGHOME/exports
$ gpg --export-secret-keys --armor $KEYID > $GNUPGHOME/exports/<[email protected]>.gpg-secret-keys.txt
This is the target folder to which we will save snapshots of $GNUPGHOME
.
$ mkdir -p $VOLATILE/full-gnupghomes
$ cp -a $GNUPGHOME $VOLATILE/full-gnupghomes/master-only
These will go into the smartcard. They are not being generated directly into the smartcard for back-up purposes.
$ gpg --expert --edit-key $KEYID
gpg> addkey
Kind: 4 - RSA (sign only) Size: 4032 Expiration: 1y
gpg> addkey
Kind: 6 - RSA (encrypt only) Size: 4032 Expiration: 1y
gpg> addkey
Kind: 8 - RSA (set your own capabilities) Allowed actions: S, E, A, Q Size: 4032 Expiration: 1y
gpg> save
$ gpg --list-secret-keys
And make sure you see one sec
and three ssb
.
Then use automated key best practice checker
$ gpg --export $KEYID | hokey lint
Everything should be green.
$ gpg --export-secret-keys --armor $KEYID > $GNUPGHOME/exports/<[email protected]>.gpg-secret-keys.txt
$ gpg --export-secret-subkeys --armor $KEYID > $GNUPGHOME/exports/<[email protected]>.gpg-secret-subkeys.txt
$ cp -a $GNUPGHOME $VOLATILE/full-gnupghomes/master-and-subkeys
Make sure pcscd
and gpg-agent
services are running.
$ ykpersonalize -m82
You may have to remove and re-insert the YubiKey after this step.
Factory defaults are 123456
for normal user and 12345678
for admin user.
$ gpg --card-edit
gpg/card> admin
gpg/card> passwd
Then 3, 1, Q
gpg/card> name
Cardholder's surname: <and type in your surname>
Cardholder's given name: <and type in your name>
gpg/card> login
Login data (account name): <[email protected]>
gpg/card> (Press Enter)
(Review the information)
gpg/card> quit
$ gpg --edit-key $KEYID
gpg> toggle
gpg> key 1
gpg> keytocard
Your selection? 1
gpg> key 1
gpg> key 2
gpg> keytocard
Your selection? 2
gpg> key 2
gpg> key 3
gpg> keytocard
Your selection? 3
gpg> save
Verify that the keys were moved. Now they should be marked as ssd>
indicating
they are stubs for a smartcard key.
$ gpg --list-secret-keys
$ gpg --export-secret-keys --armor $KEYID > $GNUPGHOME/exports/<[email protected]>.gpg-secret-keys.txt
$ gpg --export-secret-subkeys --armor $KEYID > $GNUPGHOME/exports/<[email protected]>.gpg-secret-subkeys.txt
$ gpg --export --armor $KEYID > $GNUPGHOME/exports/<[email protected]>.gpg-public-key.txt
$ cp -a $GNUPGHOME $VOLATILE/full-gnupghomes/master-and-subkeys
$ sudo cryptsetup luksOpen /dev/sdXN vault
$ sudo mkdir /mnt/vault
$ sudo mount /dev/mapper/vault /mnt/vault
$ sudo mkdir /mnt/vault/gpg-backups
$ sudo cp -a $VOLATILE/full-gnupghomes/* /mnt/vault/gpg-backups/<youremail@yourdomain>
Beware of not copying the revoke certificate which we had placed inside
$VOLATILE
$ sudo umount /mnt/vault
$ sudo cryptsetup luksClose vault
If you were using an offline machine for doing the previous steps (RECOMMENDED),
just transfer the public key
$GNUPGHOME/volatile-backups/<[email protected]>.gpg-public-key.txt
to your daily machine using a different medium than the vault.
If you weren't using an offline machine (NOT RECOMMENDED), just copy the public
key from the volatile location to your home directory, then
securely remove the folder; finally unset the
GNUPGHOME
environment variable.
$ cp $GNUPGHOME/volatile-backups/<[email protected]>.gpg-public-key.txt ~
$ sudo pacman -Syu srm
$ srm -r $GNUPGHOME
$ unset GNUPGHOME
Create a configuration (for GnuPG > 2.1.x)
$ cat << EOF > ~/.gnupg/gpg.conf
auto-key-locate keyserver
keyserver hkps://hkps.pool.sks-keyservers.net
keyserver-options no-honor-keyserver-url
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-cipher-algo AES256
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
use-agent
require-cross-certification
EOF
Then import the public key
$ gpg --import < <[email protected]>.gpg-public-key.txt
Optionally upload it to a public keyserver (so it can be imported from other machines from the web)
$ gpg --send-key <[email protected]>
Insert the YubiKey and generate secret key stubs:
$ gpg --card-status
Now it should show the Master key as not available (sec#
).
$ gpg --list-secret-keys <[email protected]>
Mark the key as ultimately trusted
$ gpg --edit-key <[email protected]>
gpg> trust
Your decision? 5
gpg> quit