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.
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.
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
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 <johnd@example.com>
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.
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
--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 :)
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
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 support@privex.io
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 "support@privex.io". 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) <support@privex.io>" 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 S4096 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
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.
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 <johnd@example.com>"
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 <johnd@example.com>"
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 <johnd@example.com>"
$ cat reply.txt
hello world
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 support@privex.io -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, john@example.com [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 support@privex.io -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
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 john@example.org private key
gpg -u john@example.com -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 the message.txt.asc file's signature
gpg --verify message.txt.asc
NOTE A user needs the GPG public key for john@example.com
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 "john@example.com" gpg: Good signature from "John Doe" [ultimate]
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 john@example.com -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-----
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 "john@example.com"
gpg: Good signature from "John Doe <john@example.com>" [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 "john@example.com"
gpg: Good signature from "John Doe <john@example.com>" [ultimate]
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