Confidentiality in the Digital Age
A primer on message and file encryption, using common, open, and secure standards.
This post is going to focus on teaching the basic functionality for the "GPG" software, specifically how to; encrypt, decrypt, sign, and verify text/files. But first, why? I have two motivations for writing this. The first is just a general desire to share some cool knowledge I have with other tech people that may be interested, but the second is due to feeling more and more like the time and place in which I live requires such knowledge to continue living a safe and peaceable life. While I won't elaborate on that second point, it is my primary motivation behind sharing this knowledge.
Apologies in advance for the somewhat unorganized or "rambling" nature of this post. It's been a while since I wrote anything in a format like this, or of this length. I also struggled to condense down various technical topics, and avoid rabbit trails.... If you find this too overwhelming just skip to the very end and try out one of those graphical programs I mention.
Definitions, and What We're Doing?
Let's review some key definitions before diving in. While Wikipedia will be a more in-depth source, what's most important to understand is that encryption is the act of taking data, and modifying it in such a way that it looks random, ideally with the result being that no one (except who you intend) can determine what the original data is. In the real world we see this idea go back millennia in things such as the Caesar cipher, which you may have used as a child with a decoder ring. Decryption is, of course, the reverse act; where we take encrypted data and return it to its original form. To sign data is much like how you sign your ballot, it ensures (hopefully) that you are in fact the author of the message â or at least, that you endorse it. Verification here simply refers to verifying the signature on some piece of data. Lastly, the software GPG, also known as the GNU Privacy Guard, is a popular utility included with most operating systems (notably excluding Windows, though it can be installed), which is primarily used for working with PGP keys. Now, that last part can be a bit confusing, so all you need to know is this: PGP is the standard, GPG is the interface. We're going to be learning how to encrypt/decrypt data using PGP keys, however we will do so with the GPG program.
Before proceeding its worth understanding that this whole system relies on the concept of public/private keypairs. Explaining how this works is far outside the scope of this guide, just know that we are going to be generating 2 keys today. One is called your private key, which should NEVER be shared with anyone ever (and should be kept safe), and this is what you will use to decrypt data. The other is your public key, which can freely be shared with anyone, because this is the file that lets people encrypt data. In this system, keys are not bidirectional. The public key only encrypts, and the private key only decrypts. Additionally, the private key can sign data, and the public key can verify that signature, but more on that towards the end.
Getting Started
Before we do anything though, we must prepare. If you're on MacOS, this software is already installed, simply open the "Terminal" application, and type gpg --version
to verify that you have it. If you're on a Linux distribution, it's likely already installed, but if not, you probably already know how to install it on your particular OS (the package name should be gnupg
). Lastly, if you're on Windows, you can head over to GnuPG.org and click on Gpg4win. I can't easily test anything on Windows, however I assume that once that program is installed and you've rebooted, you'll be able to open Windows Terminal or Command Prompt and run the gpg
version command above.
Encryption
Assuming you've gotten everything ready to go, let's start with encryption so we don't need to setup our own keys. Open your OS' terminal and run the following command (I recommend copying and pasting): gpg --keyserver keyserver.ubuntu.com --recv-keys A922AD77F5C03259F4C307E56D25CEF6002D3D34
- This will download my public key, which will allow you to encrypt things that only I can decrypt. When that's imported you can use it like this: gpg --encrypt --armor --recipient A922AD77F5C03259F4C307E56D25CEF6002D3D34
- When you press enter you'll get no output aside from a new line. This is because the program is waiting for input. Type hello matthew
, press enter, and then press Control+D to terminate input. This will cause GPG to spit out the following:
-----BEGIN PGP MESSAGE----- hQIMA0JBMXbUS/t9AQ/+JkFmiXd5r75szswyAHHmVyFPk9fNhJ0/PvMikoIOoyCv 2D8Vf96fW8ynbeXdWrRelKE+0vm5l+awdwdsjQNHkC/xaGjeUHtY+JwmgCpahwzf 2xa3Vv5HM9g1r+qAjLDPcLxt1b/l6uA89YCxJ1Yzt2fmjjn6R5C8lhIVXfg1AG6j ywTwUCEa2GaHgtLSKivkMMyj/KTXrGcJ6Zr1tPd4ud+S/AeQVBSlcHvk82+BarG1 VP+pcMHzcZoCnWcxR3DOlTeAYQJywMj0EklRXwrD1CyL0La/GpNiCNbRYZGkPM3m LfytQjoBs/wTOm5u7XYUiFMVqfsGLChcKqJxNh4RPUcbakV1qRHYGCFTZyz7qiw1 que/Ccvl+xmYt2q1Qsp/E31UWwA7iSx1AxAIVZKQpZHDQsiaCuTUzQiKORosPUlK c+Gl/ve2ER39eMbEjM3KwDGAkFp8POwT4wdN4u+vC4W2ud2fhdXmEIULVrm9ok39 gw6KcC1iFZ/oVmTyWcCX9Fc7HM/EX07oTKIfGimgAZJJ//jbbRvxebwn/Kk9ufok uZbqT/wzzIiRDSIl+7E8GaWMrxBY5RRDOFTRIDFLSGMcKT7Q18noZgnmHFP+inYI Sue3HJzVlt43BxwDSHKuSs6qEw2KriIM4+Is/V6+A/VIA+BLz1OT8QIr58oMx6LS SQEXp67lZKZ9oNznRPqb9HASUjX4bPDtmxn53ySHSDJUzLUNkIrXhvEyXo1mYno0 nIdNPEkfp5SDM1TEw286egEgc5xM9a+s1PU= =vgDk -----END PGP MESSAGE-----
Wow! That's quite a lot of output for such a small message, isn't it! I'm not 100% sure about this, but I think that encrypted data has a minimum size, so don't worry about encryption ballooning your data size, at most it adds a few kilobytes. What's important here is that, how on earth would anyone figure out what the original message was? Try this out yourself with a different message, and send me the output to see if I can decrypt it! One command line option we typed that isn't obvious as to its purpose, is the --armor
part. That flag effectively tells GPG to output our encrypted data as letters, numbers, and symbols only, which makes it easy to display, type, copy/paste, etc, but it also increases the data size. If you run that command without --armor
it only takes up 602 bytes, instead of 878, but for the remainder of this guide we will use --armor
. Just know that if you're going to encrypt large files, you shouldn't use this due to the increased data consumption.
Now, having done barely any work, you can already send secret messages to me, and you never even had to create any keys of your own. This a the strength and weakness of PGP. A strength as demonstrated, but also a weakness because it means both parties have to do work if they want to talk to each other.
Making Your Keys
So, how can we get you a public key so that others like myself can send you encrypted data? This is a more complex subject, and there are more secure ways to generate and store these keys but for the sake of time we will only go surface level today. To create a key I'm going to recommend running gpg --full-generate-key
. When prompted for key type, enter 1 for RSA/RSA, then for the number of bits 4096, and for expiry "0" to indicate it never expires. Note once again there are better ways to do this, and key expiration is generally a good idea in environments where signatures matter, but for simplicity we will avoid this. As for your identity, depending on the context you can leave this blank. I use my PGP key for verifying my identity in the public sphere, and so my key includes my full name and an email address, but if you're only going to be communicating then maybe just put in a nickname and no email. The comment will be publicly visible, and I'm not entirely sure of its purpose, but I used mine to indicate which key it was.
Once you've entered all the necessary details, GPG will ask you for a passphrase. This is your last line of defense, should someone get ahold of your private key file (or gain access to your computer). Effectively you're going to place a very basic encryption on the private key itself, and your password decrypts it. I recommend no less than 12 characters, and it ought to be randomly generated. I'll have to make another post about this some time, but suffice to say, your password generation skills are awful, so generate a randomized one that you can memorize or store inside of a password manager (I don't recommend this though). After this, gpg will take a moment to generate the key using your system's random number generation capabilities, which on most or all systems are influenced by your actions. The more things you do, the more secure this randomness is, although this process is usually quite quick so I wouldn't worry about it too much.
Encryption
Okay, that was a lot, but where are we now? Now you have a private/public key pair. the final output of the generation command shows you your key ID (a string of random digits and letters between A and F). That ID of course, you already know how to use to encrypt data, but how do we decrypt data that someone has sent to us using our public key? Quite simply, run gpg --decrypt --armor
. You will once again get no output other than a new line in the terminal. Here you can paste in your PGP message, press enter, and then Control+D, and GPG will output the decrypted message. I can't give you a demonstration message since I'm writing this in the past and don't have your public key, however try encrypting using the steps earlier, then decrypting what you encrypted. You may notice we didn't specify which key to decrypt with, and that's because the PGP message contains enough extra data to tell you which key it needs, so we don't have to worry about that.
Using Files
So, we can encrypt and decrypt short messages. That's nice, but our reliance on manually typing, or using the clipboard is annoying. Wouldn't it be nice if we could use some files? Well, as a matter of fact we can. While these steps vary system to system, the following steps should generally work. If they don't work on Windows let me know and I'll investigate further and update the post with different instructions for Windows.
Firstly, for encrypting, we can just add a filename to the end of the command, i.e. gpg --encrypt --armor --recipient ... SuperSecretTextfile.txt
which will encrypt the file and save the encrypted version as SuperSecretTextfile.txt.asc. Don't like that file name? Then add --output
(or -o
) like so: gpg --encrypt --armor --recipient ... -o SuperEncryptedFile.pgp SuperSecretTextfile.txt
(note that the input file must be the last argument). Secondly, for decrypting its largely the same. You can just pass a filename to decrypt, and if you want to store that as a file you can use --output/-o. Also you can use --output while still typing in data manually (i.e. gpg --encrypt --armor --recipient ... -o message.pgp
will let you type a message and save the encrypted version to message.pgp).
Signatures
Now, I want to discuss signatures. I won't go into the same level of detail, but make sure to reference the above paragraphs if you want to do this with files. The purpose of a signature is to verify that someone endorses a piece of data. Signatures are also tied to time stamps, so if someone copies your signed message it will be possible to prove its the same message, and not a new message with the same contents (for example if you authorize someone to borrow 100$, they can't claim to have gotten the message twice because both messages will have the same time stamp). For myself, I only have to run gpg --clearsign --armor
, though I don't know how it determines which key to use here, which may be worth looking into more. But for the time being we only have one signing key anyway, so this should be fine.
Once you type your message and get the output, you can verify it with gpg --verify
. Remember, signing uses the private key, verification uses the public key. Anyone can verify. One last thing, if you want to encrypt a message with your friend's public key AND sign it with your private key (so they know you are the one who sent/encrypted the message), you can use for example gpg --encrypt --sign --armor --recipient A922AD77F5C03259F4C307E56D25CEF6002D3D34
to send me a signed, encrypted message.
Sharing Keys
One last thing you need to know to make (easy) use of this system, is: how do you share your public key? There are two ways to go about this. The first is to just get the key file using a command like gpg --export --armor A922AD77F5C03259F4C307E56D25CEF6002D3D34
which gives you the public key for that ID (make sure to use your own). This output is pretty big, so feel free to use --output/-o as we learned above, just make sure the key ID is the final argument. The second way is to upload your public key to a keyserver (which is how you were able to acquire mine at the beginning of this guide). To do this it seems you only need to run gpg --send-key A922...
(using your own ID of course). Though, for more information about this process, please consult OpenPGP.org.
Conclusion (But Not Really)
Wrapping up, I understand I glossed over a lot of things. This is a high level overview to get you started and going in the right direction for secure and verifiable communication with other people. While I can't easily explain the math and science behind encryption I can assure you that apart from random guessing, it is infeasible for someone to crack a 4096 bit RSA key. You should feel reasonably secure simply due to mathematics, that no one (except the government in 10-30 years when they get better quantum computers) can crack your encrypted messages, or falsify your digital signature. And remember, with public keys and signatures, it's not the name that proves it, it's the key ID. I can make a key with your name, but it's going to be a different key. As a matter of practice you should exchange public keys with people in person so they can verify you're receiving the right one.
At this point I think you're ready to get going, but you probably still have some additional questions. I understand this guide is not all encompassing and that you may have gotten stuck at certain points, but I encourage you to reach out or look into these things on your own, because its well worth the effort. The setup can be hard but once you've got a solid workflow it should prove quite simple. Now, I have some more tidbits to say, but if you're pressed for time this is the place to stop, otherwise if you're ready, keep reading.
Additional Info
I imagine many are thinking "this is neat and all, but typing these commands with my key ID every time is cumbersome, even with copy and paste - is there some way to automate this?" Yes! Well, sort of. There are a few ways to go about this, and I recommend everyone learns basic command line operation, but for simplicity here, let me demonstrate how you can make this easier in MacOS and Linux. before running GPG commands, type keyid=...
(replace ...
with the recipient's ID). Now, if you want to encrypt, you can just type gpg --encrypt --armor --recipient $keyid
. This will fill in $keyid
with the value you specified, and you can keep using this variable with multiple commands.
Also "where are my encrypted/decrypted files stored" or "gpg says it file not found". This part requires you to learn about your computer a bit more. Remember, these are translatable skills/knowledge to all domains of computing, not just using gpg. If you don't already have a basic understanding of files and folders (directories) you need to get familiar with this model as all computers operate this way. If you click "save" in Microsoft Word and have no idea where your document is, you don't know anything about computers. Not to be passive aggressive on this point, but tech literacy is extremely low compared to 20 years ago, despite tech being more prevalent in our lives, and these basic, foundational concepts are becoming lost with the newer generations. If you don't use computers that's fine, but if that were the case you probably wouldn't be reading this to begin with :slight_smile:. When you open your terminal, you are inside a certain directory, just like when you open your file browser (Finder, Explorer, etc), and to access files you need to either know where they are, or be in the same directory. For example if you download a file in Google Chrome on macOS it goes to your Downloads folder. But where is that? By default in your shell you can just type cd Downloads
to "change directory" into your Downloads folder. But that only works because you were already one directory up from that. Rather than me explain this however, read something like this: https://swcarpentry.github.io/shell-novice/02-filedir.html.
How can we make this more secure? Well one aspect involves using additional keys. Basically you have a master key which authorizes your sub keys, and the subkeys are what you use in your day to day life. If one of those subkeys gets compromised (or just expires) you can issue a new one with the master key. It's easier to get people to update their copy of your public key since its still tied to that master (or certify) key. This system also works best when your master key is not stored on your machine. Always assume people can access your machine, and this gives you a much better mindset for security. To make this even better, store your private sub keys on a special device, such as a Yubikey. I briefly eluded to quantum computers earlier, and that's because quantum computers can and already have broken the RSA algorithm. However, they've only broken up to 100 or so bits. And these are state of the art quantum computers operated by the China government. It's going to be at least a few years before they break 4096, if not a decade or more. So in one sense, you shouldn't use RSA anymore because the government can store your encrypted files now and decrypt them later, but on the other hand you're probably not worried about that yet. If this does concern you though (which is understandable), look into quantum resistant encryption. I don't know if there are any quantum resistant encryption algorithms supported by GPG yet.
When I set this stuff up a while ago, it was based on the following guide which I highly recommend, though it's much more in-depth: https://github.com/drduh/YubiKey-Guide.
One more thing I want to touch on is using your PGP keys on other systems. I will not detail how to acquire your private key as people are prone to unsafe methods of copying data (i.e. copying your private key to your system clipboard, or sending it to yourself in an e-mail of all things), though I'll certainly demonstrate this on a live video for someone. However, if you're able to figure out a secure way to do that, there are other ways to use your key. For example, if you have an Android phone you can use OpenKeychain to do all these same actions we've discussed, and with a graphical interface to boot. And if you want a graphical interface on your computer, I found this software, which I've not yet tested thoroughly but appears to be decent, called GpgFrontend.