If you want to exchange encrypted data with other parties, then a main concern should be how to exchange encryption keys safely. Safe key exchange is a property of Public Key Cryptography (PKC) combined with either Direct Trust or Web Of Trust.
GnuPG is a general tool for using PKC to encrypt any type of data, for instance you could encrypt a file and attach it to an email. The receiver then decrypts it also using the GnuPG tool.
In this post we will focus on hands-on encryption with the GnuPG command line tool and not so much on how to establish trust in public keys although it will get a brief mention.
But first let's cover a little background on hybrid ciphers and public-private keys.
PKC is known as an asymmetric cipher because it relies on two keys, a public key for encryption and a private key for decryption, as opposed to symmetric ciphers that rely on just one secret key for both encryption and decryption.
PKC is almost always used in a hybrid with a symmetric cipher, as is also the case in the GnuPG tool, because PKC can only encrypt a short message in the order of the size of the public key itself and it's slow.
The secret key used for the symmetric cipher is generated automatically and is only used once for the specific data you want to encrypt, which is why it is also known as a session key. The session key itself is short enough to be encrypted with PKC.
So first the data is encrypted using a session key and then the session key itself is encrypted using PKC. In the GnuPG tool this is a single operation, so you never have to concern yourself with the session key, just the public and private keys of PKC.
PKC keys come in pairs consisting of a public key and a private key.
The most fundamental feature of such a key pair is that data encrypted with the public key can only be decrypted with the private key.
The public and private key are related in such a way, that the public key can be calculated trivially from the private key, but not vice versa. Brute force guessing the private key from the public key should ideally require infinite computing resources.
As the name suggests the public key can be shared with anyone. You could for instance share your public key with a friend by email. Once in possession of your public key, your friend can now use it to encrypt a file and send it to you by email. The file is then decrypted by you using your private key.
Email is an inherently unsafe channel of communication and someone could have intercepted both your public key and the encrypted file - but no harm done. Without the private key the intercepted material cannot be decrypted.
Let's see how this works hands-on with GnuPG on Ubuntu.
Ubuntu life is easy:
sudo apt-get install gnupg
First let's create your personal key pair. GnuPG will take you through a number of steps to set it up.
Select the key type (1) RSA and RSA.
Please select what kind of key you want:
(1) RSA and RSA (default)
(2) DSA and Elgamal
(3) DSA (sign only)
(4) RSA (sign only)
Your selection? 1
A keysize of 2048 bits is still considered adequate, and if you some day wish to move your key to a safer storage, such as a OpenPGP smartcard, then the card may have a max size of 2048 bits, so let's stay with that for now.
What keysize do you want? (2048) 2048
Understanding expiration periods is difficult without understanding the concept of a primary key and its subkeys, which I will introduce in another post. For now just create the key without an expiration period, it can be changed later on.
Please specify how long the key should be valid.
0 = key does not expire
<n> d = key expires in n days
<n> w = key expires in n weeks
<n> m = key expires in n months
<n> y = key expires in n years
Key is valid for? (0) 0
Your friends will import your public key into their keyring and when they want to use the key they identify it by name, email and a comment. Make sure these uniquely identify who you are.
Real name: Bob
Email address: email@example.com
Comment: Aka bobmeister
The passphrase is critically important because it protects your private key. GnuPG maintains two keyrings, one for public keys and one for private keys. Whenever you use a private key to decrypt something, GnuPG will prompt you for the passphrase.
Chose a passphrase of 3 to 5 random words. They should be random in the sense that one should not be able to find this sequence of words in any book. Google "random passphrase generator" if you need help to generate something random.
Enter passphrase: WarmWilly-WANKA2wants&warts
When you are through, the keys are stored in a public and private keyring file under ~/.gnupg:
drwx------ 2 bob bob 4096 jul 5 14:08 ./
drwxr-xr-x 100 bob bob 4096 jul 5 09:35 ../
-rw------- 1 bob bob 9398 mar 26 20:44 gpg.conf
-rw------- 1 bob bob 3707 jul 5 13:56 pubring.gpg
-rw------- 1 bob bob 2577 jul 5 13:34 secring.gpg
-rw------- 1 bob bob 1360 jul 5 13:56 trustdb.gpg
Now that you have a key pair let's start out with a simple scenario - to encrypt a file that only you can decrypt.
The -e option names the file to encrypt and the -o option the encrypted output file. The -r option tells GnuPG who the recipient is. Encryption is performed with the recipient's public key. Choose yourself as recipient (in this scenario that's you Bob!).
Bob> echo "secret message" > message.txt Bob> gpg -o message.encrypted -r firstname.lastname@example.org -e message.txt
Using the email address to select the associated key is a general pattern when using GnuPG. If you can't remember the email address of a public key, then list the keys in your public keyring with this command:
Bob> gpg -k
Use the -d option to decrypt the file using your private key:
Bob> gpg -o message.txt -d message.encrypted
The new message.txt file should contain the same unencrypted message we started out with.
Notice that we didn't specify which key to use for decryption. The key is already identified by information stored in the encrypted file.
This completes the first scenario.
In this next scenario we encrypt a file that only your friend Joe can decrypt.
First Joe exports his public key to a file and sends it to you:
Joe> gpg -o joespublickey.asc --export -a email@example.com
You import his public key into your keyring:
Bob> gpg --import joespublickey.asc
Someone may have substituted Joe's public key for their own while it was in transit to you. To verify that it is actually his key, you list the fingerprint of the key, call him on the phone and read the fingerprint aloud.
Bob> gpg --fingerprint firstname.lastname@example.org
pub 2048R/675F7FA8 2015-03-25
Key fingerprint = BD9F 2FB3 91B0 D6CA 97EF 957F 9C15 570B 675E 7FA7
uid Bob <email@example.com>
sub 2048R/7A11F3A0 2015-03-25
If he agrees that it is indeed his key, then sign his key with your own private key to make it trusted. Note you can skip this step but GnuPG will warn you that his key is not trusted when you use it.
Bob> gpg --sign-key firstname.lastname@example.org
Encrypt a file with his public key:
Bob> echo "secret message to joe" > message.txt Bob> gpg -o message.encrypted -r email@example.com -e message.txt
Send the encrypted file to Joe who can now decrypt it using his own private key:
Joe> gpg -o message.txt -d message.encrypted
Backup all the files stored in the ~/.gnupg folder. Although the private keyring is already protected by a passphrase, you could add another layer of security, by storing the backup on an encrypted USB flash drive.
Having the private key stored on the day-to-day machine poses a risk that the key might be stolen. A hacker could break into your machine, copy the private keyring and steal your passphrase with a keylogger.
To further secure the private key we can move it off the harddisk onto a OpenGPG Smartcard or a OpenPGP USB device such as the Nitrokey Pro. Once stored on the device, the private key can still be used, but no longer copied.
The security of PKC depends on how well we manage keys.
Without access to the private key an adversary cannot decrypt anything. But if the adversary can trick us into using the adversary's own public key instead of our friends correct public key, then the adversary wins. That is why trust in public keys is a hot topic.
In a previous section we verified the public key received from a friend by calling him to check the key's fingerprint. This is known as Direct Trust and it works perfectly fine for a small group of people who know each other directly.
We used two modes of communication when the public key was exchanged, the email that carried the public key and a phone call to check the fingerprint of the public key. It is unlikely that an adversary can control both. Our friend could also publish the fingerprint somewhere online.
However Direct Trust does not scale to large groups of people. Instead we can use the Web of Trust whereby trust is propagated through third party. When you download a public key of a person you do not directly know, you can still put some trust in the key if it has been signed by someone else that you do trust.
Web Of Trust is not covered in this post, but we did see the initial step when we signed our friends public key in the last scenario. The next step would be to share it at large by uploading it to a keyserver.