How GPG works
While GPG is great software, it is said to be hard to use. For me, the hardest part is to sit down and get acquainted with the software. Actually, this is not a problem with GPG per se, but with all software. Let me give you an example: When you do not know vim, you will have a hard time editing text with vim. First, you have to get familiar with software before being able to use it. Usually, you would want to read (or at least skim) some kind of manual. And this is the problem with GPG: For me, the manual is similar to a beginner’s tutorial, since it misses quite a few things that should be discussed if you really want to use this software properly.
While writing the backup software bkup, I wanted to make use of GPG for encrypted backups for one particular reason: Asymmetric keys. This means that a key consists of two parts, a public and a private key. The private key is protected by a password and should be used by one person only. The public key is — as the name suggests — public, thus not protected by a password, and can be used by anybody. This is a nice property: For encrypting backups you only need to use the public key, so no password is necessary which means that the nightly backup can run unattended in a secure way; only for accessing the backups a password is needed as the private key will be used.
This page is basically a log of all the things I have learned while implementing bkup. It is not intended to be a GPG manual or tutorial, as there are already many out there. I am not even sure whether this page is of use to anybody except for me. So, if there are some things I glossed over, or did not explain too well, follow the links I have provided, and learn for yourself. It is a worthwhile endeavor!
Since we have already seen the merits of the GPG system, we want to get started. So, let’s create some keys. But wait… what keys? There are several to choose from.
Key creation: RSA, DSA, or ELG?
GPG supports three encryption schemes:
RSA is named after Ron Rivest, Adi Shamir and Leonard Adleman and was first published in 1977. It is one of the first asymmetric cryptosystems that has seen public use, and it is still considered a very hard problem to solve. It is based on the integer factorization problem.
DSA (Digital Signature Algorithm) is based upon a problem called discrete logarithm problem, just like ELG (see below). On the positive side, cryptographers believe (but could not show so far) that the discrete logarithm problem is much harder to solve than the integer factorization problem that forms the basis of RSA. On the other hand, RSA is around longer and thus has undergone more research, and is used in more products than any other cryptographic algorithm. DSA was originally designed to work with the SHA1 hashing algorithm only, but it was recently updated to work with other SHA specifications as well, up to SHA512. The maximum allowed key length was increased to 3072 bit, as well. This may result in backwards compatibility problems, depending on your use case and with whom you are going to share your keys with.
ELG (ElGamal, named after Taher Elgamal and published 1984) is a recent addition to GPG. It is also based on the discrete logarithm problem, just like DSA is. Thus, on a high-level perspective DSA and ELG seem to be very similar. However, in GPG a DSA key can only be used for signing, not for encryption. That is why usually you generate both a DSA and an ElGamal key: The DSA key is used for signing while the ElGamal part will be used for encryption.
While maintaining two separate keys — one key for signing and one for encryption — sounds like a lot of redundant work there is indeed merit in this approach: Mathematically, there is no difference between signing a message and decrypting a message. In both cases your private key will be used as an input to the same algorithm. Now, imagine a malicous user tricking another user into decrypting a message by asking him to sign it. One approach to mitigate this attack is that messages are never signed directly; instead, the signature is made on a secure hash of a message. Another approach is to use two different keys, one key for each of these operations. That way, such an attack would also be thwarted.
You can see the
allowed uses of a GPG key by using
the command line option
$ gpg2 --edit-key <key-id> pub 4096R/DEADBEEF created: 2011-09-24 expires: never usage: SC trust: ultimate validity: ultimate sub 4096R/CAFEBABE created: 2011-09-24 expired: 2014-08-06 usage: E sub 2048g/BA5EBA11 created: 2014-08-04 expires: 2015-09-15 usage: E sub 4096R/CA55E77E created: 2014-08-06 expires: never usage: S
The meaning of the usage flags is as follows:
|C||certify (sign another key)|
|A||authentication (log in to SSH host using a GPG key)|
One key to rule them all (Subkeys and identities)
One topic that comes up quite often is the topic of subkeys. Frequently, this topic appears to be complicated but indeed it is not. One thing to remember is not to confuse subkeys with user identities. These two concepts are not the same! You can bind several subkeys to one GPG key, and you can also bind several user identities to the same GPG key. However, selecting an identity does not select a specific subkey for you. They belong all to you, and you can combine them at your will.
To make the concepts of subkeys and user identities a little bit more clear, let me give you an example: Suppose a single GPG key has subkeys 1, 2, and 3, and is associated with the user identities A, B, and C. In one scenario you can use identity A with subkey 1, in the next scenario you can use identity A with subkey 2.
Let us practice with GnuPG:
First, choose the key:
gpg2 --edit-key <key-id>
Choose an identity (counting begins with 1, so x must be between 1 and n, both including):
Choose a specific sub key. Counting again begins with 1, the master key is selected by deselecting the currently active sub keys:
The need for multiple identities
Imagine that you have an established GPG key where several people have signed your key, and you have signed theirs. It was a lot of work to build the web of trust, and now you need to switch email addresses for whatever reason (different job, etc). Of course, you want to continue to use your established key with your new email address (and possibly let everybody know that you have retired the old address). This is where GPG’s identities come into play:
- You add your new email address to the key.
- Eventually, you revoke your old email address.
- You publish the changes to your key.
Nothing else changes, in particular you can continue to use your (sub)keys just like you always did. Even better, none of your peers need to do anything (except update your key).
But now, imagine that you own such a key for several years and by accident this key was compromised (for example, somebody got access to your laptop). Isn’t this bad? Sure it is, as it means that you have to throw away your key and rebuild the web of trust from scratch. Years of work lost. Except… if you had been using subkeys.
The need for subkeys
The idea of using subkeys is simple but its implementation can be hard depending on the particular version of the program you are using and the work flow you want to build. Let’s start with the idea and let us revisit the above example: You own a key or, to be more precise, a public-private key pair. You want to prevent that your private key gets stolen when somebody gets access to your laptop. That’s easy: Do not store the private key on the laptop. You do not need to care about the public key, as it is public anyway. All is fine and good, except that you cannot sensibly use your key any more: For signing and decrypting messages you need to access to the private part of your key.
To increase security and to have the private part of your GPG key on your laptop, you need two keys:
- The GPG master key, and
- a GPG subkey.
Both keys consist of at least a public and private key pair, possibly more if you decided to use different keys for signing and encryption. Now, you do the following: You split the GPG master key into the public and the private keys, and keep only the public GPG master key on your laptop. The private key you put somewhere safe (eg a USB pen drive hidden in a drawer in your home). Additionally, you put the complete GPG subkey (public and private part) on your laptop, and use only this key for “real” work (work unrelated to GPG itself).
In case your laptop gets compromised using this setup, the following will happen:
- The subkey becomes useless, as it has probably been exposed to the public.
- Your GPG master key is safe, since only the public part has been exposed (everybody is allowed to use that, anyway).
Hence, you need to use the GPG master key to revoke your compromised subkey, generate a new subkey, and publish your changes. Be aware that these key operations can only be signed with your primary key, so it is really important that the primary key is never compromised!
That is the high-level view. Of course, the actual implementation includes many details. Let’s get our hands dirty!
Hands on: Secure your master key
The following steps will give you a (public and private) master key pair in a secure location, and a public master key with public and private subkeys on your work computer:
On a dedicated (extra secure) machine, create a primary key, as well as at least one subkey. Then, make a backup copy of
~/.gnupgin case anything goes wrong:
cd && tar -cf gnupg.tar .gnupg
Export your secret key so that you can put it in a safe place:
gpg2 --export-secret-keys <master-key-id> > all-priv.gpg
Either directly write the file to the target media (for example a USB stick), or use a tmpfs directory such as
/run/user/$UIDas a temporary storage. If applicable, protect this file with
chmod 400. Consider printing it with paperkey. Now it is also a good time to generate a revocation certificate for the master key, and store it in a safe place far away from the master key itself.
Change the pass phrase for unlocking your sub keys so that attackers can not use the master key if they learn your day-to-day credentials:
gpg2 --edit-key <master-key-id> passwd
export-secret-subkeysto export all of the keys (private and public, primary and subkeys) but the private master key to an external file:
gpg2 --export-secret-subkeys <master-key-id> > sub-priv.gpg
In case you already have private parts of the key on the target machine (or you want to treat your main machine like all other machines), you need to delete your private keys first: GnuPG before version 2.1 is not able to merge private keys and hence will skip this key during import altogether. To delete all secret keys (master and sub keys):
gpg2 --delete-secret-key <master-key-id>
Then, use the previously generated file to import your private keys except for the private master key:
gpg2 --import < sub-priv.gpg
To check that your key now really consists of only the public part, try to print the private key:
gpg2 -K <master-key-id>
The output should show
secfor your private key. This indicates that there is a private key, but it is missing right now.
When you are in need of the private master key to perform some key operation, simply mount the USB drive (or restore your key to a tmpfs such as
--importyour credentials. Eventually, the following command line switch could be handy as well:
gpg2 --homedir /run/user/$UID
Do not forget to
shredthe sensitive temporary files after finishing your updates! Done.
GPG on multiple machines
When dealing with multiple machines, one question that inevitably pops up is whether one should create multiple keys for different machines. At least we have learned that private SSH keys must never be moved away from the machine they were created for. In this respect, GPG works differently: Private keys are not tied to a particular machine but to a particular identity. It is perfectly fine to share private keys between machines as long as they are exchanged in a safe manner. The private key is additionally protected by a password, and there is little incentive to steal a password-protected key when you already have access to the machine where sensitive documents are processed or stored.
How to synchronize the machines? The answer to this question really depends on the use case for a given machine. Fact is, you only need to protect private keys and owner-trust information. Public keys do not need to be protected and thus can be exchanged safely via key servers or other public means:
gpg2 --send-keys <master-key-id> gpg2 --refresh-keys
For synchronizing in a safe manner or without relying on third-party services SSH comes in handy:
gpg --export | ssh firstname.lastname@example.org 'gpg --import' gpg --export-secret-keys | ssh email@example.com 'gpg --import' gpg --export-ownertrust | ssh firstname.lastname@example.org 'gpg --import-ownertrust'
Or when pulling:
ssh email@example.com 'gpg --export' | gpg --import ssh firstname.lastname@example.org 'gpg --export-secret-keys' | gpg --import ssh email@example.com 'gpg --export-ownertrust' | gpg --import-ownertrust
Merging private subkeys
One issue that may come up if you are working on multiple machines is that you generate new sub key pairs (public and private keys) on different machines and forget to merge them before it is too late. Suppose you have two machines; on the first machine you create the first sub key pair A, and on the second machine you create the second sub key pair B. This is not a contrived example, it happened to me after buying a new laptop. The old laptop had a sub key the new one did not have, and vice versa. Needless to say, you want both sub key pairs to stay around, attached to one master key. How do you do that?
There are several solutions to this problem.
Use gpgsplit(1) to split your key into several individual packets, and then assemble these again for importing. (Warning: Dragons ahead! I did not take this road.)
Gpgsplit is so versatile that you can even convert master keys to sub keys.
Choosing a key server
Key servers are a nice way to make your public keys public. Everybody can install their own key server if they wish to. Usually, these key servers are interconnected, which means that when submitting a key to one key server, it will end up on several key servers. (Removing a key from key servers is not possible.) Due to the distributed nature of the key server infrastructure, it may happen that some key servers lag behind. Fortunately, when querying key servers one can choose a well-maintained server as the status of SKS key servers is publicly available.
Extend key expiry
Get the key ID (master key is sufficient, even if subkey needs to be changed):
gpg2 -k <yourname>
Edit the key. The next command will drop you into an interactive environment. In there, you can always request help by entering
?and pressing return.
gpg2 --edit-key <master-key-id>
Select the sub key in question (counting starts at 1; without this command, the master key will be selected):
Set the expiry date either by specifying a validity period or using an absolute date in the form of YYYY-MM-DD:
expire clean save
Finally, publish the results:
gpg2 --send-keys <key>
To see the changes on the other hosts, refresh the keys. It can take some time for the changes to propagate through the key servers.
Choosing encryption/compression algorithms
Now that you are well versed in the use of GPG, we can turn towards more elaborate uses. When using a backup system, for example, you can perfectly filter your data through GPG, and you will get scrambled output. But how do you know whether the resulting output is really encrypted, and with which options? Which ciphers have been used? Was the correct key used? Was the plaintext compressed before it was encrypted?
These are valid questions, and one handy tool seems to be pgpdump (git repo). However, you have first to install the tool to be able to use it, and there is already another easy way at your fingertips:
some gpg output... | gpg2 --list-packets
An example output is:
:pubkey enc packet: version 3, algo 16, keyid ... data: [2048 bits] data: [2042 bits] :encrypted data packet: length: unknown mdc_method: 2 gpg: encrypted with ELG key, ID ...
How to interpret this data? One can clearly see that the data is encrypted, and it gives the encryption key used. Without any further specification, GnuPG will always use the most recently self-signed subkey to encrypt messages, even if a particular subkey has been provided on the command line. To override this default behaviour and select a different key you have to use the exclamation-mark syntax on the subkey in question:
input data... | gpg2 -e -r 'deadbeef!'
A GPG stream consists of several packets, each describing a particular payload. Here, encryption has obviously happend with algorithm 16 (which refers to the Elgamal method, see RFC 4880), and the modification detection code packet (MDC) (a kind of checksum) uses algorithm 2 (here: SHA1, see the table below). Custom data will be encapsulated in a user attribute (UAT) packet, which is absent in the example above.
|#||Cipher S||Hash H||Compression Z|
There are two ways to set a particular algorithm:
- The recipient may specify algorithm preferences by editing a particular identity of his.
- The sender may override the recipient’s algorithm selection by using command-line switches.
set the algorithm preferences
as the message recipient, edit the key in question and use the
updpref commands, respectively:
gpg2 --edit-key ... gpg> pref [ultimate] (1). Alice <firstname.lastname@example.org> S9 S8 S7 S3 S2 H8 H2 H9 H10 H11 Z2 Z3 Z1 [mdc] [no-ks-modify] gpg> showpref [ultimate] (1). Alice <email@example.com> Cipher: AES256, AES192, AES, CAST5, 3DES Digest: SHA256, SHA1, SHA384, SHA512, SHA224 Compression: ZLIB, BZIP2, ZIP, Uncompressed Features: MDC, Keyserver no-modify gpg> setpref S9 S7 S2 H10 H2 Z2 Z0 gpg> updpref
The message sender is not bound to the preferences the recipient has
suggested using the method above; instead, he can choose an algorithm
using command line switches.
For this, use
(preferred), or — if you are careful enough not to violate the
the man page of gpg2(1) for more details.
Storing GPG keys permanently off-line
Now that we have secured our public/private key pair physically by removing its private part from all everyday machines, and we have strengthened confidentiality by choosing strong cryptographic algorithms, we want to make sure that the private part of the key remains retrievable even if the chosen secondary memory (USB drive, magnetic hard disk, SSD, etc) becomes unreadable. One way is to use paperkey to extract the secret bits from the key and print them on paper. While this is nice, this work flow can be made more pleasant by using a QR code instead of — or better: additionally to — plain text. If the QR solution is too much work, one could also consider using PaperBack.
Using GPG with SSH
Another nice use case of GPG is to use its keys as an authentication mechanism for SSH. This is a rather new feature, so be prepared that there may be still unresolved issues. The starting point for implementing this feature would be to check out the man page for gpgkey2ssh.
GPG automated signing
And now for the final trick: Sometimes it is necessary to sign documents automatically to certify their originality to the recipients. This can be achieved with GPG as well, although you have to make sure that the machine where the signing takes place is highly secured, as there will be no pass phrase on the secret key.
That’s all for now. As said before, GPG is not so difficult to use once one has learned a few simple concepts. Of course I did cover only a small subset of GPG’s functionality but that’s okay as long as we learned something. I intend to update this page when I learn new things about GPG, so if the permalink moves make sure to check the newer content as well.