This article focuses on practical implementation with a brief introduction to the underlying principles.
Throughout this article, I'll first cover the basic principles, then walk through three main sections: how to create GPG keys, how to manage your keys (key management commands), and hands-on practice: using self-created GPG keys to decrypt transmitted encrypted files.
Principle Overview
The principle behind using GPG for encrypting and decrypting documents is straightforward, as described in the documentation:
The procedure for encrypting and decrypting documents is straightforward with this mental model. If you want to encrypt a message to Alice, you encrypt it using Alice's public key, and she decrypts it with her private key. If Alice wants to send you a message, she encrypts it using your public key, and you decrypt it with your key.
The entire process is: I encrypt the file I want to send you with my private key. Then you use my public key to decrypt the file I want to send you, which has been encrypted by me.
This is the basic process.
This article provides a quick overview of how GPG encrypts document content.
This article is divided into two parts, starting with creating a usable GPG key.
How to Create GPG Keys
shell[Se] gpg --list-keysgpg: checking the trustdbgpg: no ultimately trusted keys found
First, let's list whether my machine currently has any GPG keys. As we can see, there are none. This mainly refers to whether there are GPG public keys. Let's also check for private keys.
shell[Se] gpg --list-secret-keys[Se]
Nothing there either.
One Command to Rule Them All
Let's start creating.
The detailed steps begin with gpg --full-generate-key, as follows:
shell[Se] gpg --full-generate-keygpg (GnuPG) 2.4.0; Copyright (C) 2021 Free Software Foundation, Inc.This is free software: you are free to change and redistribute it.There is NO WARRANTY, to the extent permitted by law.Please select what kind of key you want:(1) RSA and RSA(2) DSA and Elgamal(3) DSA (sign only)(4) RSA (sign only)(9) ECC (sign and encrypt) *default*(10) ECC (sign only)(14) Existing key from cardYour selection? 1RSA keys may be between 1024 and 4096 bits long.What keysize do you want? (3072) 4096Requested keysize is 4096 bitsPlease specify how long the key should be valid.0 = key does not expire<n> = key expires in n days<n>w = key expires in n weeks<n>m = key expires in n months<n>y = key expires in n yearsKey is valid for? (0) 0Key does not expire at allIs this correct? (y/N) yGnuPG needs to construct a user ID to identify your key.Real name: Chenwei JiangEmail address: cheverjonathan@gmail.comComment: Used for learningYou selected this USER-ID:"Chenwei Jiang (Used for learning) <cheverjonathan@gmail.com>"Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? OWe need to generate a lot of random bytes. It is a good idea to performsome other action (type on the keyboard, move the mouse, utilize thedisks) during the prime generation; this gives the random numbergenerator a better chance to gain enough entropy.gpg: revocation certificate stored as '/home/cheverjohn/.gnupg/openpgp-revocs.d/D1DED33E8FE9CA4B315A488968CC99424BF9EF81.rev'public and secret key created and signed.pub rsa4096 2023-09-19 [SC]D1DED33E8FE9CA4B315A488968CC99424BF9EF81uid Chenwei Jiang (Used for learning) <cheverjonathan@gmail.com>sub rsa4096 2023-09-19 [E]
Detailed Stage-by-Stage Command Explanation
Let me break down what happens at each stage.
Stage 1: Select Encryption and Signing Algorithm
In the first stage, you need to select the encryption algorithm. I chose option 1, which means both encryption and signing use the RSA algorithm.
shell[Se] gpg --full-generate-keygpg (GnuPG) 2.4.0; Copyright (C) 2021 Free Software Foundation, Inc.This is free software: you are free to change and redistribute it.There is NO WARRANTY, to the extent permitted by law.Please select what kind of key you want:(1) RSA and RSA(2) DSA and Elgamal(3) DSA (sign only)(4) RSA (sign only)(9) ECC (sign and encrypt) *default*(10) ECC (sign only)(14) Existing key from cardYour selection? 1
Oh, and there's also a copyright notice.
Stage 2: Select Key Length
Longer keys are more secure. I chose 4096 here.
shellRSA keys may be between 1024 and 4096 bits long.What keysize do you want? (3072) 4096Requested keysize is 4096 bits
Stage 3: Set Key Validity Period
Set the validity period.
shellPlease specify how long the key should be valid.0 = key does not expire<n> = key expires in n days<n>w = key expires in n weeks<n>m = key expires in n months<n>y = key expires in n yearsKey is valid for? (0) 0Key does not expire at allIs this correct? (y/N) y
For this demonstration, I configured Key does not expire at all.
Stage 4: Personal Information
This section will ultimately be used to generate your user ID.
shellGnuPG needs to construct a user ID to identify your key.Real name: Chenwei JiangEmail address: cheverjonathan@gmail.comComment: Used for learningYou selected this USER-ID:"Chenwei Jiang (Used for learning) <cheverjonathan@gmail.com>"Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
Here I set my Real name to "Chenwei Jiang", my Email address to "cheverjonathan@gmail.com", and added a comment. These are some basic information I commonly use, primarily for demonstration purposes.
The result is a USER-ID: "Chenwei Jiang (Used for learning) cheverjonathan@gmail.com".
How to Manage Your Keys (Key Management Commands)
This section covers how to manage multiple keys on a host machine.
Listing Keys
There are two types of key listings: public keys and private keys.
shell[Se] gpg --list-keysgpg: checking the trustdbgpg: marginals needed: 3 completes needed: 1 trust model: pgpgpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u/home/cheverjohn/.gnupg/pubring.kbx-----------------------------------pub rsa4096 2023-09-19 [SC]D1DED33E8FE9CA4B315A488968CC99424BF9EF81uid [ultimate] Chenwei Jiang (Used for learning) <cheverjonathan@gmail.com>sub rsa4096 2023-09-19 [E]
The above command shows the details.
The key section:
shell/home/cheverjohn/.gnupg/pubring.kbx-----------------------------------pub rsa4096 2023-09-19 [SC]D1DED33E8FE9CA4B315A488968CC99424BF9EF81uid [ultimate] Chenwei Jiang (Used for learning) <cheverjonathan@gmail.com>sub rsa4096 2023-09-19 [E]
The first line shows the public key filename.
| Value | Explanation |
|---|
Exporting Keys
The public key file is located at ~/.gnupg/pubring.kbx and stored in binary format. Using the armor parameter converts it to ASCII display.
Using commands to export as public-key.txt and private-key.txt:
shell[gpg] pwd/home/cheverjohn/Se/gpg[gpg] ls[gpg] ls -latotal 0drwxr-xr-x. 1 cheverjohn cheverjohn 0 Sep 19 23:36 .drwxr-xr-x. 1 cheverjohn cheverjohn 34 Sep 19 23:36 ..[gpg] gpg --armor --output public-key.txt --export 'Chenwei Jiang (used for learning) <cheverjonathan@gmail.com>'[gpg] lspublic-key.txt[gpg] cat public-key.txt-----BEGIN PGP PUBLIC KEY BLOCK-----mQINBGUJt+QBEADAzoLPAdK8GfJ/5Ouxh2rOrMsClMmoOznMm2GOBcqSaQsdmP4G................................................................oM3YFFujtMxK/cQ/KkbmwAtlMkWx5x8RT/dJ=NMtR-----END PGP PUBLIC KEY BLOCK-----[gpg]
As shown above, this demonstrates the steps to export public-key.txt. The detailed command is:
shellgpg --armor --output public-key.txt --export 'Chenwei Jiang (used for learning) <cheverjonathan@gmail.com>'
Below are the steps to export private-key.txt:
shell[gpg] lspublic-key.txt[gpg] gpg --armor --output private-key.txt --export-secret-keys[gpg] lsprivate-key.txt public-key.txt[gpg]
If you previously set a password, this operation requires the password. The command requiring password is:
shellgpg --armor --output private-key.txt --export-secret-keys
Uploading Public Keys
Public key servers are network servers specifically for storing user public keys. The --send-keys subcommand can achieve this.
Public key servers have no verification mechanism - anyone can upload public keys in your name, so there's no guarantee of reliability for public keys on servers.
Generally, we publish a public key fingerprint on our own website for others to verify that the downloaded public key is authentic. The --fingerprint subcommand can generate a public key fingerprint.
Hands-On Practice / Practice Makes Perfect
In this section, I'll demonstrate exporting public keys, encrypting with private keys, and decrypting with public keys on another device.
I'll show how to encrypt a file containing "hello world" and then decrypt it remotely.
The steps are divided into encryption and decryption.
Detailed steps:
Create file with the following commands:
shell[gpg] touch demo.txtecho "hello world" > demo.txt[gpg] lsdemo.txt private-key.txt public-key.txt[gpg] cat demo.txthello world[gpg]The file creation commands are:
shelltouch demo.txtecho "hello world" > demo.txtNow we have a demo.txt file containing "hello world".
Encrypt the file:
shell[gpg] lsdemo.txt private-key.txt public-key.txt[gpg] gpg --recipient 'cheverjonathan@gmail.com' --output demo.gpg --encrypt demo.txt[gpg] lsdemo.gpg demo.txt private-key.txt public-key.txt[gpg] cat demo.gpg�..............�&5p�.�)I�槹iQ%[gpg]Encryption command:
shellgpg --recipient 'cheverjonathan@gmail.com' --output demo.gpg --encrypt demo.txtYou can see that demo.gpg is the encrypted file.
Decrypt the file:
shell[gpg] gpg --output demo --decrypt demo.gpggpg: encrypted with rsa4096 key, ID 13C117D5FEC4F051, created 2023-09-19"Chenwei Jiang (Used for learning) <cheverjonathan@gmail.com>"[gpg] lsdemo demo.gpg demo.txt private-key.txt public-key.txt[gpg] cat demohello world[gpg]Decryption command:
shellgpg --output demo --decrypt demo.gpgAfter entering this command, you need to input the password set earlier, then you can get the file.
The above demonstrates the process of encrypting files using local keys and decrypting them locally.
Next, let's begin...
Obtaining Files on Other Computers, Encrypting Them, Then Having the Original Host Decrypt Using Private Keys
First, we transfer public-key.txt to another host. You can use GitHub's functionality to upload/download files. For convenience, I'll upload the following file tree from the above process:
Shellcheverjohn@Dell-G33579 git:(doc/test-gpg*)% tree ~/workspace/Opensource/github.com/Chever-John/cheverjohn.me/docs/wait-for-publish/gpg.├── demo├── demo.gpg├── demo.txt├── private-key.txt└── public-key.txtAfter removing private-key.txt, I'll upload the files to GitHub.
You can see I've downloaded the public-key.txt file on another host, as shown in the file tree:
shellcheverjohn:wait-for-publish/ git:(doc/test-gpg*)$ tree gpg [0:54:06]gpg├── demo├── demo.gpg├── demo.txt└── public-key.txt1 directory, 4 filesNext, I need to use this public-key.txt to encrypt a file, then transfer this file back to the host with the private key for decryption.
First, we need to import this public-key.txt locally:
shellgpg --import public-key.txtCommand execution result:
shellcheverjohn:gpg/ git:(doc/test-gpg*)$ gpg --import public-key.txt [1:20:11]gpg: key 3BE465D20064251C: public key "Chenwei Jiang (Learning second) <cheverjonathan@gmail.com>" importedgpg: Total number processed: 1gpg: imported: 1Now we need to use this public key to encrypt text.
First, let's create a file hello-no-encrypt.txt:
shellcheverjohn:gpg/ git:(doc/test-gpg*)$ touch hello-no-encrypt.txt [1:16:07]cheverjohn:gpg/ git:(doc/test-gpg*)$ nvim hello-no-encrypt.txt [1:16:15]cheverjohn:gpg/ git:(doc/test-gpg*)$ cat hello-no-encrypt.txt [1:16:24]Hello Sasa!cheverjohn:gpg/ git:(doc/test-gpg*)$ tree [1:16:28].├── demo├── demo.gpg├── demo.txt├── hello-no-encrypt.txt└── public-key.txt1 directory, 5 filesWe need to encrypt this file and then send it to the host with the private key for decryption.
The entire encryption process:
shellcheverjohn:gpg/ git:(doc/test-gpg*)$ gpg --output hello-encrypted.gpg --encrypt --recipient 'Chenwei Jiang (Learning second) <cheverjonathan@gmail.com>' hello-no-encrypt.txtgpg: 617C5542800731C1: There is no assurance this key belongs to the named usersub rsa4096/617C5542800731C1 2023-09-21 Chenwei Jiang (Learning second) <cheverjonathan@gmail.com>Primary key fingerprint: 5588 D37D AF51 50FD 9186 47E7 3BE4 65D2 0064 251CSubkey fingerprint: A038 0DA1 D481 62C7 517C D6C6 617C 5542 8007 31C1It is NOT certain that the key belongs to the person namedin 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) yEncryption command:
shellgpg --output hello-encrypted.gpg --encrypt --recipient 'Chenwei Jiang (Learning second) <cheverjonathan@gmail.com>' hello-no-encrypt.txtThen we need to upload the encrypted file hello-encrypted.gpg to the machine with the private key.
Again, I'll use GitHub as the file transfer tool.
You can see I've obtained the file on the host machine (the machine with the keys) and started decryption:
shell[gpg] tree git:(doc/test-gpg).├── demo├── demo.gpg├── demo.txt├── hello-encrypted.gpg├── hello-no-encrypt.txt└── public-key.txt1 directory, 6 filesNext, we need to decrypt hello-encrypted.gpg:
shell[gpg] gpg --output hello-decrypted.txt --decrypt hello-encrypted.gpg git:(doc/test-gpg)gpg: encrypted with rsa4096 key, ID 617C5542800731C1, created 2023-09-21"Chenwei Jiang (Learning second) <cheverjonathan@gmail.com>"[gpg] ls git:(doc/test-gpg*) ✱demo demo.gpg demo.txt hello-decrypted.txt hello-encrypted.gpg hello-no-encrypt.txt public-key.txt[gpg] cat hello-decrypted.txt git:(doc/test-gpg*) ✱Hello Sasa!Decryption command:
shellgpg --output hello-decrypted.txt --decrypt hello-encrypted.gpg
Comments