Public key encryption using gpg

Public key, also known as asymmetric encryption involves two keys i.e. public key and private key. It helps two parties to communicate with each other in a much secure way.

The whole process can be described as follows:
Adam wants to send a secret message to his friend Eve. Both have generated keys in their machines using the command gpg --gen-key. So Both have a set of “public key and private key”. In order to securely send the message, Adam will need Eve‘s public key. Why? To encrypt the message with this public key. This encrypted message can be decrypted only with the private key of Eve. Adam is safe to send this encrypted message via the internet because it is nearly impossible for anyone to decrypt this message provided the private key of Eve is not compromised.

List and generate keys

Go to your terminal and type gpg --list-keys. This will print all keys in your keyring. This list includes your own keys(if already generated) and all imported keys.

gpg --gen-key – We can use this to generate a public-private key pair. It will ask some questions like name, email, etc.

Exporting and importing keys

We can export our public key(Private key is supposed to be with you only and not to be distributed) to a file using gpg’s export option like so:

gpg --armor --output my-public-key.gpg --export my-email-id@domain.com

The armor flag is optional, it just outputs the file in ASCII armored/ normal text format.

The output flag is necessary here. If not mentioned then our key will be output to the standard output rather than to a file.

Now we can distribute the file my-public-key.gpg to other people, and they can import this key in their key-ring. After importing they can see our public key when hitting the command gpg --list-keys on their machine.

Note1: If we want to export anyone else’s public key, then we will need to replace my-email-id@domain.com with their corresponding email id.

Note2: Email id is used to identify the keys, we can also use public key id instead of email id. Public key id can be extracted from the fingerprint of the public key. gpg --list-keys shows a long text something like ET99B6FEEG1704H6A86VD9MC9A77225Q43590LD6, this is the fingerprint of the public key. The last eight characters is the public key id.

A public key can be imported using gpg’s import option. For example in the above case, people can import our public key using gpg’s import option and mentioning the file that we have distributed i.e. my-public-key.gpg
gpg --import my-public-key.gpg
# this will add a new public key in the key-ring.

Encrypting a file or a message using gpg

gpg --encrypt --recipient example@example.com myfile.csv
# file myfile.csv.gpg will get generated

or gpg --output encryptedfile.gpg --encrypt --recipient example@example.com myfile.csv
# file encryptedfile.gpg will get generated because of output flag

Assumptions:
– The file myfile.csv exists in your current directory
– We have already imported the public key of the person whose email id is example@example.com

This will encrypt the file myfile.csv using the public key of person example@example.com and output a new file myfile.csv.gpg. Now this file myfile.csv.gpg can only be decrypted by the person example@example.com. Why? … because we encrypted the file using his public key and only he has the corresponding private key which can decrypt the encrypted file.--recipient option means that you want to encrypt our message/ file for the person whose email id comes after --recipient. In this case, the recipient is example@example.com

Decrypting a file or a message using gpg

gpg --decrypt encrypted-file.gpg
# this will display our decrypted file contents to standard output screen
gpg --output my-decrypted-file --decrypt encrypted-file.gpg
# this will create a new file my-decrypted-file holding the decrypted content

Signing and verifying signatures in gpg

We know that in gpg, we can encrypt a file using a public key and then it can be decrypted using the corresponding private key. However, we can do it in the opposite way also i.e. we can encrypt a file using a private key and then it can be decrypted using the corresponding public key. This is known as signing. Signing is not same as encryption.

When we encrypt a file using a public key, nobody can decrypt except the recipient(only recipient has the private key). That means encrypting a file using a public key assures that file is meant for someone(recipient).

When we sign a file using our private key, everybody can decrypt(decrypt here means verify the signature) the file because all those who have our public key can do it. That means signing a file using our private key assures that the file came from us(if not then our private key is compromised)

gpg --sign myfile.csv
# this will output a new myfile.csv.gpg which holds both the original file and the signature

gpg --output signed-file.gpg --sign myfile.csv
# this will create a new file signed-file.gpg signed by our private key

Note: we don’t need to mention our private key in the above command, gpg will automatically use our private key(assuming we already have generated the public-private key pair).

Now the file signed-file.gpg is a signed file, we can send it to our friend through the internet. If our friend is able to verify the file using our public key, then it assures that the file came from us because we signed the file with our private key and we know that only our public key can decrypt/ verify it.

gpg --verify signed-file
# if the file is really from us, then our friend will get an output of something like gpg: Good signature

We can also use decrypt option instead of --verify to verify signatures
gpg --decrypt singed-file
# this will verify the file, decrypt it and display the original contents of the file to our standard output.

gpg --output decrypted-file --decrypt singed-file
# this will verify the file, decrypt and create a new file decrypted-file holding the original contents

The decrypt flag works like this:
– If the file has no signature, it will just decrypt the file.
– If it has a signature but we don’t have the public key, it will decrypt the file but it fail to verify the signature.
– If it has a signature and we have the public key, it will decrypt and verify.

Signing and encrypting a file

We learnt how to encrypt a file and sign a file. How about sending a secret file/ message in a more secure and trusted way? Encryption ensures that nobody spies on our secret message. Signing ensures that the secret file is indeed from us. Having both i.e. signing and encrypting a file ensures that the secret file has not been spied upon and it is indeed from us!

gpg --output signed-encrypted-file.gpg --sign --encrypt --recipient example@example.com my-file.csv
# outputs a new filesigned-encrypted-file.gpg

The above command will first sign the file with our private key and then encrypt the signed file with the recipient’s public key.

Note: The order of sign and encrypt flag doesn’t matter. gpg will always sign and then encrypt the file

This file can be then verified and decrypted with a single command like this:
gpg --output decrypted-file --decrypt signed-encrypted-file.gpg

Leave a Reply