What is GPG / PGP and how do I use it?

What is GPG / PGP

GnuPG (more commonly known as GPG) is an implementation of a standard known as PGP (Pretty Good Privacy). It uses a system of "public" and "private" keys for the encryption and signing of messages or data.

Understanding public vs. private keys

Private keys are the first half of a GPG key which is used to decrypt messages that are encrypted using the public key, as well as signing messages - a technique used to prove that you own the key. As the name implies, this part of the key should never be shared.

Public keys are the second half of a key which is used to encrypt messages for the owner of the private key. As the name implies, this part of the key is safe to give out to the public, as it can only be used to encrypt messages or data for the private key owner.

You can download GnuPG (including graphical versions for those uncomfortable with command line) for various platforms, including Windows and macOS / OSX from the GnuPG Website.

On most Linux distributions, GnuPG is included by default as the command line utility gpg, or is available in your package manager.

For our usage examples, we only cover the command line version of GPG. If you're using a GUI version, you should be able to find guides online on how to use them.


Looking to buy a Virtual or Dedicated server? Do you like privacy and low prices? Try Privex!

We have virtual servers starting from just US$0.99/mo, and dedicated servers starting from as low as US$50/mo

Unlike other hosts, we don't ask for any personal details - only a name (can be an alias / username), and an e-mail address so we can send you your server details and renewal invoices.

We also accept several different cryptocurrencies with our own in-house payment processor - no third parties involved in processing your payments.

At the time of writing, we currently accept: Bitcoin (BTC), Litecoin (LTC), Monero (XMR), Dogecoin (DOGE), HIVE, and HBD

Order a server TODAY! Privacy is affordable™


Generating a key pair and exporting the public key

To use GPG to send and receive messages securely, first you must generate a key pair.

gpg --generate-key

NOTE: If you want to be able to add a comment to the key, change the bit size (e.g. RSA 2048 or 4096) or algo, or other extra key options you might wish to adjust, you should use gpg --full-generate-key instead:

gpg --full-generate-key

After creating a key pair, you'll want to export the public key to share with others.

# List the keys you own (have the private key for)
$ gpg -K --fingerprint
sec   rsa4096 2019-03-02 [SC] [expires: 2021-03-01]
    9ECF 1199 8AD7 A743 7353  BC57 0E66 E4DE A98A 4921
uid           [ultimate] John Doe <[email protected]>
ssb   rsa4096 2019-03-02 [E] [expires: 2021-03-01]

# Take the last 8 characters of that string of random letters and numbers and remove the space
$ gpg -a --export A98A4921 > john_doe.asc

In the above example, the public key was exported to john_doe.asc, you should open the file in a text editor such as Notepad, and make sure the first line shows:

-----BEGIN PGP PUBLIC KEY BLOCK-----

This is to make sure you haven't accidentally exported your private key.

Importing a public key from a key server

Next, you'll want to import the public key of the person/organization you want to send and encrypted message to.

The below example imports the Privex Support key (key ID 288D D163 2F6E 8951) from a key server.

gpg --recv-keys 288DD1632F6E8951

DISCLAIMER: The Privex Support key is occasionally rotated. For the latest key fingerprint, you should check the Contact Us page

Change the default key server in your config to prevent issues with --recv-keys

A lot of systems are pre-configured to use unreliable / broken GPG key servers, which can cause problems when using --recv-keys. You can resolve most problems with --recv-keys / --search-keys by adding a reliable key server to your GPG config:

Commands to fix keyserver config

# Ensure your user's .gnupg folder exists, so we can create / append to the config files
mkdir -p ~/.gnupg
# You should probably run this command to set keys.openpgp.org as your
# default keyserver (fastest and most reliable as of Jan 2021)
echo "keyserver hkps://keys.openpgp.org" | tee -a ~/.gnupg/dirmngr.conf | tee -a ~/.gnupg/gpg.conf

Once you've added the keyserver setting to your config, you should now be able to use --recv-keys and --search-keys without issues :)

Retrieve a key from a specific key server for just one command

You can use the --keyserver flag to manually specify a key server to use, which will only be used for that one command. This can be useful if you can't find a key on your default keyserver, and need to temporarily try downloading the key from a different keyserver.

Retrieve 288D D163 2F6E 8951 from keys.openpgp.org

gpg --keyserver hkps://keys.openpgp.org --recv-keys 288DD1632F6E8951

Searching for keys on a key server (e.g. by name or email)

If we search for privex.io on keys.openpgp.org - it'll come back with nothing. This is because keys.openpgp.org does not allow searching by names / domains / comments.

$ gpg --keyserver hkps://keys.openpgp.org --search-keys privex.io

gpg: error searching keyserver: No data
gpg: keyserver search failed: No data

However, if we search for an exact email, it will return results if they're found:

$ gpg --keyserver hkps://keys.openpgp.org --search-keys [email protected]

gpg: data source: https://keys.openpgp.org:443
(1) Privex Support (Shared key by Privex Inc. support team for Jan 2021 to
      4096 bit RSA key 288DD1632F6E8951, created: 2021-01-19
Keys 1-1 of 1 for "[email protected]".  Enter number(s), N)ext, or Q)uit >

If we enter the number 1 and hit enter, then it will import the first key that it found

gpg: key 288DD1632F6E8951: "Privex Support (Shared key by Privex Inc. support team for Jan 2021 to 2023) <[email protected]>" not changed
gpg: Total number processed: 1
gpg:              unchanged: 1

Other keyservers, such as hkps://keyserver.ubuntu.com support searching by name / domain etc. - if we search for privex.io - we can see 4 different keys are available, which you can select and download.

Searching keyserver.ubuntu.com for privex.io:

gpg --keyserver hkps://keyserver.ubuntu.com --search-keys privex.io
gpg: data source: https://162.213.33.8:443
(1) Kale S 
      4096 bit RSA key BED8EFF89F1F7520, created: 2019-01-02
(2) Privex Support (Shared key by Privex Inc. support team for Jan 2021 to
      4096 bit RSA key 288DD1632F6E8951, created: 2021-01-19
(3) Christopher S. (Privex CEO) 
      4096 bit RSA key DDB36F2B55284433, created: 2017-12-02
(4) Privex Inc. Package Signing Key (Privex signing key for DEB / RPM / et
      4096 bit RSA key A07AE80FE77AB97B, created: 2020-11-06
Keys 1-4 of 4 for "privex.io".  Enter number(s), N)ext, or Q)uit >

If we enter the value 1 2 3 4 - it will import the keys 1, 2, 3, and 4:

Keys 1-4 of 4 for "privex.io".  Enter number(s), N)ext, or Q)uit > 1 2 3 4
gpg: key DDB36F2B55284433: public key "Christopher S. (Privex CEO) " imported
gpg: key 288DD1632F6E8951: 2 signatures not checked due to missing keys
gpg: key 288DD1632F6E8951: "Privex Support (Shared key by Privex Inc. support team for Jan 2021 to 2023) " 3 new signatures
gpg: key BED8EFF89F1F7520: 1 signature not checked due to a missing key
gpg: key BED8EFF89F1F7520: public key "Kale S " imported
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   1  signed:   1  trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: depth: 1  valid:   1  signed:   0  trust: 1-, 0q, 0n, 0m, 0f, 0u
gpg: next trustdb check due at 2023-01-19
gpg: Total number processed: 3
gpg:               imported: 2
gpg:         new signatures: 3

Encrypting and sending your message

Now, write your message in a plain text editor such as Notepad (Windows) or Textedit (Mac). You may want to put your public key at the end of the message if you want it to be sent encrypted, otherwise you'll have to send your public key as an attachment or unencrypted text in the message.

Let's assume you saved your message as message.txt. Now let's encrypt it for Privex Support.

gpg -a -r 288DD1632F6E8951 -e message.txt

The above command should've encrypted the file message.txt for the public key with the ID 2E833D27B0E01433 (Privex Support), and outputted the encrypted version as message.txt.asc

Now just open up the .asc file, you should see it starts with

-----BEGIN PGP MESSAGE-----

Simply copy and paste the contents of this file (including the BEGIN and END lines) into an email or other form of message, and make sure you've included your public key in some form - either in the encrypted message, or sent in plain text with the message (e.g. pasted at the end, or attached to an email). Finally, send the message.

Decrypting an encrypted message sent to you

To decrypt a message sent to you, assuming it's saved as reply.txt.asc, simply run the following command, gpg will automatically select the correct private key to decrypt the message and output it to the terminal.

Decrypt an encrypted message

$ gpg -d reply.txt.asc

gpg: encrypted with 4096-bit RSA key, ID 0E66E4DEA98A4921, created 2019-03-02
      "John Doe <[email protected]>"
hello world

You can also pipe the encrypted message into GPG. This is very useful for interacting with the clipboard - e.g. the pbpcopy and pbpaste commands on macOS (you can also setup pbpaste/copy on Linux, by installing some extra packages and adding some aliases)

Piping pbpaste into gpg -d (decrypt)

$ pbpaste | gpg -d
gpg: encrypted with 4096-bit RSA key, ID 0E66E4DEA98A4921, created 2019-03-02
      "John Doe <[email protected]>"
hello world

If you want to save the message / data instead of outputting it to the terminal, use shell redirection.

The below example outputs the message to reply.txt:

$ gpg -d reply.txt.asc > reply.txt

gpg: encrypted with 4096-bit RSA key, ID 0E66E4DEA98A4921, created 2019-03-02
      "John Doe <[email protected]>"

$ cat reply.txt

hello world

Trust a GPG key to stop getting asked whether you're sure you want to use a certain key

By default, GPG will assume imported public keys are unsafe, and will nag you to confirm that you're absolutely certain you want to sign/verify/decrypt/encrypt something for a certain key. For example, if you try to encrypt a message for Privex Support, you'll likely see something like this:

[root@a89afb813068 /]# gpg -r [email protected] -ae hello.txt
gpg: checking the trustdb
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: next trustdb check due at 2023-01-22
gpg: E3069E994C92D942: There is no assurance this key belongs to the named user
sub  rsa4096/E3069E994C92D942 2021-01-19 Privex Support (Shared key by Privex Inc. support team for Jan 2021 to 2023) 
 Primary key fingerprint: 17E8 77C3 5C3E 886A 5232  6C6A 288D D163 2F6E 8951
      Subkey fingerprint: AEBC 3439 6D4B ABE9 818D  0D37 E306 9E99 4C92 D942

It is NOT certain that the key belongs to the person named
in the user ID.  If you *really* know what you are doing,
you may answer the next question with yes.

Use this key anyway? (y/N)

To fix this issue, you need to sign the public key which GPG is complaining about, which acts as a statement to GPG "I, [email protected] [ABCD1234] - am 100% certain that key DE12FABC belongs to the person I believe it does."

Sign the Privex Support key to tell GPG you trust it

gpg --lsign-key 288DD1632F6E8951

Once you run this command, you'll be shown information about the key you're signing, and the default key which GPG will use to sign the key:

pub  rsa4096/288DD1632F6E8951
     created: 2021-01-19  expires: 2023-01-19  usage: SC
     trust: unknown       validity: unknown
 Primary key fingerprint: 17E8 77C3 5C3E 886A 5232  6C6A 288D D163 2F6E 8951

     Privex Support (Shared key by Privex Inc. support team for Jan 2021 to 2023) 

This key is due to expire on 2023-01-19.
Are you sure that you want to sign this key with your
key "John Doe " (9FD64F451078892A)

The signature will be marked as non-exportable.

Really sign? (y/N)

Now, if we try to encrypt a message for Privex Support - GPG won't bother us with an "are you SURE this is the right key?" prompt, and just encrypt the message immediately:

user@host $ gpg -r [email protected] -ae hello.txt
gpg: checking the trustdb
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   1  signed:   1  trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: depth: 1  valid:   1  signed:   0  trust: 1-, 0q, 0n, 0m, 0f, 0u
gpg: next trustdb check due at 2023-01-19

Signing and verifying a file / message to show that you approve a message, or verify the authenticity of a file

Clearsign (GPG signature as part of the file/message)

For signing simple text messages, clearsign is usually used, as they're often intended for humans to read, thus the visible signature won't cause much of an issue

First let's create a file message.txt

hello world
lorem ipsum dolor

this message is from john doe!

Now, we'll sign it with our John Doe key

Sign the file with the [email protected] private key

gpg -u [email protected] -a --clear-sign message.txt

If we now read the file message.txt.asc - we can see both the original message, and the signature:

user@host $ cat message.txt.asc
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

hello world
lorem ipsum dolor

this message is from john doe!
-----BEGIN PGP SIGNATURE-----

iQFFBAEBCAAvFiEEp6Qc+4bcuOcca8Lgn9ZPRRB4iSoFAmAKXEgRHGpvaG5AZXhh
bXBsZS5jb20ACgkQn9ZPRRB4iSoo/Af+JyG6r7FhZKPpaQ+nVu0zv3X+EbEqHGy2
SkBlSu3knbTrDsNmGT3offk7PDdyhtScvCauLcfVmRum9pLTRjoOq1qAewMSZhjk
TmOFgC4BUAVE5wsSG4gvgfRU9W4zijDCSXo6L9zSejIsIifj++w8oCR2KqtizVGa
3dzTOudIqUjV8yJr+6uAHfyPo0DRyy3C97s4ZLCJkl8Dr4xNRUPpvk9SSjHtVPOm
eSrO5GEGSkw/h74Cb/AwYJMVgGdOqDTe0pvJUHetw7d9zBjYMf5iUeaUCn7CwrSl
R35cTc9XNejA2vXimFwPiADkhoT5mRPX4Z5j3fm08HjO5tyJN0DDUQ==
=VDen
-----END PGP SIGNATURE-----

Verify a clear-signed message

Verify the message.txt.asc file's signature

gpg --verify message.txt.asc

NOTE A user needs the GPG public key for [email protected] to be able to verify the signature, while you require the private key to be able to make a signature.

Output from the command:

gpg: Signature made Fri Jan 22 05:02:00 2021 UTC
gpg:                using RSA key A7A41CFB86DCB8E71C6BC2E09FD64F451078892A
gpg:                issuer "[email protected]"
gpg: Good signature from "John Doe " [ultimate]

Detached Signature (separate signature file)

Detached signatures are very common for signing files where the signature would prevent the file from being able to be read, or where you don't have the ability to / don't want to distribute the original file with your signature.

They're most common for verifying software, to ensure that nobody has tampered with the application other than the actual developer(s) who've signed it.

First we'll remove the previous clearsign signature

rm message.txt.asc

Now we'll use the -b flag to create a detached signature (alternatively you can use --detach-sign for clarity)

gpg -u [email protected] -a -b message.txt

If we cat message.txt.asc - we can see this time that it's JUST the signature, not the original contents. This means the person verifying the signature, needs both the original file, and the signature file (.asc)

-----BEGIN PGP SIGNATURE-----

iQFFBAABCAAvFiEEp6Qc+4bcuOcca8Lgn9ZPRRB4iSoFAmAKXdMRHGpvaG5AZXhh
bXBsZS5jb20ACgkQn9ZPRRB4iSqkRgf/W2/XkhI0tyi4eRQRAS82sfnf4snUU8WS
U7S+PnbMDHdtNfDHQQRp3ygm0YcfNDeIa1KUT+7IsgKnmEDNQLBldTX4C776ibT9
cnUJCBj+qFfDcw2DtpMkbKnOHyvhmkkHaN09dXbcwAYP7B5ytuR066DeYz3EOIlK
12WiK8v/TxDpXiVLsgz9huOj6YkuhC/JISK6kVf56j4sMI5O2h0yV87CqVx6gmEK
NeQHAEM2mdpiVUwObzj+XDYw7/LyCYsxrDUEM6hqNAXUH9S+VhAl4ywZ2Q8fQCrO
hnqFgoSsunIZTm0iNVNzJGkkUhIFqJ7yTNS1nG+5t9TEBo3VQUvtdw==
=Ugoy
-----END PGP SIGNATURE-----

Verifying a detached signature

There are two ways to verify a detached signature.

1) Ensure the signature file has the same filename as the file being verified, but ends in either .asc (ASCII Armoured) or .gpg (raw binary)

If the original file has the same name, minus the .asc / .gpg extension, then you can simply pass the signature's name to gpg, and it will auto-detect the original filename

gpg --verify message.txt.asc

This would output:

gpg: assuming signed data in 'message.txt'
gpg: Signature made Fri Jan 22 05:08:35 2021 UTC
gpg:                using RSA key A7A41CFB86DCB8E71C6BC2E09FD64F451078892A
gpg:                issuer "[email protected]"
gpg: Good signature from "John Doe <[email protected]>" [ultimate]

2) Manually specify both the signature filename and the original filename

If the original file has a different name to the signature, OR the signature and file are in different locations, then you should specify both filenames to GPG, placing the signature's file name after --verify, and then the original filename after that.

gpg --verify message.txt.asc message.txt

This would output:

gpg: Signature made Fri Jan 22 05:08:35 2021 UTC
gpg:                using RSA key A7A41CFB86DCB8E71C6BC2E09FD64F451078892A
gpg:                issuer "[email protected]"
gpg: Good signature from "John Doe <[email protected]>" [ultimate]

Looking to buy a Virtual or Dedicated server? Do you like privacy and low prices? Try Privex!

We have virtual servers starting from just US$0.99/mo, and dedicated servers starting from as low as US$50/mo

Unlike other hosts, we don't ask for any personal details - only a name (can be an alias / username), and an e-mail address so we can send you your server details and renewal invoices.

We also accept several different cryptocurrencies with our own in-house payment processor - no third parties involved in processing your payments.

At the time of writing, we currently accept: Bitcoin (BTC), Litecoin (LTC), Monero (XMR), Dogecoin (DOGE), HIVE, and HBD

Order a server TODAY! Privacy is affordable™