How to Use GPG: A Practical Guide to Key Management, Encryption, and Signing

GPG (GNU Privacy Guard) is an implementation of PGP and is widely used in the field of cryptography. Its fundamental principle is asymmetric cryptography, also known as public-key cryptography. This article will not delve deeply into its underlying principles but will instead introduce its basic usage. The scenarios described below are those I might encounter in my daily work.
Creating a Key Pair
Since GPG is based on asymmetric cryptography technology, the first step in using it is to generate a key pair: a public key and a private key:
$ gpg --full-generate-key
After entering the command above in the terminal, the program will display several options for the user to choose from.
- Keypair. The previous default option was
RSA, but it has now been replaced with the more secure and fasterECC. - Elliptic curve. Select the default
Curve25519. - Expiration date. Choose according to your needs; for convenience, you can select
never expire, which can be changed later using commands. - Name and email address.
- Comment: Add a comment describing the key’s purpose.
- Passphrase. Make sure to memorize your passphrase permanently.
After completing the steps above, the key pair will be generated. It will be stored in the ~/.gnupg/ directory. The permissions for this directory are strict by default, so you do not need to change them. It’s a very good idea to back it up to another highly secure drive.
Managing Key Pairs
Listing Key Pairs
Check all generated and stored public keys:
$ gpg --list-keys
Check private keys:
$ gpg --list-secret-keys --keyid-format LONG
In the terminal output, look for the lines starting with sec and ssb. The strings of characters immediately following the slashes (/) are your GPG master Key ID and subkey ID:
sec ed25519/CCCDF90A8A54770A 2026-05-31 [SC]
156798B6096108662D9CF0FCCCCDF90A8A54770A
uid [ultimate] sg <[email protected]>
ssb cv25519/3E14A0E6F7B4A928 2026-05-31 [E]
In the example above, CCCDF90A8A54770A is the master key ID, and 3E14A0E6F7B4A928 is the subkey ID.
Deleting a Key Pair
Deleting a key pair requires a specific order. You must delete the private key first. The command is as follows:
$ gpg --delete-secret-key <key-id>
To delete the public key:
$ gpg --delete-key <key-id>
Backing Up Key Pairs
If you don’t want to back up the entire directory, you can export the key pair, back it up, and then import it onto another device later.
Export a private key:
$ gpg --armor --export-secret-keys <key-id> > private-key.asc
Exporting a public key:
$ gpg --armor --export <key-id> > public-key.asc
If you want to preserve the trust relationships you’ve established with other key owners, you should also export your ownertrust values:
$ gpg --export-ownertrust > ownertrust.txt
Importing a public key:
$ gpg --import public-key.asc
Importing a private key:
$ gpg --import private-key.asc
Importing ownertrust values:
$ gpg --import-ownertrust ownertrust.txt
Uploading and Downloading Public Keys
The private key in a key pair must never be disclosed to anyone, while the public key can be shared with friends, posted on websites, or uploaded to public key servers:
$ gpg --keyserver <keyserver-name> --send-keys <key-id>
If we want to retrieve somebody’s public key from the key servers, we can use the following commands.
Search a key:
$ gpg --keyserver <keyserver-name> --search-keys <email address>
Import a key from a key server:
$ gpg --keyserver <keyserver-name> --receive-keys <key-id>
Update all keys that have already been retrieved from key servers:
$ gpg --refresh-keys
Editing Key Pairs
Use the following command to open the key pair editing panel:
$ gpg --edit-key <key-id>
Type help to view all options. The following options are commonly used:
passwd change the passphrase
uid select user ID N
adduid add a user ID
deluid delete selected user IDs
primary mark the selected user ID as primary
key select subkey N
addkey add a subkey
delkey delete selected subkeys
expire change the expiration date for the key or selected subkeys
revkey revoke the key or selected subkeys
trust change the owner trust
Here, we highlight three commands, and the others may be discussed later:
- addkey
As mentioned earlier, the key generation command generates a master key and a subkey. The master key’s type must include “C”, which stands for Certify, meaning the master key can certify other public keys. This is the core function of the master key, which will be explained in detail later.
As shown earlier, when the master key is generated, a subkey of type “E” (for Encrypt) is automatically created, indicating that this subkey can be used to encrypt and decrypt data. New subkeys can also be derived from the master key using the addkey command. The program will prompt you for the type of the new subkey, such as Sign Only, which is also denoted by the single letter “S”. The expiration date of a subkey can be set according to your needs, such as 2 years. The usage of a subkey does not affect the master key. Therefore, this approach enhances the security of the master key.
Note that the generated subkeys are all private keys. There is still only one public key—the public key corresponding to the master private key.
- expire
You can renew the main key or a subkey at any time using the expire command. It is recommended to set a reminder (e.g., via a calendar) to notify yourself when renewal is approaching.
- revkey
This command is used to revoke the corresponding public key if the private key has been compromised. However, since the private key may have been stolen or may no longer be accessible, it is best to execute the following command immediately after generating the key pair:
$ gpg --output revoke.asc --gen-revoke <key-id>
The command will generate a revocation certificate. You should save it in a very secure location. If you need to revoke the public key in the future, use the following command:
$ gpg --import revoke.asc
These actions are only effective locally. To ensure others are aware that the original key has been revoked, you can upload the revoked public key to key servers:
$ gpg --keyserver <keyserver-name> --send <key-id>
Practical Use
Encrypting and Decrypting
In this scenario, GPG’s public key is used for encryption, and the private key is used for decryption. That is, when A wants to send a confidential message to B, A must first obtain B’s public key, then use that public key to encrypt the message, send the encrypted message to B, and B then uses the private key to decrypt it.
The encryption command is as follows:
$ gpg [--output somefile.txt.gpg] --encrypt somefile.txt --recipient <key-id>
Decryption command:
$ gpg --output somefile.txt --decrypt somefile.txt.gpg
Signing and Verifying Signatures
In this scenario, the GPG private key is used for encryption, and the public key is used for decryption. Specifically, when A wants to publish data, A first encrypts the data with A’s private key—a process known as signing—and then publishes it. When others decrypt the data using A’s public key, they can verify whether the data originated from A.
Signing Command:
$ gpg --output <file.gpg> --sign <file>
Note that the command above compresses the original file, making it unreadable to humans. If you want to keep the original file uncompressed, use the command:
$ gpg --output <file.asc> --clearsign <file>
However, both of the above commands embed the signature directly at the end of the file. If you want to save the signature in a separate file, use the following command. The --armor option determines whether the generated signature is human-readable:
$ gpg [--armor] --output <file.sig | file.asc> --detach-sign <file>
In high-security scenarios, you may need to both encrypt and sign a file. The following command first signs the file and then encrypts it:
$ gpg [--armor] --output <file.gpg | file.asc> --encrypt --recipient <user-id> --sign <file>
Verification command:
$ gpg --verify <file.gpg | file.sig | file.asc>
Or decrypt data. When decrypting, GPG will also verify that the signature is valid:
$ gpg --output <file> --decrypt <file.gpg>
Signing Git Commits
To sign a Git commit with a specific key, configure the following settings:
$ git config --global user.signingkey <subkey-id>!
Note the ‘!’ above may be necessary to force Git to use that subkey instead of the master key for signing!
Additionally, the following settings allow Git to automatically sign commits or tags without having to explicitly add the -S option when executing the relevant Git commands.
commit.gpgsign=true
tag.gpgsign=true
When pushing a Git repository to a host like GitHub, you must first add your local GPG public key to the appropriate section on the site. GitHub will automatically match the corresponding signing subkey.
Additionally, if you want to prevent crawlers from accessing your real email address, you can use the dedicated email address provided by GitHub in the format [email protected]. That is, use the adduid command under --edit-key to add a corresponding UID. Then, set user.email to this email address either in your Git project or globally. This way, when you sign and commit a Git repository locally or push it to a remote repository, only the custom email address will be displayed on the website.
Email Encryption and Signing
When using PGP for email, both encryption and signing features may be utilized. In fact, when Thunderbird prompts users to import a key, it requires that the key support both encryption and signing. However, by design, when GPG generates a subkey, it provides only a single function by default. To enable a subkey to have multiple functions, you must edit it in expert mode using the following command:
$ gpg --expert --edit-key <key-id>
You must also select the older RSA mode for this to work. Next, export the subkey:
$ gpg --export-secret-subkeys! <subkey-id> > subkey_secret.asc
Note that the ‘!’ in the command above is mandatory. Otherwise, GPG will export all subkeys under the main private key! Next, you can import this subkey into Thunderbird. But there are currently compatibility warnings. Details are explained in Mozilla’s article.
Given these complications, I chose to use Thunderbird’s built-in key generation and management features. Thunderbird also includes features such as automatic encryption and signing, making it as convenient as possible for users to work with keys within the application.
SSH Authentication
SSH is also based on asymmetric cryptography. When a client connects to a server via SSH, the server requires the client to prove that it possesses the private key corresponding to a public key listed in the server’s key list. In practice, this involves the client signing the challenge data sent by the server with its private key, after which the server verifies the signature using the public key. The process is referred to as “authentication”, which confirms that the client’s identity is valid.
Generally, the client’s SSH key pair is managed by the SSH Agent. However, this task can naturally be delegated to the GPG Agent, which allows SSH to leverage the benefits of GPG, such as a flexible key management system, and private keys can also be stored more securely—for example, by using a YubiKey rather than storing them in a disk file, as SSH does.
To make GPG keys available to SSH, the key must be of the Authenticate type. To generate a subkey of this type, you need to edit the master key in expert mode. Alternatively, you can use the following quick command:
$ gpg --quick-add-key <key-id> ed25519 auth
You can then use the following command to view the newly created subkey, which is marked with the type “A”:
$ gpg -K --with-keygrip
The command above will also print the key’s keygrip. Now add the keygrip to the sshcontrol file in the ~/.gnupg/ directory, indicating that GPG Agent can use this key for SSH. To enable GPG Agent to actually support SSH, add the following to the gpg-agent.conf file in the ~/.gnupg/ directory:
enable-ssh-support
And configure SSH to use the GPG Agent socket:
$ export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
$ export GPG_TTY=$(tty)
$ gpg-connect-agent updatestartuptty /bye >/dev/null
After that, restart the GPG Agent and verify that SSH can now see the GPG Type A subkey:
$ gpgconf --kill gpg-agent && gpgconf --launch gpg-agent
$ ssh-add -l
Then you should export the GPG public key and upload it to the server you want to log into:
$ gpg --export-ssh-key <key-id> > ~/.ssh/id_ed25519_gpg.pub
You can now log into the server using SSH. The related processes can be configured to start automatically at boot:
$ systemctl --user enable --now gpg-agent-ssh.socket
Web of Trust
As you use GPG, you may acquire public keys of more and more people, and more and more people may acquire your public key at the same time. How can people verify the validity of others’ public keys? The answer lies in the establishment of the Web of Trust.
To understand the Web of Trust, you must clarify two concepts: Trust and Validity. Trust refers to the degree to which A trusts B, which is A’s subjective judgment. Validity is the final validity score calculated by GPG based on factors such as the Trust value. It cannot be directly modified. The common levels for these two concepts are as follows:
- unknown
q undefined (similar to -)
n not valid (no trust)
m marginal (limited trust)
f full (full trust)
u ultimate (absolute trust)
For example, after verifying B’s public key fingerprint in person, A imports B’s public key. At this point, A has a high level of trust in the Validity of B’s public key. A can use A’s own private key to sign this public key. The operation is technically referred to as “certification”. After signing, GPG sets the Validity to full. However, this does not mean that A trusts B personally. Therefore, the Trust value for B’s public key is still - by default, which means unknown as shown in the table above. If A wants to modify the trust value, A can use the trust option with the --edit-key command.
Signing can create a chain of signatures, such as A signing B, and B signing C. In this case, A can indirectly determine the validity of C’s public key without having to verify it directly. Some of GPG’s default calculation rules are listed below:
If a public key is signed by one person with "full" trust, its validity is considered "full".
If a public key is signed by three people with "marginal" trust, its validity is considered "full".
The number of layers in a signature chain is scalable but has a maximum limit (default is 5). Explaining this in detail would make the whole process more complicated! Fortunately, you generally won’t encounter this situation, so understanding the rules above is sufficient. The actual commands are as follows.
Verify the other party’s public key fingerprint:
$ gpg --fingerprint <email address>
Sign the other party’s public key:
$ gpg --sign-key <email address>
You can then distribute the newly signed public key by uploading it to a server or similar means. Alternatively, you can sign it for local use only, without intending to distribute it:
$ gpg --lsign-key <email address>
Limitations
GPG is complex, and the complexity stems from its underlying principle: asymmetric cryptography. For those unfamiliar with these concepts, it may take a long time to understand. GPG’s design does not hide this complexity, so it is also quite cumbersome to use. Furthermore, due to its long history, it lacks many modern features.
But that’s not the worst part. I often get the feeling that some people are deliberately misleading others: they go on at length about low-level principles or jargon without explaining the big picture or the result, leaving people confused and disoriented. Please note: GPG is by no means synonymous with anonymity or “security”—perhaps quite the opposite! Ultimately, it simply serves to let others know that what you have is truly yours. As for how to convince others that you are who you claim to be, technically speaking, it comes down to key management and Web of Trust—which touches on the very foundation of the whole system. While this approach may be slightly better than the straightforward power dynamics involved in certificate authorities like S/MIME or HTTPS, it still cannot escape the realm of sociology and remains dependent on CAs!
However, the above criticism isn’t specifically directed at GPG itself. GPG is valuable—as demonstrated by the applications mentioned in this article—and it’s free software. Users just need to be careful not to be misled by certain people! Here’s my email public key, and welcome to use it.