Trust the developers, not the code hosting infrastructure. ~Linux Kernel Maintainers PGP Guide
Why GPG?
“The distinction between what is public and what is private is becoming more and more blurred with the increasing intrusiveness of the media and advances in electronic technology. While this distinction is always the outcome of continuous cultural negotiation, it continues to be critical, for where nothing is private, democracy becomes impossible.” ~ Privacy Conference, Social Research, New School University
Too often these days with technology, insecurity lurks in the shadows of complexity. Getting back to primary tools is useful for reconnection to self and to freedom of expression. Quality of life is in direct correlation to the artifacts at our disposal.
Open Source GPG/GnuPG (Gnu Privacy Guard) and it’s proprietary pal PGP (Pretty Good Privacy) can be called upon to encrypt email, passwords, files, storage tombs, logical volumes and partitions. Moreover, GPG is required to sign git commits in collaborative work situations.
“I generally sign all of my mails because I believe it’s important. More than once it helped to prevent identity theft with people using a ‘similar’ email address to mine.” ~Anonymous
My primary motivation for setting up GPG is for use with Pass: The Standard Unix Password Manager
where each password or document is stored as an encrypted file. This guide will ensure that you are set up to encrypt, sign and authenticate with GPG.
Pass
is awesome for storage and retrieval of passwords and account details. You can also obfuscate the directory structure and filenames of the password store with pass-tomb. Beyond pass
, other password managers have their place, such as the Firefox ‘logins and passwords’ utility and bitwarden for syncing single-word passwords across web services.
Definition Of A Key
In public key cryptography, a key is actually a pair: a public key, and a private key. You use the private key to digitally sign files, and others use the public key to verify the signature. Or, others use the public key to encrypt something, for you to decrypt… subkeys can be revoked separately from master keys and also stored separately from them. Essentially, a separate key pair, but automatically associated with your main key pair. ~wiki.debian.org/Subkeys
GPG and 2FA
Two Factor Authentication provides that extra layer of security to login passwords, something the user has or is, not something the user knows. Typically this has meant a time-based one-time password (TOTP) via SMS, scanning a QR code, (better) app-based authentication (think Google Authenticator or Authy) or biometrics. However, SMS sends sensitive information over an unencrypted communications platform. Browser extensions and developer tools like webpack
have also been used as attack vectors for compromising QR codes and pin numbers entered on a webpage.
Technically these methods could be called two-step authentication, because the second factor is supplied via the same method as the first factor. For example, even though the second factor may be generated by a mobile-based app, that one-time code needs to be entered into the same login page on a web site along with user’s password — meaning both the password and the one-time code can still be subverted by phishing, man-in-the-middle and credential replay attacks. ~krebonsecurity
GPG used in conjunction with a physical cryptographic card and card reader or a USB device such as a Yubikey has gained traction in recent years. If using a physical key, you may register a couple of these low-cost devices with each site in case of loss. For a flexible open source project that has brought together best practices of 2FA and GPG, see privacyIDEA Authentication System available in Gnu/Linux software repositories.
Why Ed25519?
As of 2021, many smart-devices and web-services still only support the 2048 and 4096-bit RSA cyphers. Bloated and slow, RSA is not nearly as secure as Curve Ed22519 (an algorithm based on elliptic curves). The solution is to use the more efficient ECC cypher for generating the primary certification key (offline), and use that key to generate RSA subkeys for common encryption tasks.
Subkeys
GnuPG supports having multiple encryption subkeys on a keyring for the purpose of authentication, encryption and signing. If one algorithm is unsupported (e.g. the older GnuPG version 1.4 doesn’t support ECC), it can fall back to another subkey with a supported algorithm. The original key is secreted away on an encrypted volume, with a interminably long passphrase. The subkeys will subsequently be protected by a second easier-to-type passphrase for everyday use.
The master key is dusted off every once in a while to:
- alter the expiry dates of existing subkeys
- create other subkeys as needed
- possibly unencrypt a special file
- access your revocation certificate (in case of a compromised key).
Even though the master key is now safe from being leaked or stolen, the subkeys are still in your home directory. If the passphrase is discovered, the perpetrator could decrypt your communication or fake your signatures. It’s worth repeating though that any key is useless without the passphrase that protects it.
Formulating A Memorable, High-Entropy Passphrase
For creative ideas look to diceware or xkcdpass. Install xkcdpass and run the following command several times for inspiration. You’ll have fun!
$ xkcdpass --count=5 --acrostic='acronym'
Preliminaries
Make sure you’re using gpg v2
gpg2 --version | head -n1
and if you should happen to have both installed on your system
alias gpg=gpg2
Make backups of your existing GnuPG files ($HOME/.gnupg). Keep them safe. If something goes wrong during the following steps, you may need this to return to a known/good place.
umask 077; tar -cf $HOME/gnupg-backup.tar -C $HOME .gnupg
Note: umask 077 results in restrictive permissions for the backup.
Personally, I generated my keypair offline with Tails OS installed on a USB stick (See index below). This affords extra security features that some will consider nice to have. The master key need never be exposed to an internet-connected computer.
The Critical Path
- Create a master key to certify subkeys; one subkey per capability.
- Long expiry date for the master key; 50 years or your life expectancy.
- Short validity for subkey: 2-5 years to ensure that package signing, certificates and related processes stay up-to-date and don’t get stale (expiration date can be changed later).
- Generate a revocation certification, securely held in case a key becomes compromised.
- Move the private key and revocation certificate and make backups.
The Steps
Expand for details
amnesia@amnesia:~$ gpg --full-gen-key --expert
gpg (GnuPG) 2.2.12; 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.
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? 11
Possible actions for a ECDSA/EdDSA key: Sign Certify Authenticate
Current allowed actions: Sign Certify
(S) Toggle the sign capability
(A) Toggle the authenticate capability
(Q) Finished
Your selection? s
Possible actions for a ECDSA/EdDSA key: Sign Certify Authenticate
Current allowed actions: Certify
(S) Toggle the sign capability
(A) Toggle the authenticate capability
(Q) Finished
Your selection? q
Please select which elliptic curve you want:
(1) Curve 25519
(3) NIST P-256
(4) NIST P-384
(5) NIST P-521
(6) Brainpool P-256
(7) Brainpool P-384
(8) Brainpool P-512
(9) secp256k1
Your selection? 1
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) 50y
Key expires at Tue 15 Apr 2070 0429 AM UTC
Is this correct? (y/N) y
GnuPG needs to construct a user ID to identify your key.
Real name: John Smith
Email address: jsmith@kmail.com
Comment:
You selected this USER-ID:
"John Smith <jsmith@kmail.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: key 0xC0A36B17811FFED4 marked as ultimately trusted
gpg: revocation certificate stored as '/home/amnesia/.gnupg/openpgp-revocs.d/C5246A0ADE20E283A90E382CC0A36B17811FFED4.rev'
public and secret key created and signed.
pub ed25519/0xC0A36B17811FFED4 2020-04-27 [C] [expires: 2070-04-15]
Key fingerprint = C524 6A0A DE20 E283 A90E 382C C0A3 6B17 811F FED4
uid John Smith <jsmith@kmail.com>
amnesia@amnesia:~$ gpg --expert --edit-key 0xC0A36B17811FFED4
gpg (GnuPG) 2.2.12; 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: 2 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 2u
gpg: next trustdb check due at 2025-04-12
sec ed25519/0xC0A36B17811FFED4
created: 2020-04-27 expires: 2070-04-15 usage: C
trust: ultimate validity: ultimate
[ultimate] (1). John Smith <jsmith@kmail.com>
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? 11
Possible actions for a ECDSA/EdDSA key: Sign Authenticate
Current allowed actions: Sign
(S) Toggle the sign capability
(A) Toggle the authenticate capability
(Q) Finished
Your selection? q
Please select which elliptic curve you want:
(1) Curve 25519
(3) NIST P-256
(4) NIST P-384
(5) NIST P-521
(6) Brainpool P-256
(7) Brainpool P-384
(8) Brainpool P-512
(9) secp256k1
Your selection? 1
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) 3y
Key expires at Thu 27 Apr 2023 0438 AM UTC
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 ed25519/0xC0A36B17811FFED4
created: 2020-04-27 expires: 2070-04-15 usage: C
trust: ultimate validity: ultimate
ssb rsa4096/0x28C194EDFDB41226
created: 2020-04-27 expires: 2023-04-27 usage: E
ssb ed25519/0xDB4C9A99430E61E6
created: 2020-04-27 expires: 2023-04-27 usage: S
[ultimate] (1). John Smith <jsmith@kmail.com>
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? 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? 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) 3y
Key expires at Thu 27 Apr 2023 0406 AM UTC
Is this correct? (y/N) y
Really create? (y/N) y
[master passphrase requested]
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 ed25519/0xC0A36B17811FFED4
created: 2020-04-27 expires: 2070-04-15 usage: C
trust: ultimate validity: ultimate
ssb rsa4096/0x28C194EDFDB41226
created: 2020-04-27 expires: 2023-04-27 usage: E
[ultimate] (1). John Smith <jsmith@kmail.com>
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? 11
Possible actions for a ECDSA/EdDSA key: Sign Authenticate
Current allowed actions: Sign
(S) Toggle the sign capability
(A) Toggle the authenticate capability
(Q) Finished
Your selection? s
Possible actions for a ECDSA/EdDSA key: Sign Authenticate
Current allowed actions:
(S) Toggle the sign capability
(A) Toggle the authenticate capability
(Q) Finished
Your selection? a
Possible actions for a ECDSA/EdDSA key: Sign Authenticate
Current allowed actions: Authenticate
(S) Toggle the sign capability
(A) Toggle the authenticate capability
(Q) Finished
Your selection? q
Please select which elliptic curve you want:
(1) Curve 25519
(3) NIST P-256
(4) NIST P-384
(5) NIST P-521
(6) Brainpool P-256
(7) Brainpool P-384
(8) Brainpool P-512
(9) secp256k1
Your selection? 1
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) 3y
Key expires at Thu 27 Apr 2023 0527 AM UTC
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 ed25519/0xC0A36B17811FFED4
created: 2020-04-27 expires: 2070-04-15 usage: C
trust: ultimate validity: ultimate
ssb rsa4096/0x28C194EDFDB41226
created: 2020-04-27 expires: 2023-04-27 usage: E
ssb ed25519/0xDB4C9A99430E61E6
created: 2020-04-27 expires: 2023-04-27 usage: S
ssb ed25519/0xCE658A723ED3DA27
created: 2020-04-27 expires: 2023-04-27 usage: A
[ultimate] (1). John Smith <jsmith@kmail.com>
gpg> save
amnesia@amnesia:~$ gpg --output GPG-0xC0A36B17811FFED4.asc --gen-revoke 0xC0A36B17811FFED4
sec ed25519/0xC0A36B17811FFED4 2020-04-27 John Smith <jsmith@kmail.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? 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!
Password Protect Secret Key
If you followed the steps, you are ready to encrypt the private/master key. Run the following command:
$ gpg2 --export-secret-key "your@email-address" -a | gpg2 --cipher-algorithm=AES128 --output secret-key.gpg -a --symmetric
You’ll get prompted for a passphrase and then secret-key.gpg will be created. This will export all necessary information to restore the secrets keys including the trust database information to secret-key.gpg. This is an additional step, in fact you could just backup the $HOME/.gnupg directory to a couple of encrypted tombs, USBs or partitions.
Optional: Store On Paper
For the ultimate archivist, there’s paperkey It reduces the size of the file by just crunching the secret part.
I’m personally wary of placing my master key next or near to a network printer, even if it’s been encrypted. ¯\(-,-)/¯
Find the fingerprint of your key by doing:
$ gpg -K --with-keygrip
To make a paperkey backup, run the following command, replacing [fpr] with the full fingerprint of your key:
$ gpg2 --export-secret-key [fpr] | paperkey -o /tmp/key-backup.txt
Make Backups
Backup your secret-key.gpg and revocation certificate
(GPG-0xC0A36B17811FFED4.asc in the above example)
In fact, just backup ~/.gnupg
. You will have to delete these two files local working ~/.gnupg
directory.
Set up a LUKS-encrypted volume or two where you can store backups. I used gnome-disks
(conveniently packaged with Tails). Also look at tomb as an alternative safe storage method.
Remove Secret Key Keygrip
Obtain YOURMASTERKEYID by running
$ gpg -K --with-keygrip
The first line will resemble:
sec ed25519/0xC0A36B17811FFED4 2021-03-13 [SC] [expires: 2065-04-12]
Key fingerprint = 8F66 5A48 FC76 847E CCA5 9AAC 2FED 88C2 B6E3 04C5
In the above example YOURMASTERKEYID is C0A36B17811FFED4 (extracted from `sec ed25519/0xC0A36B17811FFED4 …)
The KEYGRIPS are identified by running:
$ gpg --with-keygrip --list-key YOURMASTERKEYID
Remove the relevant keygrip in $HOME/.gnupg/private-keys-v1.d/KEYGRIP.key
for master and that of the revocation certificate if it exists.
You’ll know the master/secret key material is gone, if when you run:
$ gpg2 --list-secret-keys
The legend at the left of your master key will show sec#
instead of sec
if you have followed the steps correctly.
Create A Shorter Passphrase For The Subkeys
Once the secret has been removed, run:
$ gpg2 --edit-key YOURMASTERKEYID passwd
If your everyday passphrase is compromised you can revoke and recreate another set of subkeys; the private master remains protected by the original passphrase.
Existing Security Vulnerabilities
Each time a GnuPG operation is performed, the keys are loaded into system memory and can be stolen from there by sufficiently advanced malware (think Meltdown and Spectre). Even if stored on a LUKS encrypted disk, while the password-encrypted volume is unlocked and mounted, the operating system is able to access the private key contents. For the uber paranoid, configure systemd-homedit to encrypt your /home partition (even on suspend) and/or let it handle your LUKS headers with access tied to a YubiKey or similar physical device.
Export Public Key
This command will export an ascii-armored version of the public key to a file you can share with others online and upload to git
servers such as Github, Gitlab, Gitea, or (decentralized) Radicle:
$ gpg2 --output public.pgp --armor --export username@email
Mount Key From Backup
When you need to use the master keys, mount the encrypted USB drive, and set the GNUPGHOME environment variable:
export GNUPGHOME=/media/something
$ gpg2 -K
or use the –homedir command-line argument:
$ gpg2 --homedir=/media/something -K
The latter command should now list your private key with sec and not sec#.
Add Relevant Identities
If you have multiple relevant email addresses (personal, work, open-source project, etc), you can add them to your master key. You don’t need to do this for any addresses that you don’t expect to use with PGP. The command is (put the full key fingerprint instead of [fpr]):
$ gpg2 --quick-add-uid [fpr] 'Bob Builder <bobb@example.net>'
You can review the UIDs you’ve already added using:
$ gpg2 --list-key [fpr] | grep ^uid
Pick the primary UID
GnuPG will make the latest UID you add as your primary UID, so if that is different from what you want, you should fix it back:
$ gpg2 --quick-set-primary-uid [fpr] 'Bob Builder <bobb@example.org>'
Optional: Publish Public Key To Keyserver
Many people choose to share their public key on a key-server. Your key is then discoverable by peers, helps to build a solid reputation and your work can be authenticated as your own. You still have to be mindful. The key is there in perpetuity and what checks are there that it was placed there by the owner? This version of your key can be emailed to friends and colleagues:
$ gpg2 --keyserver hkp://pool.sks-keyservers.net --send-key YOURMASTERKEYID
Some people recommend keybase.io for distribution. However, that method tracks participation in various social and technical communities which may not be desirable for some use cases. For maximum flexibility, you can place your public key on a website that you control to be discoverable by peers and co-workers. The technically adept could try out the webkey discovery service.
Optional: Keyserver Cron Job
If you use a keyserver, you may want to set up a cron job to keep up-to-date with your co-workers keys. To generate the public key output suitable to paste in, just run:
$ gpg2 --export --armor [fpr]
Set up a refresh cronjob You will need to regularly refresh your keyring in order to get the latest changes on other people’s public keys. You can set up a cronjob to do that:
$ crontab -e
Add the following on a new line:
@daily /usr/bin/gpg2 --refresh >/dev/null 2>&1
Index
A Operating System on a USB thumb drive means you can carry your own computing environment to any computer at school, work or at the Library and doesn’t affect the host system in any way. Many portable Linux distributions can run within the ram of the host machine, only writing back files you want saved to the USB stick. There are several specialized distros; Sparky, Crunchbang++ or Linux Lite for example. Tails is a distro with an emphasis on security. Installing it, while slightly more involved, is very straightforward due to excellent documentation. Once installed, to boot from a USB, change the boot order in the host machine’s BIOS to boot from the USB whenever it is plugged in. As the computer boots up and with the USB plugged in, press either <ESC>, <F2> or <F12> to enter the BIOS settings. Find the boot options in the menu and drag your USB to the top of the list. <F10> to save your preferences and exit.
Resources
https://phab.enlightenment.org/w/gnupg/
https://github.com/lfit/itpol/blob/master/protecting-code-integrity.md.
https://unix.stackexchange.com/questions/481939/how-to-export-a-gpg-private-key-and-public-key-to-a-file