Encryption without an App
We are here to discuss public key cryptography, and more specifically, how to encrypt a text file using someone else’s public key. At the time of writing, leveraging this free software is not an illegal act. We’re just using gpg from the Linux shell. Everything you need to know is in the man page.
$ man gnupg
You’ll need a public, private key pair. So let’s generate that now. Make sure gpg or GnuPG as it is sometimes called, is installed on your machine. If you’re using something Arch Linux based (with the pacman package manager, it would be:
$ sudo pacman -S gnupg
Now that you have gpg installed, generate that key-pair from the command line. In your terminal, you can use this to generate your public and private key pairs:
$ gpg --gen-key
You’ll be presented with some options. All the defaults are fine.
— Please select what kind of key you want:
(1) RSA and RSA (default)d
— What keysize do you want?
4096 (because why not)
You’ll see some other options like how long is the key valid for. Then you’ll be asked to enter your name and email.. Of course you can make up a false name and email or use burner account if you like. (This isn’t FaceBook :-) )
— Then you’ll see this message:
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.
This can be a problem if you’re doing this while ssh’d into a remote server that isn’t doing much. You’ll need to generate some entropy somehow. A quick and dirty way to do this would be to figure out what the main partition of your file system is and force your system to read the contents and write the output to nowhere. First to figure out what your partions are called, open up a new terminal window (either locally, or connected to the remote machine you’re working on) and run this command:
# df -h
This will produce results similar to:
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 25G 2.4G 23G 10% /
devtmpfs 474M 0 474M 0% /dev
tmpfs 496M 8.0K 496M 1% /dev/shm
tmpfs 496M 63M 434M 13% /run
tmpfs 496M 0 496M 0% /sys/fs/cgroup
tmpfs 100M 0 100M 0% /run/user/0
Then you can use the dd program to read the contents of the main partition, in this case it’s “/dev/vda1”, and write the contents to “/dev/null” or “/dev/zero”.
Using the above “/dev/vda1” as an example.. (You’re system might be “/dev/sda” or something else).. here is an example of the dd command to run to generate entropy:
$ dd if=/dev/vda1 of=/dev/null
If you selected a large key size above, like 4096 bits instead of 2048 bits, you might have to run this command a few times to generate enough entropy.
If you’re on a local machine (like your laptop), you can probably get away with just using your computer and moving the cursor around. That doesn’t always work for remote servers, thus the aforementioned “dd” approach outlined above.
Now, you need your recipient’s Public Key
Have your friend or colleague export their public key using something like:
$ gpg --armor --export Their Name > person-name-public-key.asc
Instead of “Their Name,” the public key owner’s “key id” or their email address can be used. The idea is that it’s one of those so that their public key can be located and used as the target for export.
“Their Name” is the name given to GnuPG upon creation of a Public/Private key-pair. For me, it would be “Tim Beach.” So to export my public key I would use:
$ gpg --armor --export Tim Beach > tim-beach-public-key.asc
The “ — armor” (dash dash armor) option allows the person exporting to use ASCII armor instead of binary to export their private key. The purpose of this is to not freak out email clients, or Slack, or Google Hangouts, or Whatsapp, or Signal (for Chrome Extension) when passing the public key(s) using some non-private platform as mentioned previously.
And to be extra clear, “.asc” is the format for exporting your public key in ASCII armor.
Let’s import that public key of your recipient, now that we have it!
We should now import the recipient’s public key. Use the file name of the “.asc” file they sent you. I’ll give a command line example of how to import this. In your terminal emulator, navigate to the directory where the received public key was downloaded. From that directory, make sure your file is indeed there and execute a command like:
$ gpg --import name_of_pubkey.asc
You can then optionally confirm some things about this public key. You’ll notice that a name is shown after import. This is the “full name” value that the owner of the public key used when generating it. For me that would be “Tim Beach.” So, in order to edit my public key in your local machine’s gpg key-store, you could use:
$ gpg --edit-key Tim Beach
This will open up at gpg command prompt “gpg>”
From here you can run direct gpg commands like:
gpg> sign
Only use sign if you confirm the primary fingerprint of the public key. If it’s confirmed, by simply asking the sender of the public key, you can cryptographically sign the recipient’s public key with your key, by running “sign” as described above. After executing “sign” in this manner, you’ll be asked for confirmation. After typing “y” to show agreement, you should be prompted to decrypt your private key-store to then cryptographically sign your recipient’s public key… btw, you can type “quit” to exit the “gpg>” prompt. This will ask you if you really want to save your changes. Say “y”
Phew… Now we can asymmetrically encrypt something to send to our recipient.
We’re going to take that text file and asymmetrically encrypt it such that only the recipient can decrypt it on their machine, where their public/private public-key-cryptography gpg key-pair is installed.
Let’s use an example file called “text.txt”
$ gpg --output text.gpg --encrypt --recipient beach.timothy@gmail.com text.txt
To be clear, prior to running this command the file “txt.gpg” did not exist, so don’t think you need to create it ahead of time. Simply take your “text.txt” file and output it as an encrypted blob which is the “text.gpg” file that you can send to your recipient.
You’ll also notice that I used my email address as the recipient. You can use the email address registered to the recipient’s public key, or you can use their username, in my case “Tim Beach”… You can also use the key id, but I like to use the email address which you can verify, after importing someone else’s public key, by running:
$ gpg --list-keys
So now we have “text.gpg” that we can securely send to our recipient. It was asymmetrically encrypted using their public key. Only they can decrypt it, and no secrets were shared between sender and recipient.
Here is the command our recipient would use to decrypt the secret message we encrypted using their cryptographic public key:
$ gpg --output text.txt --decrypt text.gpg
Symmetric Encryption
There’s another angle to consider as well. Let’s say you want to just encrypt a file on a system symmetrically. That means, you get to make up a passphrase that will lock the file you want to encrypt. This way it can live securely on your system and only with the passphrase can the file be unlocked.
Sometimes you want to encrypt a whole directory. There are ways to do that. One way would be to zip a directory and then encrypt it.
To zip a directory called “archive”, you could use:
$ zip -r archive.zip archive
“archive.zip” is the name of the file the output of the zip process will create. This could have been “monkey.zip” as it doesn’t matter. “archive” is the name of the directory itself.
Now let’s delete the archive directory and symmetrically encrypt the zip file:
$ sudo rm -rf archive
Now the original archive directory is gone. Now let’s encrypt the zip file. We’ll specify the encryption algorithm as AES256 so we don’t get the
“gpg: CAST5 encrypted data
gpg: encrypted with 1 passphrase
gpg: WARNING: message was not integrity protected”
warning when we decrypt later.
gpg --output archive.gpg --cipher-algo AES256 --symmetric archive.zip
This will create an encrypted file called archive.gpg. Your orginal archive.zip file is still there. You can “rm -rf archive.zip” so you’re left with only the encrypted archive.gpg. Don’t forget to remove the unencrypted version.
Then to un-encrypt archive.gpg, you could use:
$ gpg --output archive.zip --decrypt archive.gpg
That’s it. Hope this helps someone.
Much Love,
Tim Beach