PGP (GPG) Explained

Pretty Good Privacy, or as it’s more commonly known as by its most popular client’s name, GNU Privacy Guard, is a method of encrypting and/or signing your messages using the power of public key cryptography. And, while it can get extremely complex, the basics of using PGP are, actually, pretty simple. So in the words of the great Angus Deveson, Let’s get started.

Note that this it not a tutorial on how to use PGP, this is just an explanation of how the system works.

Everything PGP starts with a key pair, which is one public and one private key. The public key is free to be shared, hence the name, and can be used to encrypt some data in such a way that only the private key can reasonably decrypt it. The private key should be, again, as the name implies, private, since besides the ability to decrypt messages encrypted with the public key, any messages encrypted with the private key can be read with the public key… that might sound weird, encrypting a message such that anyone can decrypt it, but just wait.

Each key is made of a series of “packets” in PGP terms. You can have, for example, a public key packet, then a user ID packet which contains your email address, a private key packets, and maybe some signature packets later on. Keys may also contain subkeys, which is just another key pair inside the same logical unit. Subkeys may have different allowed usages, so you could say that this key is use for encryption, and that key is used for signing.

The final thing to talk about here is the PEM format that you see… everywhere. PEM stands for Privacy-Enhanced Mail, and while it has seen use in fields other than this, this is where it started. The format exists as a way to pass raw, binary data, over a textual transmission medium, like, well, an encrypted message in an email body. Here’s an example:



And yes, for the record, that is an invalid key block, since the actual one is about 7 times the size because the way that key is structured. But, you’ll notice that you have an beginning line that also tells you what the data should be, Base64 encoded data, and then, at the end, in this case, =MLwi is a checksum, and then the end line. This format is both machine and human readable, since, while you may not be able to actually decode the data yourself, you can read the header line and see “oh, this is a public key.”

Now, the flow of operations for PGP is, fundamentally simple. First things first, you’re going to generate a key pair for yourself, and then you are free to distribute the public key, which we have a method for this, keyservers, which are computers, or entire networks, running software with the express purpose of holding and distributing public keys from a well-known location, like a particular web URL. Alternatively, pass it out by hand, attach your public key to your messages… Once someone has your public key, then they are free to encrypt a message using said key, which will produce a PEM block which makes up the body of the actual sent message, and because of how public key cryptography works, only the private key is the correct set of numbers and variables that can undo the encryption math. With encryption, you can guarantee who has received the message.

There is one other possible operation though: signing. Again, not a concept specific to PGP, but in this case, signing refers to taking the hash of some data, say, the SHA-1 or SHA-256, and then encrypting that with your private key. Remember, the key pair is symmetrical like this: whatever is encrypted with one, can be decrypted with the other. As such, if you encrypt with your private key, anyone with your public key can read it. Well, why is this useful? Because if someone can take your public key, decrypt that data, and verify that the hash matches, they can prove that you saw the same thing when you ran this operation. And since only you have the private key, they can be sure that only you made that. This is how signing works: By encrypting a message hash with your private key, and then attaching that to the original message, you can, in effect, say “I was the one who created this, and it has not changed since.” With signing, you can guarantee who wrote the message.

One other signing point though: People may also sign other keys, if you remember when I briefly mentioned signature packets before. Signing someone’s key is a way of sharing to the rest that “X trusts Y’s key.” Signatures stick with the key, so when you download a public key that’s been signed by others, those signatures come with it too… as well as their key identifiers, allowing you to download those keys, and check that the signatures really match. This is the fundamental building block of the so-called web of trust: If A trusts B, and B trusts C, then A can be reasonably sure that C is trustworthy too. There’s a little more nuance to it than this, but we’ll get to that on a later post.

One final note: I’ve been trying to talk about PGP in terms of encrypting or signing “messages” without really clarifying what a message is. In the beginnings, this was mostly email. However, PGP emails don’t have really widespread usage, but it does have its place in some circles, mostly with the more technically inclined crowd. There is one other place that PGP has really taken off: version control. Almost every modern VCS, be it Git, Mercurial, Bazaar, you name it, likely either has a built-in feature, or some plug-in or extension to allow you to sign your commits with a PGP key, allowing for other users to verify that when the commit says you authored it, you actually authored it. Many web-based interfaces for these, like GitHub and GitLab also support uploading your public key to the server, meaning that when someone looks at the commits page, it can attach a little badge saying “hey, this one has a verified signature.”