An Introduction To PGP
Tags: security, privacy, computerscience, tutorial
Published: 2022-01-16 17:40:42

I am someone who has been interested in privacy and security for most of my adult life. I am also someone who can be described as, perhaps, a tiny bit paranoid at times. Are these things related? Probably.

However, you do not have to be paranoid to want to be secure and to have your privacy maintained online. Even if you don't have something to hide, that doesn't mean that your friends don't.

What if you're talking to someone who is standing up for women's rights or is LGBTQ+ in a country where such things are socially (or even legally) dangerous? If you don't keep yourself secure, then **you** could become their vulnerability.

I'm not trying to scare you, and I'm certainly not trying to turn you into some conspiracy theorist. I'm just trying to point out that, even if you have nothing to hide, that you should be conscious of your online security posture.

So, you may ask now, what should I do about it?

There are many good security and privacy tools and services out there (which I may expand upon in a future post), but today I want to talk about something that I have been playing around with recently: PGP.

## What Is PGP?

PGP (short for "Pretty Good Privacy") is an protocol used to _encrypt_, _decrypt_, and _sign_ data. It's widely used, and if properly implemented, is considered a great way to protect yourself and your private discussions online.

The idea behind this is that, you will start with a _public_ and a _private_ key that are paired. The public key is something that you can share openly with people, while the private key **you should keep hidden**.

The public key allows others to mark you as the recipient of a document, encrypting it and saying that only you can decrypt it.

The private key allows you to confirm who you say you are, and decrypt the message that was sent to you.

Furthermore, say you want to send a message to someone, and you want to make sure that they know you are who you say you are. PGP allows you to sign the document using your private key which the other person can confirm you are who you say you are by comparing it to your public key.

If you want a high-level description in video form, Computerphile has nice video [here](https://www.youtube.com/watch?v=GSIDS_lvRv4).

## Where Do You Get PGP?

The modern incarnation of this protocol, [OpenPGP](https://www.openpgp.org/about/), was implemented by the [Free Software Foundation](https://www.fsf.org/) in [GPG](https://gnupg.org/) ("GnuPG" or "GNU Privacy Guard"). If you are on Mac OS X, the easiest way for you to get GPG is through [GPG Tools](https://gpgtools.org/).

## How Do You Use PGP/GPG?
Now that we have gone over "what" PGP and GPG are, I want to go over some of the basic usage.

This tutorial will only really scratch the surface, but I hope that I can at least teach you some things that can help you keep private things private.

### Some Notes Before We Begin

For the rest of this article, I am going to assume that you have installed GPG, which as explained has implemented implemented OpenPGP. I will be showing you examples via the terminal.

In my case, I am a Mac OS X user and I will be showing examples via my preferred terminal, [iTerm2](https://iterm2.com/) that uses zsh that has been customized with [Oh My Zsh](https://ohmyz.sh/).  My [Oh My Zsh theme](https://github.com/ohmyzsh/ohmyzsh/wiki/Themes) is af-magic with the synthwave-everything [iTerm2 theme](https://iterm2colorschemes.com/).

If you want to know more about terminal customization, comment below or reach out to me on [my Twitter](https://twitter.com/cjtaylor2390).

### Getting Into The Terminal And Verifying Installation

To start with, you will need your terminal open and GPG installed (see above).

![Open iTerm2 window, currently cleared with a cursor resting on the upper-left-hand side of the image.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c5iswl679cu0apuolsv6.png)

Once you have your terminal open, you can confirm that you have GPG installed by doing the `which gpg` command that shows the file path.

![Open iTerm2 window. I have executed the which gpg command, which results in the path, usr/local/bin/gpg being printed to the screen.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/enx8cdf1t5pdt8ddvs4s.png)
 
The first, and incredibly useful command to know is `gpg --help` which is gives you a list of the available commands and the various flags associated with them. It's especially handy if you ever forget something (which I do _all_ the time).

![After running gpg --help, legal info and supported algorithms are printed to the screen, along with the available commands and their flags.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rqbh0z15eyzglv1qf78p.png)

### Creating Your First Public/Private Key Pair

Once you have made sure that you can use GPG and have taken some time to read some of the help document, it's time to generate your first key pair.

Run the command `gpg --full-generate-key`, and you will be prompted about which algorithm you wish to use to generate your public and private keys, as well as the number of bits of information (or [entropy](https://en.wikipedia.org/wiki/Entropy_(information_theory)) that they will contain. 

A theoretical discussion of what this all means is well beyond the scope of this blog post, but practically speaking, you can think of entropy being associated with the chance that a hostile actor could break the encryption via brute force repetition. The more bits, the harder it is for them to break the encryption. 

In this case, I have chosen `(1) RSA and RSA` and `4096` bits.

![After running gpg --full-generate-key, I am prompted by the terminal which algorithm I wish to generate the PGP key pair. I have chosen 1 (RSA and RSA) with 4096 bits of entropy.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f7tyvqw44cfddkcp9m8j.png)

After choosing the algorithm, you will then be prompted about the expiration date of your key-pair. You can choose a range from days to years (e.g., `2y`), or to not have an expiration date at all (i.e., `0`).

![After selecting the algorithm and entropy, you will then be asked to choose an expiration date. You can choose ranges of days (e.g. 2 for 2 days), weeks (e.g., 2w for 2 weeks), months (e.g., 2m for 2 months) or years (e.g., 2y for 2 years. In this case, I have chosen 2y, representing 2 years in the future from the current date.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2axcjmhytjwwb6f851b1.png)
 
 ![Alternatively at this step, you can choose that the key have no expiration date, and so you would type 0.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6fuvv0muze23fpykktph.png)

After that, you will be asked to generate a UID for the key, which is a combination of your name, your email that you want associated with the key, and some optional comment. This metadata will be a way of telling others who you are claiming to be.

In this case, I wrote my name (Corbin), the email (cjtaylor1990@dev.to), and my comment is something unquestionably true, which is that I love coffee and cats.

![The next step will be to be specifying metadata that will be part of the public key. This includes your name, email, and a comment. In this case, my name is Corbin, the email I chose is cjtaylor1990@dev.to, and the comment is that I love coffee and cats.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dq56gdwqj1t9gqhbhtc1.png)

Finally, you will be prompted to give a pin to be associated with the private key. Any time you try to use the private key, you will be asked for the key pin.

![After giving the key metadata, you will be prompted to give the secret key pin code via a GNG Tools. Choose something long yet easy to use, either with a password manager or diceware](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6qkiqwhq0ez38b9a9qud.png)
 
For my case, I used a 40 character string that I randomly generated using [1Password](https://1password.com/). Alternatively, if you don't have a way to generate and store passwords electronically, you could use [diceware](https://www.eff.org/dice) to generate passwords and then store it on a piece of paper in your wallet or a safe.

After giving the pin code, `gpg` will generate the key pair and will give you a confirmation, as well as importing the public and private keys into your GPG _key ring_ to be used later. The GPG key ring is simply the way that GPG stores and manages PGP keys on your local machine.

 ![After giving the pin code for the private key, you will get a confirmation code that the key pair has been generated. It will give you a lot of information on the screen, including a long alphanumeric value unique to the key-pair known as the fingerprint.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/626n2pl2opy1toaqb48k.png)

Notice in the picture above that there is a long alphanumeric string (`212CF1042D88FFF461A62B76811A3B169B7EA4B7`) above the `uid`. This is a unique identifier known as the key _fingerprint_ and the last 8 values in the string, `9B7EA4B7` is the key ID.

To confirm that you now have the key in your key ring, you can use `gpg --list-keys`. You can list the specific key that you just generated by specifying the email, the key ID, or the finger print values as arguments. Alternatively, you can just use the command as is to list all of the keys that are listed on your key ring.

![You can check to see that you have the new key  pair on your key ring by using gpg --list-keys, and give the email, the key ID, or the key fingerprint.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b55ywbzpxojz8alkc4uz.png)
 
### How To Encrypt A File That Is For Your Eyes Only

Now that you have a public/private key pair, you can actually start to do basic encryption/decryption. For example, say that you have a message that is for your eyes only. We could put that into a text file and encrypt it using the key that you just created.

First, you will need such a file. An easy way to create such a text file would be to use the `echo` command and then send it to an output file (e.g., `test.txt`) using the output operator (`>`).

For example, `echo Hello, PGP! > test.txt`. This will generate a `test.txt` file with your secret phrase, `Hello, PGP!` inside of it.

You can then confirm that the file contains the message using the `cat` command.

![You can create a text file that contains a message (e.g., "Hello, PGP!" by using the echo command followed by the output operator (i.e. >). This will output a text file at the path specified (e.g., test.txt) with the output inside of it. You can see what's inside of the file using the cat command. In this case, we see that you find "Hello, PGP!" inside of the file.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0681ez7sy12k3f244wyq.png)
 
Now that you have your text file with your super secret hidden message, you can then encrypt it using `gpg --encrypt` and specifying yourself as the recipient with the `--recipient` flag.

In this case, that would be `gpg --encrypt --recipient cjtaylor1990@dev.to test.txt`. This will output an encrypted file, `test.txt.gpg` which you can check the contents of with `cat`.

![Using gpg --encrypt --recipient cjtaylor1990@dev.to test.txt, I create an encrypted file, test.txt.gpg. If you use cat to see what is inside, you will see a jumbled encrypted mess. This is to be expected.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pso3g62qpnhcu1wqpmw9.png)
 
If you see a garbled mess, then **CONGRATULATIONS!** You have created an encrypted message, and if you cannot currently read it, then hackers (or the NSA) likely can't easily read it either.

Now, if all we could do is _encrypt_ the message, then that's not very useful. You want to come back later and _decrypt_ the message!

You see, by encrypting this file this way, we have used your public key (the one that you can give to others) to encrypt a message specifies that only the _real you_ can decrypt.

Thankfully, this is where the private key comes in! This also shows why it is VERY important not to share your private key with others.

Your private key (protected by your key pin) is the means by which you prove that you are the owner of the public key. The _real you_.

Since you have the private key on your GPG key chain, all you would have to do is use `gpg --decrypt` on the encrypted file, and it will then print the secret message to the screen along with the recipient (you). Note that you will be prompted (via popup) for your key pin before your private key can be used.

Furthermore, you can use the output (`>`) operation to put the secret message into a file that you specify.

For example:
`gpg --decrypt test.txt.gpg > test.txt.clear`
where I have chose the '.clear' file suffix to represent a clear-text file (as compared to an encrypted file).

![Using gpg --decrypt on the .gpg file and then entering your key pin, you can decrypt it to see the message or output the clear text message to a file using the output operator (>) . Here I do this, showing that without the output operator, the secret message will be printed to the screen, while with the operator, you will get a new file that you specify the name of (e.g., test.txt.clear, which contains the secret message, now human-readable.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nn5zw2j1cdkoc9qm8gzu.png)

### Importing A Friends Public Key To Your Key Chain

Now, encrypting messages to yourself is nice, but what if you could encrypt messages to others? Well, you can! But first, we need another friend that uses PGP.

Let's say my awesome friend @pachicodes has decided to send me their public key. Likely, it would be something like `public.pachicodes@dev.to.asc`, where the `.asc` is an "ASCII armored" file type that is often used to store and exchange PGP keys. While the raw PGP key is a binary file, the `.asc` file is an ASCII representation of that binary.

Once Pachi has given me the public key, I can import the public key into my GPG key ring using `gpg --import`, specifying the file as an argument.

![My friend has given me their public key, public.pachicodes@dev.to.asc. I'm able to import their public key into my key chain using gpg --import public.pachicodes@dev.to.asc. GPG will then give me a confirmation that the key has been imported and shows me the metadata on the key afterwards.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c4ym97xt1kwwgbevkzzk.png)

### Encrypting A Message To A Friend

Now that I have my friend Pachi's public key, say that I now have a secret message (stored in `for_pachi.txt`) that want to send them. I want to make sure that _only_ they can read it.

I can use their key to designate them in the `--recipient` flag in `gpg --encrypt`. Furthermore, to tell Pachi that the message is really from me by _signing_ the encrypted file.

In full, to encrypt the `for_pachi.txt` file, we would do,

`gpg --encrypt --sign --local-user cjtaylor1990@dev.to --recipient pachicodes@dev.to for_pachi.txt`

where `--sign --local-user` allows `gpg` that I want to sign using one of my local keys, `cjtaylor1990@dev.to`. Again, this will produce an encrypted `.gpg` file.

![Using gpg, I'm able to encrypt the for_pachi.txt file with the public key of my friend, Pachi, and sign it with my private key. After doing so, gpg will mention that there is no assurance that the recipient is who they claim to be on their public key, and asks if you want to proceed. In this case, I continued, and using ls, I see that there is a new for_pachi.txt.gpg file in my directory.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a7jwnmpmk14tkvwinavp.png)
 
This signing is done using the private key that you generated earlier, and GPG will once again prompt you to give a key pin. If I had given the part of my key that I can share (my public key) to Pachi earlier, GPG can compare the public key against the private key signature on the encrypted file and confirming that it was actually me who signed and encrypted it.

Assuming that Pachi has my key imported into her own GPG key ring, she can decrypt the encrypted file, see that it was from me, and what the secret message is:

![Here, I show what Pachi would see after she has imported my public key and used her private key to decrypt the encrypted file. It states who the signature is from, and that the secret message is "We are awesome hackers!"](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i3vog5qajaqqy6jtptkt.png)
 
Now Pachi and I have successfully exchanged public keys, and using our secret private keys, we have successfully exchanged encrypted messages back and forth to one another. Only those with access to our private keys (and key pins) could successfully sign the encrypted messages, or decrypt them to read. In this case, Pachi sees me exclaim that "We are awesome hackers!"

This idea is the heart of PGP encryption, and what makes it so powerful as a privacy and security tool. It's used in many popular privacy-focused software, such as [Proton Mail](https://protonmail.com/) and [Signal](https://www.signal.org/) as a means of strong end-to-end encryption, and has famously been used to journalistic sources and whistleblowers.

Even if anyone was able to get a hold of the traffic being sent between Pachi and myself, they would not be able to decrypt it to know what it meant, not even the service we were using to communicate!

## PGP Exporting, Back-Up, And Publishing

You can export both your public and private keys as `.asc` files by using the `gpg --export` and `gpg --export-secret-keys`, while also specifying the key you wish to export and using the output operator (`>`) to specify the file name.

For `cjtaylor1990@dev.to`, we can export the key pair by doing:

`gpg --export --armor cjtaylor1990@dev.to > public.cjtaylor1990@dev.to.asc`

and,

`gpg --export-secret-keys --armor cjtaylor1990@dev.to > private.cjtaylor1990@dev.to.asc`

The `--armor` flag specifies that we want `gpg` to output everything armored ASCII format instead of a binary.

![Here, I have used gpg --export to export my own public key, using the --armor flag to use a format consistent with an .asc file. I then use > to output to a txt file, public.cjtaylor1990@dev.to.asc. I see this file in my directory now, and using the head command, see what the contents look like. The inside is a large block of ASCII character and marked with a header that specifies that the block is a PGP public key.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6vajs1n4e4vzmhnabhl0.png)
 
![Using gpg --export-secret-keys with the --armor flag, I'm able to output my secret key in an .asc file. Using ls, I see now I have both public and private parts of the key-pair exported from GPG and can now be backed up.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9pl186nxquaorfkhx1ki.png)

Now that both parts of the key pair have been exported from GPG, you can then back them up (e.g., on an encrypted drive). Backing up your keys is important, as without them, you will be able to decrypt any message intended for you nor sign any encrypted file.

Finally, you can share your **PUBLIC** key by uploading it to a public key server that allows other to download it and import it so that they can contact you securely.

To do this, you can use the `pgp --send-keys` command, specifying the key-ID (in my case, `9B7EA4B7` or the last 8 characters of my key fingerprint).

![Using gpg --send-keys, and specifying my key ID, 9B7EA4B7, I can upload my public key to a PGP key server. In this case, since I didn't specify a server, the terminal says that it is sent to the default server, key.openpgp.org.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/06kzvzvpv0n5plswqekw.png)
 
The default server is [key.openpgp.org](https://keys.openpgp.org/), which you can then search using your key's fingerprint.

![On key.openpgp.org, if someone knows your public key's fingerprint, they can search for and download it to put it on their own GPG key chain. The page is minimal, but after searching, it as a link in the middle of the screen that will start to download the public key file when clicked. This allows them to contact you securely, allowing only the you (with your private key) to decrypt their message.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yaqy3abjje8vefvwpqm5.png)

## Revoking A Compromised Key

As this whole protocol is dependent upon on each person keeping their private key uncompromised, it is important to make sure that you _revoke_ a key that you believe to be compromised. You can likewise revoke a key if you no longer use it.

To make sure you are ready for such a scenario, you can generate a revocation certificate for your key using the `gpg --gen-revoke` followed by your key ID. You will then use the output operator (`>`) to output the data to a file, in this case `revoke.cjtaylor1990@devo.to.asc`. You will then be asked for more details about why you are revoking the key.

![Using the gpg --gen-revoke command with my key ID, I generate a revoke certificate and output it to an .asc file, revoke.cjtaylor1990@devo.to.asc. You will be prompted why the key is being revoked, and if you want to add any more comments.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3kbmjvxx0d3d112xp4le.png)
 
You can then keep the revoke certificate `.asc` file around for safe keeping (**DO NOT SHARE IT**) and if you find that you have to mark it as no longer a valid key, you can then import the certificate as a key into your GPG keychain. This will mark the key as revoked and no longer valid.

![Using gpg --import on the revoke certificate file, revoke.cjtaylor1990@dev.to.asc, this will tell GPG that the key pair associated with that revoke certificate is no longer valid. GPG will not consider the key as invalid.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9863ciegipkubdvh2bl6.png)

You can confirmed that the key was revoked using `gpg --list-keys` and then send the updated (revoked) public key to the public key server using `gpg --send-keys`.

![After we have imported the revoke certificate, I use gpg --list-keys 9B7EA4B7 (the key ID) to verify that the key has been revoked (invalidated) locally. I then use pgp --send-keys to push the changes to the PGP public key server, keys.openpgp.org.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7mxzscd2vb79o7f9136z.png)

Keeping a revoke certificate around and making sure that any compromised or unused key pairs are marked as revoked helps protect you from others reading any encrypted data with you as the recipient. Furthermore, it makes sure that others can trust that any information signed by your private key is really from you.

## Deleting PGP Keys From Key Ring

If you have revoked a PGP key pair and no longer need it, you can delete it from your local key ring.

First, start by deleting the private key by using `gpg --delete-secret-keys` and specifying the key that you wish to delete. In this case, I am deleting the secret key associated with `cjtaylor1990@dev.to` that I revoked in the last section.

![Using gpg --delete-secret-keys and specifying the key associated with cjtaylor1990@dev.to, I am prompted if I really want to delete the private key from the key ring. After confirming each time, you the private key is finally deleted and will no longer be usable.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jqisd6pdc7bgj53vgioo.png)

You are then able to delete the public key with `gpg --delete-key`, while specifying the key in the same fashion as you did in the previous command.

![Using gpg --delete-key and specifying the key associated with cjtaylor1990@dev.to, I'm able to delete the key from my local key ring after a confirmation.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ezd9n8o436xzwekpsu93.png)

## Summary And Final Thoughts

If you've been following along, you now have created your own PGP key pair (a _public_ key and a _private_ key) using `gpg --full-generate-key`. The public key can be shared with others, while the private key and your key pin should be kept secret.

With your public key, you encrypted a secret message using `gpg --encrypt` that only the person with your private key (the _real you_) can decrypt; you specified who can open it using the `--recipient` flag.

With `gpg --decrypt` and your key pin, you decrypted your secret message, confirming that it is the same one that you started with despite having been garbled and made a mess of during the encryption process.

Similarly, after importing a friends PGP public key, you were able to import it into your GPG key chain using `gpg --import` and then encrypt a file addressed to them using similar commands, but adding the `--sign --local-user` flags to sign the encrypted file with your private key and allowing your friend to know it was from you.

You learned how to export your public and private keys using `gpg --export` and `gpg --export-secret-keys` respectively as a way of backing them up. You also learned how share your public key via a PGP public key server using `gpg --send-keys`.

Finally, you learned how to generate a revoke certificate using `gpg --gen-revoke` so that, if your keys are compromised, you can invalidate them locally (by using `gpg --import` to import the revoke certificate) and on the PGP public key server (by using `gpg --send-keys` after the key has been marked invalid locally).

While this introduction does not necessarily cover all there is to know about PGP, nor does it cover specific use cases (e.g., [email encryption](https://emailselfdefense.fsf.org/en/)) or how to use the GPG Tools GUI, I hope I was able to help you appreciate (or even want to use) this useful privacy tool.

I would not consider using PGP the first thing you should worry about when improving your online security posture; that would probably be to use a password manager and enabling two-factor authentication. However, I still consider it very interesting and an incredible privacy tool, with an excellent track record.

Thank you for reading this introductory tutorial on PGP encryption. I know it's been a while since I wrote anything, but this has been an interest of mine lately, and I wanted to share.