Overview
- Introduction
- Install GPG
- Basic usage
- Key management
- Encryption
- Signatures
- Conclusion
- Reference links
Introduction
GnuPG is a cryptography tool that helps you manage public and private keys as well as perform encrypt, decrypt, sign, and verify operations. It is an open-source version of PGP. This tutorial will go over basic key management, encrypting (symmetrically and asymmetrically), decrypting, signing messages, and verifying signatures with GPG.
There are bindings to most programming languages so you can use it within your own custom application, but this tutorial is focused on the command-line utility gpg.
In this tutorial, the word 'message' is synonmous for 'file' or 'document'. You can encrypt and sign binary files just the same as text messages.
You can find the DevDungeon public GPG key at https://www.devdungeon.com/gpg.
Install GPG
You can find the download links for all available platforms and source code on the official GnuPG website.
Windows
On Windows, I recommend the Gpg4win application. You can find the installer at Windows GnuPG installer (Gpg4win) download page. Just run the installer and then gpg will be available in your command prompt.
Mac
The easiest way to install on Mac in my opinion is using Mac Homebrew. There is a formula for gpg named gnupg: GPG for Mac Homebrew. You will need to install brew first if you don't already have it.
# Install on Mac
brew install gnupg
Linux
Most Linux distributions have gpg in their package repository. Check with your specific distribution to find what the gpg package name is. It might be gnupg or gpg2 or some variation.
# On Debian/Ubuntu based distros
sudo apt-get install gpg
Android
There is an Android version available Android GnuPG
Basic usage
To get started and make sure it is installed correctly, run gpg with the --help flag to print out the version number, supported encryption and hash algorithms, and all the usage options. This will give you an overview of all the features GPG has.
gpg --help
Example output of gpg --help:
gpg (GnuPG) 2.2.10 libgcrypt 1.8.3 Copyright (C) 2018 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later https://gnu.org/licenses/gpl.html This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Home: C:/opt/gnupg Supported algorithms: Pubkey: RSA, ELG, DSA, ECDH, ECDSA, EDDSA Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH, CAMELLIA128, CAMELLIA192, CAMELLIA256 Hash: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224 Compression: Uncompressed, ZIP, ZLIB, BZIP2 Syntax: gpg [options] [files] Sign, check, encrypt or decrypt Default operation depends on the input data Commands: -s, --sign make a signature --clear-sign make a clear text signature -b, --detach-sign make a detached signature -e, --encrypt encrypt data -c, --symmetric encryption only with symmetric cipher -d, --decrypt decrypt data (default) --verify verify a signature -k, --list-keys list keys --list-signatures list keys and signatures --check-signatures list and check key signatures --fingerprint list keys and fingerprints -K, --list-secret-keys list secret keys --generate-key generate a new key pair --quick-generate-key quickly generate a new key pair --quick-add-uid quickly add a new user-id --quick-revoke-uid quickly revoke a user-id --quick-set-expire quickly set a new expiration date --full-generate-key full featured key pair generation --generate-revocation generate a revocation certificate --delete-keys remove keys from the public keyring --delete-secret-keys remove keys from the secret keyring --quick-sign-key quickly sign a key --quick-lsign-key quickly sign a key locally --sign-key sign a key --lsign-key sign a key locally --edit-key sign or edit a key --change-passphrase change a passphrase --export export keys --send-keys export keys to a keyserver --receive-keys import keys from a keyserver --search-keys search for keys on a keyserver --refresh-keys update all keys from a keyserver --import import/merge keys --card-status print the card status --edit-card change data on a card --change-pin change a card's PIN --update-trustdb update the trust database --print-md print message digests --server run in server mode --tofu-policy VALUE set the TOFU policy for a key Options: -a, --armor create ascii armored output -r, --recipient USER-ID encrypt for USER-ID -u, --local-user USER-ID use USER-ID to sign or decrypt -z N set compress level to N (0 disables) --textmode use canonical text mode -o, --output FILE write output to FILE -v, --verbose verbose -n, --dry-run do not make any changes -i, --interactive prompt before overwriting --openpgp use strict OpenPGP behavior (See the man page for a complete listing of all commands and options) Examples: -se -r Bob [file] sign and encrypt for user Bob --clear-sign [file] make a clear text signature --detach-sign [file] make a detached signature --list-keys [names] show keys --fingerprint [names] show fingerprints Please report bugs to https://bugs.gnupg.org
Key management
When it comes to keys there are private(secret) keys and public keys. They are paired together. The public key is, as expected, something you can make public and share with others. The private key is like your secret password though, don't share that one with anyone! You might have the public key of many people stored on your computer but the only private key you will probably have is your own.
List keys stored locally
# List public keys you have stored (yours and other people's keys)
gpg --list-keys
# List private keys (generally only your own)
gpg --list-secret-keys
Create a new private key
Use the --gen-key flag to create a new secret (private) key. This will walk you through an interactive prompt to fill out the questions like what is your name.
gpg --gen-key
Export a private key
You might want to export your private key in order to back it up somewhere. Don't share your private key with other people though. You can export in armored (ASCII) format and you could actually print it out on paper or write it down since it is human readable and put it in cold storage. Text format may also work better than binary in certain communication mediums.
# Find the ID of your key first
# The ID is the hexadecimal number
gpg --list-secret-keys
# This is your private key keep it secret!
# Replace XXXXXXXX with your hexadecimal key ID
gpg --export-secret-keys --armor XXXXXXXX > ./my-priv-gpg-key.asc
# Omitting the --armor flag will give you binary output instead of ASCII
# which would result in a slightly smaller file but the ASCII
# formatted (armored) can be printed physically, is human readable,
# and transfered digitally easier.
# Both formats can be imported back in to GPG later
Delete a key
You can delete a private key from local storage with the following command:
# Private keys
# Use the ID listed with --list-secret-keys
gpg --delete-secret-keys XXXXXXXX
# Public keys
# Use the ID listed with --list-keys
gpg --delete-keys XXXXXXXX
Import a key
If you need to import a key you can use the following command. This is useful if you are on a new computer or a fresh install and you need to import your key from a backup. You can import a public or a private key this way. Typically the only time you will be importing a private key is when restoring a backup of your own private key. The most common case for importing a public key is to store someone else's public key in order to send them a private message or to verify a signature of theirs.
# This works the same for binary or ASCII (armored) versions of keys
# This is also the same for private and public keys
gpg --import ./my-priv-gpg-key.asc
# You can also directly import a key from a server
# For example, import the DevDungeon/NanoDano public GPG key from MIT
gpg --keyserver pgp.mit.edu --recv C104CDF0EDA54C82
Generate revocation key
gpg --output my_revocation_certificate.asc --gen-revoke <key>
Push your public key to key server
You may want or need to publish your public key somewhere where everyone can find it. For example, to push code to the Maven central repository, you must sign your code with a GPG key that has a public signature somewhere like the MIT public key server. You can push your public key using the --send-keys flag.
# There are many public key servers out there, not just MIT
# Replace XXXXXXXX with your key id from --list-keys
gpg --keyserver hkp://pgp.mit.edu --send-keys XXXXXXXX
Encryption
There are two types. Symmetric and asymmetric. GPG supports many different algorithms for each method. The most commonly known ones are AES for symmetric and RSA for asymmetric. ECDSA is starting to slowly replace RSA though. The following examples will demonstrate how to do both symmetric and asymmetric encryption as well as decrypt a message.
Encrypt with a passphrase (symmetric)
Can be decrypted by anyone with the passphrase. No specific recipient. Passphrase can be shared with many people. This can be useful for just encrypting files locally with a simple passphrase, or to encrypt a document before sending it to someone. You'll have to find another channel to send them the passphrase though if it is not already exchanged before-hand.
There are two formats of output you can get: binary and text. The binary version will take up less space, but the ASCII version is a little easier to work with and can be transported over text means, say, pasted in to an email. They both decrypt the same way.
gpg --symmetric message.txt
# Prompts you for a passphrase
# Creates message.txt.gpg (binary)
gpg --armor --symmetric message.txt
# Same, but ASCII format output instead of binary
# Creates message.txt.asc (ASCII)
# Specify the encryption algorithm
gpg --symmetric --cipher-algo AES256
# Get the list of cipher algorithms
gpg --version
# E.g. 3DES, BLOWFISH, AES256, TWOFISH
# Specify output file
gpg --output message.txt.gpg --symmetric message.txt
# Encrypt and sign (all in the single output file)
gpg --sign --symmetric message.txt
You can also encrypt and sign at the same time. Signatures are covered in more detail in the Signatures section below.
Encrypt for a single recipient (asymmetric)
You can encrypt a message for a single specific recipient. You do this by encrypting asymmetrically with your private key and the recipients public key. By doing this, only the recipient's private key will decrypt the message. You will need the recipient's public key in order to do this. They can share their public key with you directly, or you can search public key servers.
# Import NanoDano's public GPG key
gpg --keyserver pgp.mit.edu --search-keys nanodano@devdungeon.com
# It will print a list of matching results.
# Enter the number next to the one you want to import
# After it's imported you can verify the public key is stored with
gpg --list-keys
After you have the receipient's public key imported, you can encrypt messages that only they can decrypt.
# This will prompt and ask the recipient's email address
# and you will have to enter the ID or email
gpg --encrypt message.txt
# or specify the recipient as the -r argument
gpg --recipient nanodano@devdungeon.com --encrypt message.txt
# Encrypted output will be in message.txt.gpg
# Encrypt and store in ASCII format (message.txt.asc)
# Both binary and ASCII versions decrypt the same
gpg --armor --recipient nanodano@devdungeon.com --encrypt message.txt
# Encrypt and sign at the same time
gpg --encrypt --sign --recipient nanodano@devdungeon.com message.txt
# Specify output file
gpg --output message.txt.gpg
Decrypt a message
You can decrypt messages with the -d or --decrypt option. It will automatically determine if it is symmetrically encrypted with something like AES and it needs a passphrase, or if it was encrypted asymmetrically with something like RSA and it needs to look for a private key. The recipient will be detected automatically and GPG will search locally to see if the private key is stored. If it is, it will ask for the passphrase and then print out the decrypted message to the console. If it is a symmetric encryption it will prompt you for the passphrase, and then print the message.
# Decrypt and print message to screen
# Will automatically verify signature if there was one
# Will automatically detect if symmetric or asymmetric
# Will automatically use the appropriate private key if available
# Will automatically prompt for passphrase if symmetric
gpg -d message.txt.gpg
# Decrypt and put output in decrypted.txt
gpg --decrypt message.txt.gpg > decrypted.txt
Signatures
You can sign files that were encrypted using asymmetric or symmetric methods. The benefit of providing a signature is to let everyone prove that you were the author of the file, or at least, you confirmed the contents of the file at the time of your signature. You can also just sign files without encrypting them at all.
Sign a message
You can use the sign feature without any encryption. That is, if you want to share something in plain-text or make a public post that everyone can read, but you want to include a signature to prove you were the original author.
The resulting output file is the unencrypted original document with a signature at the end. It is not used to encrypt and secure the information and guarantees no confidentiality. It only proves integity and authenticity of the message. You can create a binary signature or a plain-text signature.
gpg --clearsign message.txt
# Outputs message.txt.asc in plain text, suitable
# for pasting in an email or posting online
gpg --sign message.txt
# Outputs message.txt.gpg a binary file
# Both of these can be verified with --decrypt
# but they are not _actually_ encrypted.
gpg --decrypt message.txt.gpg
gpg --decrypt message.txt.asc
# This will print out the message along with the signature info
Encrypt and sign
You can encrypy-and-sign a message in one step. This will attach the signatures to the encrypted file. With these two encrypt-and-sign methods below, the signature is included in the encrypted .gpg/.asc file that is output. When someone decrypts them, the signature will be checked automatically.
# Symmetric encrypt with signature
gpg --sign --symmetric message.txt
# Asymmetric encrypt with signature
gpg --sign --encrypt --recipient nanodano@devdungeon.com message.txt
Verify signatures
If a signature is included in the encrypted file, GPG will automatically output the verification of the signature when it decrypts the message. You don't have to take any special action to verify the signature you just use the normal -d or --decrypt option, it happens by default.
# When you decrypt the message it will verify the signature
gpg --decrypt message.txt.asc
You can also manually verify a signature for things like a clear signed file with the --verify option like this:
# Verify a signed message that included a signature
gpg --verify message.txt.asc
# Verify and extract original document
gpg --output message.txt message.txt.asc
Detached signatures
So far all the signatures we have seen have been embedded in to the file with the message. It is also possible to separate the signature file from the message file. This is called a detached signature.
# Create a separate signature file
gpg --detach-sign message.txt
# Will create message.txt.sig
# This verify will automatically check the signature
# against a file named "message.txt"
gpg --verify message.txt.sig
# Specify the file to check it against
gpg --verify some_signature.sig ./message.txt
Conclusion
After reading this, you should understand how to use GPG for its most common tasks like creating and managing keys, encrypting symettrically with AES, encrypting a message for a specific person with RSA, and how to sign and verify signatures.
This was not a comprehensive overview of all the GPG features. It was only a brief overview of some basics. Here are some notable things that are not covered here:
- Plugins for applications like Outlook and Thunderbird to add GPG encryption support.
- Trusted rings
- Signing people's public keys
- Good encrpytion habits
- Revocation keys
Read more about all the features on the Official GnuPG documentation.