Background
Almost a decade ago I wrote this article showing how to use PGP to secure your emails. Today I decide to rewrite it, to make it useful in 2025, and to instruct people who might want to encrypt their communication with me but don't know how.
This is a complete rewrite, expect more than just PGP in emails. I will use my own key as an example, feel free to test what you learned with it.
The Core Concept: How PGP Works
Before we dive in, let's understand the main idea. PGP (Pretty Good Privacy) uses a system called "public-key cryptography". This system solves two big problems: privacy (encryption) and authenticity (signing).
It does this by giving you a key pair, which consists of two related digital keys:
- Your Public Key:
- Think of this as a padlock or an open mailbox slot.
- You can give this key to everyone. You can put it on your website, your Twitter bio, or a public keyserver.
- People use your public key to encrypt messages for you. Anyone can "lock" a message with your public key, but only you can unlock it.
-
People also use your public key to verify your digital signature.
-
Your Secret Key (or Private Key):
- Think of this as the one and only key that opens your padlock or your mailbox.
- You must NEVER share this key with anyone. It's protected by a strong passphrase that you will create.
- You use your secret key to decrypt messages that were encrypted with your public key.
- You also use your secret key to digitally sign messages, proving they came from you.
In summary:
- To Encrypt (Privacy): You get your friend's public key and use it to lock a message. Only your friend can unlock it with their secret key.
- To Sign (Authenticity): You use your secret key to create a unique signature for a message. Anyone can use your public key to check that the signature is valid and that the message hasn't been changed.
Install GnuPG
GnuPG (Gnu Privacy Guard) is the most popular, free, and open-source software implementation of PGP.
Linux
Typically gpg is pre-installed since most package managers depend on it. You can check your version:
~
❯ gpg --version
gpg (GnuPG) 2.4.0
libgcrypt 1.10.2-unknown
...
If your gpg version is old or not present, follow your distro's documentation to install or upgrade it (e.g., sudo apt install gnupg or sudo dnf install gnupg).
Windows
Install the complete Gpg4win suite, which includes GnuPG and helpful tools.
MacOS
Install GPG Tools (also known as Mac GPG).
How to Use GPG
Generate Your Keypair
First, you need to create your own public and secret keypair.
~
❯ gpg --full-generate-key
This command will walk you through a few questions. The default options are modern, secure, and highly recommended.
- Please select what kind of key you want:
-
Choose
(9) ECC (sign and encrypt) *default*. This is a modern and fast elliptic-curve key. -
Please select which elliptic curve you want:
-
Choose
(1) Curve 25519 *default*. This is a fast, secure, and modern curve. -
Please specify how long the key should be valid:
0 = key does not expireis the simplest option.-
If you choose an expiration (like
1yfor one year), you will need to remember to extend it later. For beginners,0(no expiration) is fine. -
Key is valid for? (0)
0 -
Is this correct? (y/N)y -
GnuPG needs to construct a user ID to identify your key.
- Real name: Enter your name (e.g.,
jm33-test). - Email address: Enter the email you'll use this key with (e.g.,
jm33.me@gmail.com). - Comment: Optional (e.g.,
Demo). - You'll see a User-ID like:
"jm33-test (Demo) <jm33.me@gmail.com>". -
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
-
Create a Passphrase:
- You will be prompted to enter a passphrase. This is critically important.
- This passphrase is the only thing protecting your secret key. If someone steals your key file, they can't use it without this passphrase.
- Make it long, strong, and memorable. Do not forget it.
GPG will then generate your keys. It might ask you to move your mouse or type on the keyboard to generate "entropy" (randomness).
...
public and secret key created and signed.
pub ed25519 2023-06-04 [SC]
00416191C169BCF410712173E9FAF7E43E456E68
uid jm33-test (Demo) <jm33.me@gmail.com>
sub cv25519 2023-06-04 [E]
The long string 00416191C169BCF410712173E9FAF7E43E456E68 is your key's fingerprint. This is a unique ID for your key.
You can view it again at any time:
❯ gpg --fingerprint jm33.me@gmail.com
pub ed25519 2023-06-04 [SC]
0041 6191 C169 BCF4 1071 2173 E9FA F7E4 3E45 6E68
uid [ultimate] jm33-test (Demo) <jm33.me@gmail.com>
sub cv25519 2023-06-04 [E]
Share Your Public Key
Now that you have a key, you need to let people get your public key so they can send you encrypted messages.
Option 1: Send the key as a file (Recommended)
You can "export" your public key to a file and email it, host it on your website, or send it via chat.
# This exports your public key (identified by your email) to a file named "my-key.asc"
gpg --export --armor --output my-key.asc jm33.me@gmail.com
You can then send my-key.asc to your contacts.
Option 2: Use a Keyserver
A keyserver is like a public phone book for PGP keys.
# Upload your key (using its fingerprint) to a public server
gpg --keyserver hkps://keyserver.ubuntu.com --send-key 00416191C169BCF410712173E9FAF7E43E456E68
Warning: Be aware that uploading to a public keyserver is permanent. You cannot delete it.
Obtain and Trust a Recipient's Public Key
To send an encrypted message to someone, you first need their public key.
Step 1: Get the Key
- From a file: If they sent you their
key.ascfile, you just import it:
bash
gpg --import key.asc
- From a keyserver: If you know their key's fingerprint or ID, you can download it:
bash
# Replace the fingerprint with your recipient's
gpg --keyserver hkps://keyserver.ubuntu.com --recv-key 00416191C169BCF410712173E9FAF7E43E456E68
Step 2: Verify the Key (CRUCIAL)
How do you know the key you just downloaded actually belongs to your friend? An attacker could have uploaded a fake key to a keyserver.
You must verify the fingerprint "out-of-band" (meaning, through a different channel).
- Ask
gpgto show you the fingerprint of the key you just imported:
bash
gpg --fingerprint user@example.com
- Call your friend, text them, or meet them in person and ask them, "What is your PGP key's fingerprint?"
- Compare what they tell you with what you see on your screen. If they match exactly, you have the right key.
Step 3: Trust the Key
Once you've verified the key, you need to tell GPG that you trust it. This is done by "signing" their key with your own secret key. This is like making a note in your system that says "I've checked this, and it's legit."
# Start the key-editing process
gpg --edit-key user@example.com
# In the GPG prompt, type:
gpg> fpr
# (This shows the fingerprint again, just to be sure)
gpg> sign
# (This signs their key with your secret key. You'll be asked for your passphrase)
gpg> trust
# (It will ask you how much you trust them. Choose '5' for 'ultimate' if it's your key, or '3' for 'full' if you've personally verified it.)
gpg> quit
# (This saves your changes and exits)
Now you are ready to send them encrypted messages.
Clear Sign: Sign clear-text messages
Sometimes you don't need to hide a message, but you want to prove it came from you and wasn't changed. This is "signing". A "clear-signed" message leaves the text readable.
How to create it
# This creates a file 'cleartext.txt.asc'
gpg --clear-sign -u 9CF295D2 cleartext.txt
-u(or--local-user) specifies which of your secret keys to use for signing (in case you have more than one).
How to verify it
Save the signed message (including the -----BEGIN PGP SIGNED MESSAGE----- and -----BEGIN PGP SIGNATURE----- blocks) as signed_msg.txt and run:
❯ gpg --decrypt signed_msg.txt
You can fetch my latest public key from keyserver...
...
gpg: Signature made Wed 31 May 2023 11:43:18 AM CST
gpg: using EDDSA key 739673C5A6C3797A12986FFF410C99D49CF295D2
gpg: Good signature from "jm33@jm33.me <jm33@jm33.me>" [ultimate]
The message gpg: Good signature tells you two things:
- The signature is valid and belongs to the key
...410C99D49CF295D2. - The message content has not been tampered with since it was signed.
How does this work?
It's not "encrypting with the secret key," which is a common confusion. Here's what really happens:
- Hash: GPG creates a short, unique digital summary of your message (called a "hash", e.g., SHA256).
- Sign: GPG then uses your secret key to encrypt only that hash. This encrypted hash is your digital signature.
- Verify: When your recipient verifies the message:
- Their GPG client uses your public key to decrypt the signature, revealing the original hash you made.
- It then calculates its own hash of the message text it received.
- It compares the two hashes. If they match, the signature is "good".
Encrypt Data with PGP
Symmetric Encryption (Password-Only)
This is a simple way to encrypt a file with just a password. It doesn't use any keypairs. This is useful for encrypting a file for yourself or for someone you can securely share a password with.
# Encrypts 'data.bin' to 'data.bin.gpg'
# It will ask you to create a passphrase for this file
gpg -c data.bin
# Decrypts 'data.bin.gpg' to a new file
# It will ask for the passphrase you created
gpg -d data.bin.gpg > decrypted.bin
Asymmetric Encryption (To a Recipient)
This is the main use case. You encrypt a file so that only your recipient can open it.
# Encrypt 'msg.txt' for the recipient with fingerprint ...3E456E68
# AND sign it with your own key (...410C99D49CF295D2)
❯ gpg --encrypt --recipient 00416191C169BCF410712173E9FAF7E43E456E68 --sign -u 410C99D49CF295D2 msg.txt
This creates msg.txt.gpg.
--encrypt: Tells GPG to encrypt.--recipient: Tells GPG who to encrypt for (using their public key).--sign: Tells GPG to also sign the message with your secret key, so they know it's from you.-u: (or--local-user) Specifies your secret key to use for the signature.
Pro-tip: When you encrypt a file, you are encrypting it for someone else's public key. This means even you can't decrypt it unless you also add yourself as a recipient.
# To encrypt for a recipient AND for yourself:
gpg --encrypt --recipient RECIPIENT_ID --recipient-self --sign -u YOUR_KEY_ID msg.txt
--recipient-selfis a handy shortcut to add your own key from the-uflag as a recipient.
To decrypt and verify: The recipient just needs to run:
❯ gpg --decrypt msg.txt.gpg
...
(The original message content is displayed)
...
gpg: Signature made Sun 04 Jun 2023 07:42:23 PM CST
gpg: using EDDSA key 739673C5A6C3797A12986FFF410C99D49CF295D2
gpg: Good signature from "jm33@jm33.me <jm33@jm33.me>" [ultimate]
GPG automatically uses their secret key to decrypt the file and verifies the signature with your public key.
Thunderbird and PGP
The Thunderbird email client has excellent, built-in OpenPGP support.
First, you need to export your secret key from GPG on your command line so you can import it into Thunderbird.
# Export your secret key (identified by its fingerprint or email) to a file
gpg --export-secret-keys -a 00416191C169BCF410712173E9FAF7E43E456E68 > my-secret-key.asc
Treat this my-secret-key.asc file as securely as a password!
Now, in Thunderbird:
- Assuming you have already configured your email account, click the
≡menu button. - Go to
Account Settings. - Select your email account from the left-hand menu.
- Click on
End-to-End Encryption. - Under the "OpenPGP" section, click
Add Key.... - Choose
Import an existing OpenPGP Keyand clickContinue. - Select the
my-secret-key.ascfile you just exported. - Thunderbird will ask for the passphrase you created when you generated the key.
- After importing, you must select the key to actively use with your account. While still in the
End-to-End Encryptionsettings, select your newly imported key under "Use this OpenPGP key for this account".
Now, when you compose a new email, you will see an "Encryption" or "Security" button where you can choose to sign and/or encrypt the message. Thunderbird will automatically fetch the public keys of your recipients if they are on a keyserver or attached to an email you received from them.
Example: Sending an Encrypted Email to Me (jm33@jm33.me)
Here is my own PGP key information, which I've signed to prove it's authentic. You can find this block at https://jm33.me/pages/gpg.html.
Let's use this as a real-world example to tie everything together.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
You can fetch my public key from Ubuntu key server:
gpg --keyserver hkps://keyserver.ubuntu.com --recv-key 5BEF5813ACA297CEA6F74C32FD7899D296E6FCE2
To verify:
gpg --fingerprint 5BEF5813ACA297CEA6F74C32FD7899D296E6FCE2
You should see:
pub ed25519 2025-09-21 [SC] [expires: 2028-09-21]
5BEF 5813 ACA2 97CE A6F7 4C32 FD78 99D2 96E6 FCE2
uid [ full ] Jimmy Mi <jm33@jm33.me>
sub cv25519 2025-09-21 [E] [expires: 2028-09-21]
The following keys are also in use:
ProtonMail key
739673C5A6C3797A12986FFF410C99D49CF295D2
Git commits
A914BB005F8A42F36C2997594876EC6D60BDB1DF
6D15BC0F5325CFD19E54568E8F97F3B56FB4E276
You can fetch them using gpg with the same command above, just replace the key fingerprint.
Use ProtonMail key for emails, if you have concerns, encrypt with 5BEF5813ACA297CEA6F74C32FD7899D296E6FCE2.
Sign my key to trust it:
gpg --sign-key 5BEF5813ACA297CEA6F74C32FD7899D296E6FCE2
To upload the signed key to Ubuntu key server:
gpg --keyserver hkps://keyserver.ubuntu.com --send-key 5BEF5813ACA297CEA6F74C32FD7899D296E6FCE2
Thanks in advance if you decide to sign my key!
-----BEGIN PGP SIGNATURE-----
iHUEARYKAB0WIQRb71gTrKKXzqb3TDL9eJnSlub84gUCaM9z1AAKCRD9eJnSlub8
4ptvAQDGtjM89OF2/eWcG33uF1Xd+8/B7ZGtZW1niAyosAuD/AEAj3Z03wIGNHCu
ipG9AZU/ZSTmhICZYqByOBQwlkHPjAA=
=lOHt
-----END PGP SIGNATURE-----
So, how would you use this to send me an encrypted email? Here's the step-by-step process:
Step 1. Verify the Message (Optional, but good practice)
First, you can verify that this message block itself is authentic.
Save the entire block above to a file named jimmy_key.txt.
Then run:
gpg --decrypt jimmy_key.txt
If you have already imported my key (5BEF...FCE2), GPG will check the signature and report gpg: Good signature from "Jimmy Mi <jm33@jm33.me>". This proves the instructions weren't tampered with.
Step 2. Get My Public Key for Email
The instructions say: "Use ProtonMail key for emails". This is the key I prefer for email correspondence.
The fingerprint for that key is: 7396...95D2.
Let's import this key from the keyserver:
gpg --keyserver hkps://keyserver.ubuntu.com --recv-key 739673C5A6C3797A12986FFF410C99D49CF295D2
Step 3. Verify and Trust My Key
Now that you have the key, you must verify it (as described in the "Obtain and Trust" section).
gpg --fingerprint 739673C5A6C3797A12986FFF410C99D49CF295D2
You would check this fingerprint against a trusted source (like my GitHub or Twitter bio). Once you're sure it's me, sign my key to tell your GPG you trust it:
# Start the key editor
gpg --edit-key 739673C5A6C3797A12986FFF410C99D49CF295D2
# In the GPG prompt:
gpg> sign # Sign the key
gpg> trust # Set trust level (e.g., '3' for 'full')
gpg> quit # Save and quit
Step 4. Write and Encrypt Your Email
Now you're ready!
- Write your message in a plain text file, let's call it
my_secret_message.txt.
bash
echo "Hello Jimmy, this is a secret message just for you." > my_secret_message.txt
- Encrypt it for me (using my key) and sign it (using your key) so I know it's from you.
bash
# Replace 'YOUR_KEY_FINGERPRINT' with your own key's fingerprint or email
gpg --encrypt --recipient 739673C5A6C3797A12986FFF410C99D49CF295D2 \
--sign --local-user 'YOUR_KEY_FINGERPRINT' \
my_secret_message.txt
This creates my_secret_message.txt.gpg. This .gpg file is what you attach to an email and send to me at jm33@jm33.me. Only I will be able to decrypt it.
If you're using Thunderbird, this process is even easier. After importing my key, just click the "Encrypt" button before sending your email, and Thunderbird will handle all this for you.
Comments
comments powered by Disqus