🔐 How to verify a signed email with GPG
I recently received an email from a friend that contained an attached PGP signature (.asc file). I was intrigued about how to verify whether the signature was valid or not, so I started digging into this topic.
Apparently there are many different ways of integrating PGP signatures directly into your email client. For example:
- Thunderbird + Enigmail
- Some Chrome extensions for Gmail (FlowCrypt, Mailvelope, etc)
- GPG Mail (https://gpgtools.org/)
But, I wanted to do it “the hard way”. Simply downloading the email .eml file, downloading the signature (.asc file) and using the plain GPG cli to verify it. This is a short summary of what I did.
Import my friend’s public key into my PGP keyring
If the email is signed, that means my friend has a set of PGP public/secret keys that he used when he sent the email. Normally, he will use his secret key to generate the signature and anybody holding his public key will be able to verify his signatures. Public PGP keys are usually published in personal websites, services like Keybase, or simply shared per-to-per between persons. For example, you can get my public GPG key in my Keybase profile, or in Github.
Once you get the public key, importing it into your keyring is as simple as running this command:
$ curl https://keybase.io/martinzugnoni/pgp_keys.asc | gpg — import
Of course, I used my friend’s public key instead. But, you get the point. Now, the GPG cli is able to verify any signature that was generated with the secret key associated to the recently imported public key.
Download .eml and .asc files
I was using Gmail, and downloading both the signature and .eml file was pretty straightforward. See screenshots below.
The .eml file contains a bunch of headers and metadata at the beginning, followed by the actual email content and the PGP signature at the bottom.
What is actually required to verify the signature is the email content, because the signature was generated based on that. You will notice a section delimited by boundaries like these:
This is an OpenPGP/MIME signed message (RFC 4880 and 3156)
// the email content
I copied all the content within those boundaries into a plain text file called
email.txt that I will later use as data file to validate the signature.
Verify the signature
Once we have the public key imported into our keyring, the
.asc file with the signature and the
email.txt file with the plain email content we should be in shape to check whether the signature is valid or not.
$ gpg — verify signature.asc email.txt
gpg: Signature made Fri May 22 11:18:44 2020 -03
gpg: using RSA key XXXX
gpg: Good signature from “firstname.lastname@example.org” [ultimate]
Signature looks OK!
Now we can be sure that my friend was indeed the person sending that message, and that the message was not tampered by any man in the middle.
Otherwise, we would get an error message similar to these:
gpg: BAD signature from “email@example.com” [ultimate]
Doing all this manual process for every email you receive is very impractical. That’s why direct integrations into your preferred email client is probably a better solution.
In any case, getting used to PGP signatures and the process of sending and receiving signed emails is a very recommendable practice.