有一天我们可能会遇到这样的场景:某个文件不宜以明文形式存放,比如包含客户数据的数据库转储、带有凭据的文档,或是准备上传到并非完全可信的云存储上的备份。在文件离开本机之前对其进行加密,即可解决这一问题;而在 Linux 环境下,GPG 正是完成此项任务的标准工具。
GnuPG(GNU Privacy Guard),命令行调用为 gpg,实现了 OpenPGP 标准。它支持两种文件加密方式:对称加密(symmetric encryption),即使用同一个口令(passphrase)对文件进行加锁和解锁;以及公钥加密(public key encryption),即任何人都可以使用你的公钥为你加密文件,但只有你的私钥才能解密。
下面将介绍如何使用 gpg 通过上述两种方法对文件进行加密和解密、如何与他人交换加密文件,以及如何在脚本中处理加密操作。
注意:这里版本是2.3.3,不同版本命令略有不同。
1.安装 GnuPG
几乎所有 Linux 发行版都预装了 GnuPG,因为包管理器本身依赖它。我们可以通过以下命令验证是否可用:
gpg --version
输出示例:
[ymadmin@backup ~]$ gpg --version
gpg (GnuPG) 2.3.3
libgcrypt 1.10.0-unknown
Copyright (C) 2021 Free Software Foundation, Inc.
License GNU GPL-3.0-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: /home/ymadmin/.gnupg
Supported algorithms:
Pubkey: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
CAMELLIA128, CAMELLIA192, CAMELLIA256
AEAD: EAX, OCB
Hash: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
Compression: Uncompressed, ZIP, ZLIB, BZIP2
[ymadmin@backup ~]$
版本号可能有所不同,但任何当前主流的 GnuPG 2.x 版本均支持本文所用命令。
如果命令不存在,可安装 gnupg 包,在Fedora、RHEL 及其衍生版中,执行:sudo dnf install gnupg2可以进行安装。
2.使用口令加密文件
对称加密是最简单的方案:一个口令加密文件,同一个口令解密文件。无需生成或交换密钥,非常适合加密个人备份,或通过独立渠道共享口令后向他人发送文件。
使用 -c(--symmetric)选项:
gpg -c database20260815.sql
[ymadmin@backup ~]$ gpg -c database20260815.sql
gpg: directory '/home/ymadmin/.gnupg' created
gpg: keybox '/home/ymadmin/.gnupg/pubring.kbx' created
[ymadmin@backup ~]$
gpg 会提示你输入口令并要求重复确认(QWE123465),随后将加密结果写入 database20260815.sql.gpg。原始文件仍保留在原处。在删除原始文件之前,建议先将加密副本解密到一个临时文件并进行比对:
gpg -o /tmp/database20260815.sql -d database20260815.sql.gpg
cmp database20260815.sql /tmp/database20260815.sql
当两个文件完全一致时,cmp 命令不会有任何输出。比对成功后,删除临时文件和原始明文文件:
rm /tmp/database20260815.sql
rm database20260815.sql
默认情况下,输出为二进制文件。如果你需要将加密内容粘贴到邮件或工单中,可添加 -a(--armor)选项以生成 ASCII 文本格式,这里事先新建一个mynotes.txt的文本文件,随机写入内容,然后加密(口令:123456):
gpg -c -a mynotes.txt
这将生成 notes.txt.asc,一个纯文本文件,可安全地进行复制粘贴。
[ymadmin@backup ~]$ cat mynotes.txt.asc
-----BEGIN PGP MESSAGE-----
jA0ECQMC49sJFvFa1mD/0l4Bp4u3CdoyIapfazvZdCGfx1yrbyAxrvtcIHF1qbjm
AGC7rme5Dyg267WKb60L3QYyvldMDC94gEbVf29yg8e+dHCZBY+2D0Ddkdx0CWKN
PC68O/iEkXuqzGgR+4J9
=SnWt
-----END PGP MESSAGE-----
[ymadmin@backup ~]$
我们也可以通过 --cipher-algo AES256 显式指定加密算法(若策略要求使用特定算法);运行 gpg --version 可查看当前构建支持的算法列表。
3.解密文件
解密时,将加密文件传给 gpg 并带上 -d(--decrypt)选项,同时使用 -o 指定输出文件名:
[ymadmin@backup ~]$ gpg -o database20260815.sql -d database20260815.sql.gpg
gpg: AES256.CFB encrypted data
gpg: encrypted with 1 passphrase
[ymadmin@backup ~]$
gpg 会要求输入口令,然后写入解密后的文件:
如果不加 -o,-d 选项会将解密内容输出到标准输出(stdout),这在只想查看小型加密文本文件时非常实用:
gpg -d mynotes.txt.asc
[ymadmin@backup ~]$ gpg -d mynotes.txt.asc
gpg: AES256.CFB encrypted data
gpg: encrypted with 1 passphrase
test
123
456
netskyman@163.com
[ymadmin@backup ~]$
4.生成 GPG 密钥对
公钥加密解决了共享口令的问题。你公开发布自己的公钥,任何人都可以用它来为你加密文件,但只有你的私钥才能解密。私钥永远不会离开你的机器。
使用以下命令生成密钥对:
gpg --full-generate-key
[ymadmin@backup ~]$ gpg --full-generate-key
gpg (GnuPG) 2.3.3; 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 (default)
(2) DSA and Elgamal
(3) DSA (sign only)
(4) RSA (sign only)
(14) Existing key from card
Your selection? 1
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072)
Requested keysize is 3072 bits
Please 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 years
Key is valid for? (0)
Key does not expire at all
Is this correct? (y/N) y
GnuPG needs to construct a user ID to identify your key.
Real name: imoonrong
Email address: netskyman@163.com
Comment: mypwdj
You selected this USER-ID:
"imoonrong (mypwdj) <netskyman@163.com>"
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: /home/ymadmin/.gnupg/trustdb.gpg: trustdb created
gpg: key 5313A3181E4A4372 marked as ultimately trusted
gpg: directory '/home/ymadmin/.gnupg/openpgp-revocs.d' created
gpg: revocation certificate stored as '/home/ymadmin/.gnupg/openpgp-revocs.d/C5D589A0AA05779332B1CAF85313A3181E4A4372.rev'
public and secret key created and signed.
pub rsa3072 2026-08-15 [SC]
C5D589A0AA05779332B1CAF85313A3181E4A4372
uid imoonrong (mypwdj) <netskyman@163.com>
sub rsa3072 2026-08-15 [E]
[ymadmin@backup ~]$


该命令会引导你完成一系列提示:密钥类型(默认即可)、过期日期、姓名和电子邮件地址。最后,它会要求你为私钥设置一个保护口令。生成完成后,列出密钥以确认:
gpg --list-keys
输出示例:
[ymadmin@backup ~]$ gpg --list-keys
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
/home/ymadmin/.gnupg/pubring.kbx
--------------------------------
pub rsa3072 2026-08-15 [SC]
C5D589A0AA05779332B1CAF85313A3181E4A4372
uid [ultimate] imoonrong (mypwdj) <netskyman@163.com>
sub rsa3072 2026-08-15 [E]
[ymadmin@backup ~]$
那串长十六进制字符串即为密钥指纹(key fingerprint)。它唯一标识了该密钥,其他人可以通过它来验证密钥确实属于你。
5.交换公钥
要让他人能够为你加密文件,你需要将自己的公钥以 ASCII 格式导出并发送给对方:
将 netskyman@163.com 对应的公钥导出为 ASCII 文本格式,保存到 netskyman-public.asc 文件中。
gpg --armor --export netskyman@163.com > netskyman-public.asc
可以查看生成的内容:
[ymadmin@backup ~]$ cat netskyman-public.asc
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
8sQD5xycf0e60NwS0ePxS/B9SIDAkA==
=NRM6
-----END PGP PUBLIC KEY BLOCK-----
[ymadmin@backup ~]$

当你收到他人的公钥时,将其导入你的密钥环(keyring):
gpg --import netskyman-public.asc
输出示例:
gpg: key 5313A3181E4A4372: "imoonrong (mypwdj) <netskyman@163.com>" imported
gpg: Total number processed: 1
gpg: imported: 1
6.为指定接收方加密文件
导入接收方的公钥后,使用 -e(--encrypt)和 -r(--recipient)选项为其加密文件:
gpg -e -r tom@163.com report.pdf
这将生成 report.pdf.gpg,只有 Tom 的私钥才能解密。如果你尚未认证 Tom 的密钥,gpg 会发出警告:
gpg: 9F8E7D6C5B4A3F2E: There is no assurance this key belongs to the named user
Use this key anyway? (y/N)
只有在你已按上述方法验证过指纹的情况下,才应回答 y。要永久消除该警告,请使用 --sign-key 认证该密钥。
你可以指定多个接收方,他们中的每一个人都能解密同一个文件。如果你自己也想保留一份可读的副本,别忘了把自己也加进去:
gpg -e -r bob@example.com -r alice@example.com report.pdf
如果上述命令中没有 -r alice@example.com,那么即使是你——文件的加密者——也无法解密该文件。
7.签名与验证加密文件
加密可以隐藏内容,但无法证明文件的创建者。任何拥有 Bob 公钥的人都可以为他加密文件。添加 -s(--sign)选项即可弥补这一缺口:
gpg -s -u alice@example.com -e -r bob@example.com report.pdf
-u(--local-user)选项显式指定 Alice 的签名密钥,当你拥有多个私钥时这一点尤为重要。gpg 会要求输入私钥保护口令,然后一次性完成签名和加密。当 Bob 解密文件时,gpg 会自动验证签名:
gpg -o report.pdf -d report.pdf.gpg
输出示例:
gpg: encrypted with cv25519 key, ID 9F8E7D6C5B4A3F2E, created 2026-01-01
"Bob Example <bob@example.com>"
gpg: Signature made Thu 01 Jan 2026 11:42:10 CET
gpg: using EDDSA key 1A2B3C4D5E6F7A8B9C0D1E2F3A4B5C6D7E8F9A0B
gpg: Good signature from "Alice Example <alice@example.com>" [full]
Good signature 这一行同时确认了文件来自 Alice,且在签名后未被篡改。如果文件在传输过程中被修改,gpg 会报告签名无效(bad signature)。对于验证明文下载(而非加密文件),通常使用校验和(checksum)就足够了;相关内容可参考 sha256sum 和 md5sum 命令的指南。
8.加密目录
gpg 只能加密单个文件,不能直接加密目录。通常的做法是先用 tar 打包目录,再通过管道直接加密归档文件:
tar czf - project/ | gpg -c -o project.tar.gz.gpg
tar 命令将压缩后的归档输出到标准输出,gpg 则加密该数据流并写入 project.tar.gz.gpg,全程不会在磁盘上留下未加密的归档文件。
恢复目录时,反向执行管道操作:
gpg -d project.tar.gz.gpg | tar xzf -
当你需要为他人加密归档时,只需将 -c 替换为 -e -r name@example.com 即可。
9.速查表
| 任务 | 命令 |
|---|
| gpg -c file |
| gpg -o file -d file.gpg |
| gpg --full-generate-key |
| gpg --list-keys |
| gpg --armor --export you@example.com > public.asc |
| gpg --import public.asc |
| gpg -e -r name@example.com file |
| gpg -s -e -r name@example.com file |
| tar czf - dir | gpg -c -o dir.tar.gz.gpg |
| gpg -d dir.tar.gz.gpg | tar xzf - |