This document is a WORK IN PROGRESS.
This is just a quick personal cheat sheet: treat its contents with caution!
GNU Privacy Guard (GnuPG/GPG)¶
-
Pretty Good Privacy (PGP)
Pretty Good Privacy is proprietary software that provides cryptographic privacy and authentication for data communication. PGP is used for signing, encrypting, and decrypting texts, e-mails, files, directories, whole disk partitions and to increase the security of e-mail communications.
It was originally written by Phil Zimmerman in 1991. After several changes of hands, it’s now owed by Symantec Corp. They also own the registered trademark for "PGP", "Pretty Good" and "Pretty Good Privacy".
-
OpenPGP
After PGP took off in popularity, others wanted to write software that was compatible with the PGP format.
In 1997, PGP Inc proposed to the IETF a standard called OpenPGP and allowed various uses of the name "OpenPGP". This was accepted and the IETF formed the OpenPGP Working Group.
The OpenPGP protocol is currently formalized in the obsolete RFC 2440 and new RFC 4880.
-
GNU Privacy Guard (GnuPG/GPG)
GNU Privacy Guard, also known as GnuPG and GPG, is the Free Software Foundation’s implementation of the OpenPGP protocol (written almost entirely by Werner Koch).
Like PGP, it provides cryptographic privacy and authentication for data communication (signing, encrypting, decrypting, etc).
Reference(s)
- https://web.archive.org/web/20211107011848/https://www.gnupg.org/gph/en/manual.html
- https://web.archive.org/save/https://wiki.debian.org/Subkeys
- https://www.howtogeek.com/427982/how-to-encrypt-and-decrypt-files-with-gpg-on-linux/
- https://wiki.gentoo.org/wiki/GnuPG
- https://wiki.archlinux.org/index.php/GnuPG
- https://www.openpgp.org/
- https://keys.openpgp.org/
- https://en.wikipedia.org/wiki/Public-key_cryptography
- https://web.archive.org/web/20220106091620/https://paul.fawkesley.com/difference-between-gpg-pgp-and-openpgp/
- https://web.archive.org/web/20220106091742/https://paul.fawkesley.com/gpg-for-humans-why-care-about-cryptography/
- https://web.archive.org/web/20220106091820/https://paul.fawkesley.com/gpg-for-humans-public-key-crypto-primer/
- https://web.archive.org/web/20220106091905/https://paul.fawkesley.com/gpg-for-humans-protecting-your-primary-key/
- https://web.archive.org/web/20220106091931/https://paul.fawkesley.com/gpg-for-humans-preparing-an-offline-machine/
- https://web.archive.org/web/20220106095043/https://davesteele.github.io/gpg/2014/09/20/anatomy-of-a-gpg-key/
- https://web.archive.org/web/20211216165032/https://zeroindexed.com/pgp-encryption-subkeys
Table of contents¶
Introduction¶
Keypair capabilities¶
GPG relies on the idea of asymmetric keypair: a private/secret key associated with a public key. They are called asymmetric, because they have different capabilities.
-
Private/secret key capabilities:
- Decrypt something that have been encrypted with the associated public key only.
- Sign something to prove other people its integrity (i.e what you signed has not been altered/tampered in any way) and to prove other people your identity (i.e. what you signed has been signed by you and no one else).
- Certify a trusted public key, one of yours or someone else's. Certifying a public key is actually signing it, but certification is a specific signing mechanism only applied to public keys.
- Authenticate to something, e.g. log into a machine via SSH. Authenticating is actually a signing challenge, but authentication is a specific signing mechanism only applied to that challenge.
-
Public key capabilities:
- Encrypt things that can only be decrypted with the associated private/secret key.
- Verify things that have been signed by the associated private/secret key only.
Note
When creating a keypair, you can choose to enable or disable some capabilities:
- The Signing (S) capability (so the verify capability with it, because a public key has nothing to verify if its associated private/secret key cannot sign anything).
- The Encryption (E) capability (so the decryption capability with it, because a private/secret key has nothing to decrypt if its associated public key cannot encrypt anything).
- The Authentication (A) capability (independently from the signing capability).
Also note that a primary keypair always has the certification (C) capability, while sub keypairs cannot have that capability. This means that only the primary keypair can create sub keypairs and certify/revoke them.
More about primary and sub keypairs in a following section.
Example¶
Alice wants to share a secret message to Bob, in order to do so here are the steps follow:
-
Alice will have to sign the message with her private/secret key, this way she will prove to Bob that the message comes from her and no one else and she will also prove that the message has not been altered/tempered in any way (the message has kept its integrity).
-
Now Alice will have to encrypt the message with Bob's public key, this way she will prove to Bob that only him can read the content of the message.
-
At this point Alice can transmit the encrypted message to Bob by any means, even publicly.
-
After receiving it, Bob will decrypt the message with his private/secret key and verify Alice's signature with her public key. If no private/secret key has been compromised, then he can reasonably think that the message has been kept secret.
Public vs private/secret¶
It is clear, from the previous example, that public keys must be shared. You need to have the public key of the recipient in order to encrypt the file, and the recipient needs your public key to verify it. There is no danger in making your public keys just that—public. In fact, there are public key servers for that very purpose, as we shall see in the key servers section.
Warning
It’s very important to properly verify that a public key belongs to who you think it does. There is absolutely nothing to stop someone from creating a keypair using someone else’s email address and pretend it really belongs to that person. We will go into more details about this subject in the key verification section - for now, suffice to say that public keys have fingerprints which must be carefully verified, preferably in person.
Warning
Good key management is crucial in order to ensure not just the integrity of your keyrings but the integrity of other users' keyrings as well. The core of key management in GnuPG is the notion of signing keys. Key signing has two main purposes: it permits you to detect tampering on your keyring, and it allows you to certify that a key truly belongs to the person named by a user ID on the key. Key signatures are also used in a scheme known as "the web of trust" to extend certification to keys not directly signed by you but signed by others you trust. Responsible users who practice good key management can defeat key tampering as a practical attack on secure communication with GnuPG.
In contrast, the private/secret key must be kept... very private and very secret. If your public key can be online in the public domain, then your private/secret key must be kept secure (ideally offline, on a removable and write-protected media, in a very safe place). The whole security of GPG relies on making sure your private/secret key can’t be used by anyone else. In an Internet-connected world, this can be really tough. Moreover, your public key will build up its reputation over the year (after being signed by trusted people), so it can be really annoying to revoke your keypair. Ideally you would like to keep the same keypair for years, if not decades. How to keep your private key secure and hidden for so long (especially if you have to use it on a daily basis)?
GPG offers us a solution. It is possible to split off your "primary" key and keeping it really safe, then using "sub" keys for every-day use.
Primary keypair and sub keypairs¶
When you create a new GPG keypair then you will always create a primary keypair, you can also create/add an associated sub (subordinate) keypair, which is the case by default.
Tip
The primary and sub keypairs are bundled to facilitate key management and the bundle can often be considered simply as one keypair.
The problem is:
-
The primary key is too powerful, because it always has the certification (C) capability (while sub keypairs cannot have that capability, this means that only the primary keypair can create sub keypairs and certify or revoke). If someone steals your primary key, the certification capability allows to certify other people’s keys, and the primary key can even generate new sub keypair and revoke your sub keypair - totally stealing your identity!
-
In other words: your primary keypair is your identity! If the private/secret key is compromised, you will need to revoke it and create a new key (which can be really annoying, like said before, because your public key might build up a reputation over the year after being signed by trusted people).
The solution is:
-
Create a primary keypair with the least capabilities possible (so just the certification capability).
-
Create an associated sub keypair with the other capabilities needed.
-
Move the private/secret key of your primary keypair somewhere secure (ideally offline, on a removable and write-protected media, in a very safe place).
-
... (TODO)
Because subordinate keypairs cannot have the certification (C) capability, if a sub keypair is compromised, then you can simply primary keypair can create sub keypairs and certify or revoke
Difference between revocation and deletion
TODO
One sub keypair per machine vs. one single sub keypair for all machines
One might be tempted to have one sub keypair per machine so that you only need to exchange the potentially compromised sub keypair of that machine. In case of a single sub keypair used on all machines, it needs to be exchanged on all machines in case of a compromising.
But, if you have multiple encryption sub keypairs, GPG is said to encrypt only for the most recent encryption sub keypair, and not for all known and not revoked encryption sub keypairs.
TODO:
-
Try to Sign with private/secret primary key (that has only C capability) and to Verify with public sub key (that has S capability): this should not be possible.
-
Try to Sign with private/secret primary key (that has SC capability) and to Verify with public sub key (that has S capability): this should be possible.
-
Try to Sign with private/secret primary key (that has SC capability) and to Verify with public sub key (that has no S capability): this shouldn't be possible.
-
Try to Encrypt with public primary key (that has only C capability) and to Decrypt with private/secret sub key (that has E capability): this should be possible.
-
Try to Encrypt with public primary key (that has only C capability) and to Decrypt with private/secret sub key (that has no E capability): this should not be possible.
-
Create multiple sub key pairs just with the E capability: is only the last private/secret keypair capable of decrypting something encrypted with the primary public key?
-
Create multiple sub key pairs just with the S capability: is only the last public keypair capable of verifying something signed with the primary private/secret key?
Avoid dotfile madness¶
Prior to installation, make sure you stay in control of your home directory.
Prerequisite(s)
See how to handle GnuPG related dotfiles.
Install¶
GnuPG should be installed by default, if not:
Config¶
TODO
WIP
If you need to set the default key more permanently then edit the file ~/.gnupg/gpg.conf
and set
the default-key
parameter.
Tip
Note that Test User <tu@test.user>
is the <USER-ID>
of the key that we just created!
Use¶
Setup your keys¶
Primary keypair creation¶
Create a key, using the $ gpg --full-generate-key --expert
command. The first time it is run, it
will create some directories essential to the correct operation and implementation of GnuPG. You
might have to run it again in order to create your keys:
$ gpg --full-generate-key --expert
> gpg (GnuPG) 2.2.32; Copyright (C) 2021 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
> (14) Existing key from card
> 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 # (disable sign capability, which was toggle by default)
>
> 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 (disable encrypt capability, which was toggle by default)
>
> 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? 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: Stéphane Tzvetkov
> Email address: st@stephane.plus
> Comment:
> You are using the 'utf-8' character set.
> You selected this USER-ID:
> "Test User <tu@test.user>"
>
> 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 4B6F2675F6D24EFA marked as ultimately trusted
> gpg: revocation certificate stored as '/home/user/.config/gnupg/openpgp-revocs.d/4E54F7D32D247BB5A32AEE622A8F3875F6D42EFA.rev'
> public and secret key created and signed.
>
> pub rsa4096 1970-01-01 [C]
> 8E54F7D38A427AA7A62AEE624B6F2675F6D24EFA
> uid Test User <tu@test.user>
Tip
Note that Test User <tu@test.user>
is the <USER-ID>
of the key that we just created!
Sub keypair creation¶
Your primary key is your online identity, and your identity and reputation are built up by having other people vouch for that key being yours by signing it themselves. So, since your primary key is very important and is built up over years, you want to protect it very much. In particular, you do not want to store it on a computer that might get stolen or hacked into; you want to keep your primary key off-line in a safe place.
This, of course, makes your primary key very inconvenient to use. So for day-to-day operations you want to use a key that is not such a big problem to replace if it gets compromised. This is why sub keypairs were invented.
A sub keypair is still a public/private keypair and is secure as long as only you have the private key. It is, cryptographically, just as secure as your primary key. The difference is that your reputation is only attached to it by your own signature, the signature from your private key. To use the Twitter analogy, the world trusts that you are your Twitter handle because all your followers say so (I know, it doesn't always really work that way, but analogies are hard!), and then with that trust established you can then much more easily convince the world you own your Instagram handle by just tweeting it and people will believe you because the tweet came from your account, which they trust.
You still want to keep your sub keypair safe, but now if it is compromised it is not the huge problem it would be if your primary key were compromised (or, in the analogy, someone hijacked your Twitter account). Now you can just revoke the sub keypair and issue a new one by signing a revocation certificate and a new sub keypair and posting them both on your public keyring (like tweeting "hey, my Instagram handle changed, don't use the old one, use this one instead"). This makes keeping your sub keypair on your laptop computer a more acceptable risk than keeping your primary key on it.
TL;DR Sub keypairs make key management much easier by separating the cryptographic functions of public keys from the trust and identity functions of (primary) public keys.
WIP
$ gpg --expert --edit-key "Test User <tu@test.user>"
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
> (14) Existing key from card
> 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? A # add Authenticate capabilities, because sign and encrypt capabilities are already enabled by default
>
> Possible actions for a RSA key: Sign Encrypt Authenticate
> Current allowed actions: Sign Encrypt 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? (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
> Enter passphrase: # Input the passphrase of the previous 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.
>
> sec rsa4096/4B6F2675F6D24EFA
> created: 1970-01-01 expires: never usage: C
> trust: ultimate validity: ultimate
> ssb rsa4096/D663DA438B1DEFBC
> created: 1970-01-01 expires: never usage: SEA
> [ultimate] (1). User Test <tu@user.test>
gpg> save # save and exit
Backup keypairs and remove the primary keypair¶
-
Export the private/secret primary key:
-
Export all the private/secret sub keys:
-
Save
master-secret-key.gpg
andsub-secret-keys.gpg
on a physical device. -
Delete the private/secret keys (you need to delete all the sub keypairs as well):
-
Enter the master password and confirm the deletion in the subsequent confirmation dialogs.
-
Restore the sub keypair:
-
Check the result:
$ gpg --list-secret-keys > > /Users/username/.gnupg/pubring.kbx > -------------------------------------------- > sec# rsa4096 2018-09-14 [C] [expires: 2020-09-13] > 5615F7C581E8450E34F9031703426E5D827D6A81 > uid [ultimate] User Name <username@mail.com> > ssb rsa4096 2018-09-14 [S] [expires: 2018-09-16] > ssb rsa4096 2018-09-14 [E] [expires: 2020-09-13] > ssb rsa4096 2018-09-14 [A] [expires: 2020-09-13]
The
#
after the primary key means that the key is not stored locally.
Key verification¶
TODO
Key servers¶
TODO
--refresh-keys
Request updates from a keyserver for keys that already exist on the local keyring. This
is useful for updating a key with the latest signatures, user IDs, etc. Calling this with
no arguments will refresh the entire keyring.
--search-keys names
Search the keyserver for the given names. Multiple names given here will be joined to‐
gether to create the search string for the keyserver. Note that keyservers search for
names in a different and simpler way than gpg does. The best choice is to use a mail ad‐
dress. Due to data privacy reasons keyservers may even not even allow searching by user
id or mail address and thus may only return results when being used with the --recv-key
command to search by key fingerprint or keyid.
--fetch-keys URIs
Retrieve keys located at the specified URIs. Note that different installations of GnuPG
may support different protocols (HTTP, FTP, LDAP, etc.). When using HTTPS the system
provided root certificates are used by this command.
GPG for SSH with gpg-agent¶
Reference(s)
Enable the gpg-agent
SSH support:
$ echo "enable-ssh-support" >> $GNUPGHOME/gpg-agent.conf
$ gpg-connect-agent reloadagent /bye # tell the GPG agent to reload its configuration
> OK
Set SSH_AUTH_SOCK
so that SSH will use gpg-agent
instead of ssh-agent
. Add this to tour shell
configuration file (i.e. $HOME/.bashrc
or $HOME/.zshrc
or whatever):
$ vi $HOME/.bashrc # or ${ZDOTDIR:-${HOME}}/.zshrc or wherever
> ...
+ >
+ > # GPG - SSH setup
+ > unset SSH_AGENT_PID
+ > if [ "${gnupg_SSH_AUTH_SOCK_by:-0}" -ne $$ ]; then
+ > export SSH_AUTH_SOCK="$(gpgconf --list-dirs agent-ssh-socket)"
+ > fi
+ > export GPG_TTY=$(tty)
+ > gpg-connect-agent updatestartuptty /bye >/dev/null
$ source $HOME/.bashrc # or ${ZDOTDIR:-${HOME}}/.zshrc or wherever
Get the keygrip
of the key you are interested in (e.g. Test User <tu@test.user>
):
$ gpg --list-keys --with-keygrip
> ...
> pub rsa4096 1970-01-01 [C]
> 8E54F7D38A427AA7A62AEE624B6F2675F6D24EFA
> Keygrip = 7A523F57E28EABF523145F101E70A10582884EAA
> uid [ultimate] Test User <tu@test.user>
> sub rsa4096 1970-01-01 [SEA]
> Keygrip = 3A5C6B0B8E2ABE26D7030814B816BB6A093A92FC
> ...
Now add the keygrip
of your sub key to the list of approved keys:
$ touch $GNUPGHOME/sshcontrol
$ echo 3A5C6B0B8E2ABE26D7030814B816BB6A093A92FC >> $GNUPGHOME/sshcontrol
Check if the key is present in the SSH identities list:
Retrieve the public SSH key for the sub keypair:
WIP
Reference(s)
- https://web.archive.org/web/20220105162802/https://gist.github.com/mcattarinussi/834fc4b641ff4572018d0c665e5a94d3
- https://wiki.archlinux.org/title/GnuPG#gpg-agent
- https://www.linode.com/docs/guides/gpg-key-for-ssh-authentication/
- https://www.esev.com/blog/post/2015-01-pgp-ssh-key-on-yubikey-neo/
- https://medium.com/@ahawkins/securing-my-digital-life-gpg-yubikey-ssh-on-macos-5f115cb01266
GPG for Git¶
Sign your Git commits with GPG
TODO
GPG for everyday use¶
WIP
-
TODO: check
$ man gpg
-
List a summary of all local keys:
-
List a summary of all local public keys:
-
List a summary of all local private/secret keys:
-
Delete a secret key from your local public key list:
-
Delete a public key from your local public key list:
-
Show your current default public key:
-
Show the fingerprint for a key:
-
Search for keys containing a specific string:
-
Encrypt a File:
-
Decrypt a File
-
Export keys
$ gpg --output ~/public_key.txt --armor --export <USER-ID> $ gpg --output ~/private_key.txt --armor --export-secret-key <USER-ID>
Store these files to a safe location, such as a USB drive, then remove the private key file (e.g. using
shred
): -
Import keys by retrieving the key files which you previously exported:
Then delete the private key file (if any), e.g. using
shred
: -
Revoke a key by creating a revocation certificate:
After creating the certificate import it:
Then ensure that key servers know about the revocation:
-
Sign a file (by creating an associated signature file, i.e. the
.asc
file):OR, if you need to specify a particular key:
This then produces a file with a
.asc
extension which can be uploaded. If you need to set the default-key more permanently then edit the file~/.gnupg/gpg.conf
and set the default-key parameter. -
Verify a signed file (with its associated signature file, i.e. the associated
.asc
file): -
Sign a public key (from/to a server):
-
Import the public key or retrieve it from a server:
-
Check its fingerprint against any previously stated value:
-
Sign the key:
-
Upload the signed key to a server:
-
-
Change the email address associated with a GPG key
Enter the new name and email address. You can then list the addresses with:
If you want to delete a previous email address first select it:
Then delete it with:
To finish type:
Publish the key to a server:
-
High-quality options for GPG for symmetric (secret key) encryption
This is what knowledgable people consider a good set of options for symmetric encryption with GPG to give you a high-quality result.
gpg \ --symmetric \ --cipher-algo aes256 \ --digest-algo sha512 \ --cert-digest-algo sha512 \ --compress-algo none -z 0 \ --s2k-mode 3 \ --s2k-digest-algo sha512 \ --s2k-count 65011712 \ --force-mdc \ --pinentry-mode loopback \ --armor \ --no-symkey-cache \ --output somefile.gpg \ filename # to encrypt
Troubleshooting¶
Inappropriate ioctl for device
error¶
If you encounter the Inappropriate ioctl for device
errors, like described
here.
Then do the following:
$ vi ${XDG_CONFIG_HOME:-${HOME/.config}}/gnupg/gpg.conf # create it if not present
> use-agent
> pinentry-mode loopback
$ vi ${XDG_CONFIG_HOME:-${HOME/.config}}/gnupg/gpg-agent.conf # create it if not present
> allow-loopback-pinentry
No pinentry
error¶
If you encounter the No pinentry
error, then follow the below steps.
- Change the default
pinentry-program
topinentry-tty
(for a CLI-only experience):
If you do not have
/usr/bin/pinentry-tty
, use/usr/bin/pinentry-curses
instead (for older systems).
- Then run again the
gpg
command causing the error, but with the--pinentry-mode ask
option!
If this cheat sheet has been useful to you, then please consider leaving a star here.