Use the method described here if you would like most of the following benefits:
- Establish provenance of exactly one public key on the Internet over time (years typically).
- Use multiple keys daily without exposing the secret key corresponding to your published public key.
- Facilitate key creation and revocation.
While provenance isn't necessary for many folks, it's useful if not essential if you publish software artifacts on the Internet or issue public statements like security announcements. You establish provenance by accumulating digital signatures on your published key by other keys that are perceived to be trusted. By keeping your public key offline for daily use, you limit exposure of the key that certifies the keys you use for day-to-day use. If a subkey is lost or compromised, you simply revoke it and issue a new one that is published under your public key; there is no impact to the public key on which you have painstakingly accumulated trust.
The Debian Wiki has more to say on the benefits of using multiple subkeys for daily use.
- Establish a secure computing environment in which to generate and manage keys. While the details of this step are out of scope, it's vitally important for adequate security. How secure is secure depends on your needs and capabilities.
- Establish a removable, encrypted storage device to hold your GPG private keyring containing all active keys. After initial creation of a master key and subkeys, the volume should be taken offline and held in a secure location. It should be mounted only to create new subkeys and revoke old subkeys. Ideally all key management operations should be performed in the secure computing environment established in step 1.
- Export signing and encryption keys to one or more smart cards for secure and convenient day-to-day usage.
The premise of this exercise is to create keys that are secure for years, so it merits some planning and attention to detail. The most important aspects to consider:
- Setting up a secure computing environment in which to perform key management. Ideally this environment would be available not only for initial key generation but for subsequent subkey management operations (creation, revocation) in the future.
- Managing an encrypted removable storage device for the long term.
I'll simply state what worked for my needs in those areas. I had old MacBook lying around that I reinitialized and got
patched, then I downloaded Kali Linux, a security-oriented distribution. I obtained a security-oriented encrypted flash
drive (Aegis Secure Key) and followed the Kali documentation for creating a bootable USB drive. Once I could boot into
Kali from the flash drive, I leveraged the persistent volume feature of Kali to persist my home directory to a second
volume on the flash drive. While it was a lot of work to set all that up, I can say in retrospect that it was
worthwhile. Now I can just boot into Kali from the flash drive and my home directory naturally contains my .gnupg
folder containing my public and private keyrings.
It's worth noting that the Aegis Secure Key has a hardware crypto engine and requires an 8-digit PIN to mount, so the details of encryption are all opaque to me. It's an expensive device, but has proven trustworthy over several years of use and I appreciate that I don't have handle the cryptographic details to use it. A cheaper alternative would be to layer an encrypted filesystem on top of an ext4 filesystem on a regular flash drive. Whatever you use, it's worth spending some time and money on durable and reliable hardware. Remember, this thing will need to last for ten years or more, which is an eternity for a computer hardware device.
The following shell session provides a soup-to-nuts process for generating a certificate key and subkeys that are exported to a smart card for daily use. The process assumes you are working in your secure computing environment with the home directory mounted on the encrypted flash drive. Comments are provided in hash boxes to delineate steps and important notes.
root@kali:~# rm -fR .gnupg
#################################################
# Generate a certification key
#################################################
root@kali:~# gpg --expert --full-gen-key
gpg (GnuPG) 2.2.5; Copyright (C) 2018 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: directory '/root/.gnupg' created
gpg: keybox '/root/.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? s
Possible actions for a RSA key: Sign Certify Encrypt Authenticate
Current allowed actions: 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: 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? (3072) 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)
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: Marvin S. Addison
Email address: [email protected]
Comment:
You selected this USER-ID:
"Marvin S. Addison <[email protected]>"
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: /root/.gnupg/trustdb.gpg: trustdb created
gpg: key 9A1331FCCF8BA2CA marked as ultimately trusted
gpg: directory '/root/.gnupg/openpgp-revocs.d' created
gpg: revocation certificate stored as '/root/.gnupg/openpgp-revocs.d/5C5B8648E408DE13091A163F9A1331FCCF8BA2CA.rev'
public and secret key created and signed.
pub rsa4096 2018-06-08 [C]
5C5B8648E408DE13091A163F9A1331FCCF8BA2CA
uid Marvin S. Addison <[email protected]>
root@kali:~# gpg --expert --edit-key 5C5B8648E408DE13091A163F9A1331FCCF8BA2CA
gpg (GnuPG) 2.2.5; Copyright (C) 2018 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.
gpg: checking the trustdb
gpg: marginals needed: 3 completes needed: 1 trust model: pgp
gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u
sec rsa4096/9A1331FCCF8BA2CA
created: 2018-06-08 expires: never usage: C
trust: ultimate validity: ultimate
[ultimate] (1). Marvin S. Addison <[email protected]>
#################################################
# Attach additional identities as needed
#################################################
gpg> adduid
Real name: Marvin S. Addison
Email address: [email protected]
Comment:
You selected this USER-ID:
"Marvin S. Addison <[email protected]>"
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
sec rsa4096/9A1331FCCF8BA2CA
created: 2018-06-08 expires: never usage: C
trust: ultimate validity: ultimate
[ultimate] (1) Marvin S. Addison <[email protected]>
[ unknown] (2). Marvin S. Addison <[email protected]>
#################################################
# Set all identities to ultimate trust
#################################################
gpg> trust
sec rsa4096/9A1331FCCF8BA2CA
created: 2018-06-08 expires: never usage: C
trust: ultimate validity: ultimate
[ultimate] (1) Marvin S. Addison <[email protected]>
[ unknown] (2). Marvin S. Addison <[email protected]>
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
sec rsa4096/9A1331FCCF8BA2CA
created: 2018-06-08 expires: never usage: C
trust: ultimate validity: ultimate
[ultimate] (1) Marvin S. Addison <[email protected]>
[ unknown] (2). Marvin S. Addison <[email protected]>
gpg> q
Save changes? (y/N) y
root@kali:~# gpg --expert --edit-key 5C5B8648E408DE13091A163F9A1331FCCF8BA2CA
gpg (GnuPG) 2.2.5; Copyright (C) 2018 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.
gpg: checking the trustdb
gpg: marginals needed: 3 completes needed: 1 trust model: pgp
gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u
sec rsa4096/9A1331FCCF8BA2CA
created: 2018-06-08 expires: never usage: C
trust: ultimate validity: ultimate
[ultimate] (1). Marvin S. Addison <[email protected]>
[ultimate] (2) Marvin S. Addison <[email protected]>
gpg> uid 2
sec rsa4096/9A1331FCCF8BA2CA
created: 2018-06-08 expires: never usage: C
trust: ultimate validity: ultimate
[ultimate] (1). Marvin S. Addison <[email protected]>
[ultimate] (2)* Marvin S. Addison <[email protected]>
gpg> uid
sec rsa4096/9A1331FCCF8BA2CA
created: 2018-06-08 expires: never usage: C
trust: ultimate validity: ultimate
[ultimate] (1). Marvin S. Addison <[email protected]>
[ultimate] (2) Marvin S. Addison <[email protected]>
#################################################
# Generate a subkey for signing
#################################################
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? 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? e
Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions: Sign
(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? (3072) 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)
Key does not expire at all
Is this correct? (y/N)
Key is valid for? (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.
sec rsa4096/9A1331FCCF8BA2CA
created: 2018-06-08 expires: never usage: C
trust: ultimate validity: ultimate
ssb rsa4096/FE5DE05A039DDED9
created: 2018-06-08 expires: never usage: S
[ultimate] (1). Marvin S. Addison <[email protected]>
[ultimate] (2) Marvin S. Addison <[email protected]>
#################################################
# Generate a subkey for encryption
#################################################
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? (3072) 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)
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.
sec rsa4096/9A1331FCCF8BA2CA
created: 2018-06-08 expires: never usage: C
trust: ultimate validity: ultimate
ssb rsa4096/FE5DE05A039DDED9
created: 2018-06-08 expires: never usage: S
ssb rsa4096/337B85789C73123C
created: 2018-06-08 expires: never usage: E
[ultimate] (1). Marvin S. Addison <[email protected]>
[ultimate] (2) Marvin S. Addison <[email protected]>
gpg> quit
Save changes? (y/N) y
#################################################
# Make backups and revocation keys
#################################################
root@kali:~# export KEY=9A1331FCCF8BA2CA
root@kali:~# export BAK=~/.gnupg/backup
root@kali:~# mkdir $BAK
root@kali:~# gpg --output ~/.gnupg/backup/$KEY.revoke.asc --gen-revoke $KEY
sec rsa4096/9A1331FCCF8BA2CA 2018-06-08 Marvin S. Addison <[email protected]>
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? 0
Enter an optional description; end it with an empty line:
>
Reason for revocation: No reason specified
(No description given)
Is this okay? (y/N) y
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!
root@kali:~# gpg --armor --output $BAK/$KEY.privkey.asc --export-secret-key $KEYroot@kali:~# gpg --armor --output $BAK/$KEY.subkeys.asc --export-secret-subkeys $KEY
root@kali:~# gpg --armor --output $BAK/$KEY.pubkey.asc --export $KEY
root@kali:~# ls $BAK
9A1331FCCF8BA2CA.privkey.asc 9A1331FCCF8BA2CA.revoke.asc
9A1331FCCF8BA2CA.pubkey.asc 9A1331FCCF8BA2CA.subkeys.asc
root@kali:~# gpg --expert --edit-key 50B2D0FBB07958AE80F1E7ADFCEB20CC6F4C5AA3
gpg (GnuPG) 2.2.5; Copyright (C) 2018 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: key "50B2D0FBB07958AE80F1E7ADFCEB20CC6F4C5AA3" not found: No public key
#################################################
# Export subkeys to smartcard (i.e. YubiKey 4)
#################################################
root@kali:~# gpg --expert --edit-key $KEY
gpg (GnuPG) 2.2.5; Copyright (C) 2018 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/9A1331FCCF8BA2CA
created: 2018-06-08 expires: never usage: C
trust: ultimate validity: ultimate
ssb rsa4096/FE5DE05A039DDED9
created: 2018-06-08 expires: never usage: S
ssb rsa4096/337B85789C73123C
created: 2018-06-08 expires: never usage: E
[ultimate] (1). Marvin S. Addison <[email protected]>
[ultimate] (2) Marvin S. Addison <[email protected]>
gpg> key 1
sec rsa4096/9A1331FCCF8BA2CA
created: 2018-06-08 expires: never usage: C
trust: ultimate validity: ultimate
ssb* rsa4096/FE5DE05A039DDED9
created: 2018-06-08 expires: never usage: S
ssb rsa4096/337B85789C73123C
created: 2018-06-08 expires: never usage: E
[ultimate] (1). Marvin S. Addison <[email protected]>
[ultimate] (2) Marvin S. Addison <[email protected]>
gpg> keytocard
Please select where to store the key:
(1) Signature key
(3) Authentication key
Your selection? 1
gpg: WARNING: such a key has already been stored on the card!
Replace existing key? (y/N) y
sec rsa4096/9A1331FCCF8BA2CA
created: 2018-06-08 expires: never usage: C
trust: ultimate validity: ultimate
ssb* rsa4096/FE5DE05A039DDED9
created: 2018-06-08 expires: never usage: S
ssb rsa4096/337B85789C73123C
created: 2018-06-08 expires: never usage: E
[ultimate] (1). Marvin S. Addison <[email protected]>
[ultimate] (2) Marvin S. Addison <[email protected]>
gpg> key 2
sec rsa4096/9A1331FCCF8BA2CA
created: 2018-06-08 expires: never usage: C
trust: ultimate validity: ultimate
ssb* rsa4096/FE5DE05A039DDED9
created: 2018-06-08 expires: never usage: S
ssb* rsa4096/337B85789C73123C
created: 2018-06-08 expires: never usage: E
[ultimate] (1). Marvin S. Addison <[email protected]>
[ultimate] (2) Marvin S. Addison <[email protected]>
gpg> keytocard
You must select exactly one key.
gpg> key 1
sec rsa4096/9A1331FCCF8BA2CA
created: 2018-06-08 expires: never usage: C
trust: ultimate validity: ultimate
ssb rsa4096/FE5DE05A039DDED9
created: 2018-06-08 expires: never usage: S
ssb* rsa4096/337B85789C73123C
created: 2018-06-08 expires: never usage: E
[ultimate] (1). Marvin S. Addison <[email protected]>
[ultimate] (2) Marvin S. Addison <[email protected]>
gpg> keytocard
Please select where to store the key:
(2) Encryption key
Your selection? 2
gpg: WARNING: such a key has already been stored on the card!
Replace existing key? (y/N) y
sec rsa4096/9A1331FCCF8BA2CA
created: 2018-06-08 expires: never usage: C
trust: ultimate validity: ultimate
ssb rsa4096/FE5DE05A039DDED9
created: 2018-06-08 expires: never usage: S
ssb* rsa4096/337B85789C73123C
created: 2018-06-08 expires: never usage: E
[ultimate] (1). Marvin S. Addison <[email protected]>
[ultimate] (2) Marvin S. Addison <[email protected]>
gpg> key
sec rsa4096/9A1331FCCF8BA2CA
created: 2018-06-08 expires: never usage: C
trust: ultimate validity: ultimate
ssb rsa4096/FE5DE05A039DDED9
created: 2018-06-08 expires: never usage: S
ssb rsa4096/337B85789C73123C
created: 2018-06-08 expires: never usage: E
[ultimate] (1). Marvin S. Addison <[email protected]>
[ultimate] (2) Marvin S. Addison <[email protected]>
#################################################
# WARNING! WARNING! DANGER Will Robinson!
# DO NOT save changes or the secret part of your
# subkeys will be removed from your keyring
# and you will never, ever be able to recover
# them. This detail is key if you want to
# retain the capability to export subkeys to
# new cards in the future; for example, damage
# or loss.
#################################################
gpg> quit
Save changes? (y/N) N
Quit without saving? (y/N) y
#################################################
# Review the final status
#################################################
root@kali:~# gpg --card-status
Reader ...........: 1050:0407:X:0
Application ID ...: D2760001240102010006069235230000
Version ..........: 2.1
Manufacturer .....: Yubico
Serial number ....: 06923523
Name of cardholder: Marvin Addison
Language prefs ...: [not set]
Sex ..............: unspecified
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: not forced
Key attributes ...: rsa4096 rsa4096 rsa4096
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 15
Signature key ....: 7DF5 3B21 62E9 9705 3C64 4629 FE5D E05A 039D DED9
created ....: 2018-06-08 17:53:30
Encryption key....: B438 D3B6 790B B982 2398 5BA2 337B 8578 9C73 123C
created ....: 2018-06-08 17:54:28
Authentication key: 9A75 77B3 EAD5 3B70 AFC7 69D8 E901 CE63 B0F6 2848
created ....: 2018-03-03 12:08:52
General key info..: sub rsa4096/FE5DE05A039DDED9 2018-06-08 Marvin S. Addison <[email protected]>
sec rsa4096/9A1331FCCF8BA2CA created: 2018-06-08 expires: never
ssb rsa4096/FE5DE05A039DDED9 created: 2018-06-08 expires: never
ssb rsa4096/337B85789C73123C created: 2018-06-08 expires: never
root@kali:~# gpg --list-secret-keys --with-subkey-fingerprints
/root/.gnupg/pubring.kbx
------------------------
sec rsa4096 2018-06-08 [C]
5C5B8648E408DE13091A163F9A1331FCCF8BA2CA
uid [ultimate] Marvin S. Addison <[email protected]>
uid [ultimate] Marvin S. Addison <[email protected]>
ssb rsa4096 2018-06-08 [S]
7DF53B2162E997053C644629FE5DE05A039DDED9
ssb rsa4096 2018-06-08 [E]
B438D3B6790BB98223985BA2337B85789C73123C