GnuPG 加密与签名速查表 - GPG 加密解密命令大全

GPG 的日常动作可以压成四个:生成密钥对、把公钥给对方、对方用你的公钥加密、你用私钥解密或签名。真正容易翻车的不是命令而是密钥本身——私钥丢了就无法恢复,所以生成后第一件事是导出备份;收到他人公钥也别直接信任,要核对指纹确认没有被中间人替换。本表按密钥生成与管理、导入导出、加密解密、签名验证、信任与密钥服务器、Git 签名与实用分组,把整条链路串起来。日常使用时还有两个习惯值得保持:用 -a 输出 ASCII armored 形式以便放进邮件或聊天窗口;用 gpg-agent 缓存密码,少输多次口令;给密钥加过期时间并定期轮换,比一次性设置永不过期更容易应对审计。

系统与运维·共 37 条命令·最后更新 2026-07-21
gpg加密签名安全

典型使用场景

面向需要「可验证的身份」而不是「信任某个人」的场景:给 Git 提交和 tag 签名、把发布包签名让人验证、把机密文件加密给同事、给自己签发密钥做备份。GnuPG 的失败原因往往很具体也很反直觉:gpg-agent 没起来时一切卡死、导入了公钥却忘了 trust 导致验证仍提示「未经签名」、密钥服务器上一个字符的邮箱输错就静默返回空结果。所以本表的重点不只是命令怎么写,而是每一步做完后**去哪儿看结果**。

密钥生成与管理 8

gpg --full-generate-key
交互式生成密钥对(可选算法和有效期)
gpg --quick-generate-key "Name <email>"
快速生成密钥
gpg --list-keys
列出所有公钥
gpg --list-secret-keys
列出所有私钥
gpg --list-keys KEYID
查看指定密钥详情
gpg --edit-key KEYID
交互式编辑密钥(添加子密钥、设置过期等)
gpg --delete-key KEYID
删除公钥
gpg --delete-secret-key KEYID
删除私钥

密钥导入导出 6

gpg --export -a KEYID > pubkey.asc
导出公钥为 ASCII 文件
gpg --export-secret-keys -a KEYID > private.asc
导出私钥(务必妥善保管)
gpg --import pubkey.asc
导入公钥
gpg --import private.asc
导入私钥
gpg --send-keys KEYID --keyserver keyserver.ubuntu.com
上传公钥到密钥服务器
gpg --recv-keys KEYID
从密钥服务器获取公钥

加密与解密 6

gpg -e -r recipient@domain.com secret.txt
用收件人公钥加密文件
gpg -e -r user@domain.com -o secret.txt.gpg secret.txt
加密并指定输出文件名
gpg -d secret.txt.gpg > secret.txt
解密文件并输出到指定文件
gpg -c secret.txt
对称加密(仅用密码,无需公钥)
gpg -d secret.txt.gpg
解密对称加密文件
echo "message" | gpg -e -r user@domain.com
加密管道输入的文本

签名与验证 6

gpg -s document.txt
生成签名(生成 .gpg 二进制文件)
gpg --clear-sign document.txt
生成明文签名(可读且含签名)
gpg -b document.txt
生成分离签名(.sig 文件,原文不变)
gpg --verify document.txt.sig document.txt
验证分离签名
gpg --verify document.txt.asc
验证明文签名文件
gpg --detach-sign -a file.tar.gz
生成 ASCII 分离签名

信任与密钥服务器 5

gpg --edit-key KEYID > trust
设置密钥信任级别(交互式)
gpg --sign-key KEYID
对他人公钥签名(信任背书)
gpg --refresh-keys
从密钥服务器刷新所有密钥
gpg --search-keys "user@domain.com"
在密钥服务器搜索公钥
gpg --fingerprint KEYID
查看密钥指纹用于核对身份

Git 签名与实用 6

git config --global user.signingkey KEYID
设置 Git 使用的签名密钥
git config --global commit.gpgsign true
开启所有提交自动签名
git commit -S -m "message"
创建 GPG 签名提交
git tag -s v1.0 -m "release"
创建 GPG 签名标签
git verify-commit HEAD
验证最新提交的签名
gpgconf --kill gpg-agent
重启 gpg-agent(解决密码缓存问题)

参数矩阵

参数作用示例
--quick-generate-key非交互一条命令出密钥,适合脚本;无交互选项时用它代替 --full-generate-keygpg --quick-generate-key "Name <email>"
--recv-keys从密钥服务器拉取他人公钥;必须配 KEYID 或邮箱,邮箱拼错不会报错只是拉不到gpg --recv-keys KEYID
--clear-sign生成明文签名,正文可读且内嵌签名,适合邮件与可读性优先的场景gpg --clear-sign document.txt
commit.gpgsign让 git 每次提交自动 GPG 签名,验证方可追溯到密钥指纹git config --global commit.gpgsign true
gpgconf --kill gpg-agent重启代理进程,解决改密码后不弹口令、旧口令一直有效的僵死状态gpgconf --kill gpg-agent

易错点与避坑指南

现象gpg --import 后 gpg --verify 仍提示签名不是来自这个密钥,甚至出现 WARNING。

原因公钥导入了但没有建立信任,gpg 不知道该密钥是否可信。

处置先 gpg --fingerprint KEYID 核对指纹,再 gpg --edit-key KEYID 进入后 trust 设成 ultimate,退出后重新验证。

现象gpg --recv-keys 命令跑完没有任何输出,也没报错,但公钥并不在本地。

原因邮箱拼错或密钥服务器上根本没有对应密钥,收到的响应为空。

处置改用 gpg --search-keys "user@domain.com" 先搜到确切 KEYID/指纹,再 gpg --recv-keys。

现象改了私钥密码后 gpg 仍然只认旧密码,或操作长时间卡住不返回。

原因gpg-agent 缓存了旧的 passphrase 状态,进程僵死。

处置执行 gpgconf --kill gpg-agent 重启代理后再操作。

现象git commit -S 卡在终端里不返回,CI 上直接失败。

原因gpg 需要交互式输入口令,无 TTY 的环境(CI、定时任务)里必然挂住。

处置CI 中改用 gpg --batch --pinentry-mode loopback 配合 gpg-agent 缓存,并在提交前 gpgconf --kill gpg-agent 验证缓存可用。

现象导出的私钥文件随手提交进了仓库或发到了聊天工具。

原因gpg --export-secret-keys -a KEYID 输出的是可直接使用的私钥,泄露即失去全部身份。

处置立即 gpg --delete-secret-key KEYID 并吊销对应公钥,重新生成密钥对;私钥只进密码管理器或离线备份。

排障路径

  1. 1签名验证失败时,先核对指纹再看信任

    gpg --fingerprint KEYID && gpg --verify document.txt.sig document.txt

    指纹必须与对方公开渠道公布的完全一致;一致但仍警告,说明是 trust 未设,不是密钥不对。

  2. 2按邮箱找密钥

    gpg --search-keys "user@domain.com"

    拿到 KEYID 后用 gpg --recv-keys KEYID 精确拉取,比直接 recv 邮箱可靠。

  3. 3确认本机公私钥齐全

    gpg --list-keys && gpg --list-secret-keys

    --list-keys 有而 --list-secret-keys 没有,说明私钥没导入或已被删除,签名会失败。

  4. 4代理状态异常时重置

    gpgconf --kill gpg-agent

    口令缓存失效、改密码后不生效、gpg 卡死,都先用这条重置代理。

命令示例

非交互地生成一对新密钥

gpg --quick-generate-key "Name <email>"

默认算法与子密钥已够日常签名和加密使用;生成后用 gpg --list-secret-keys 确认私钥在本地。

用收件人公钥加密并指定输出文件名

gpg -e -r user@domain.com -o secret.txt.gpg secret.txt

加密只需要对方的公钥;对方用自己的私钥解密,公钥泄露不构成风险。

生成明文签名:正文可读且内嵌签名

gpg --clear-sign document.txt

输出是 .asc 里的可读正文加签名,验证只需 gpg --verify document.txt.asc。

验证最近一次 Git 提交的签名

git verify-commit HEAD

要签提交需先 gpg config 层面设置 signingkey 并开启 commit.gpgsign(用 git config --global),否则提交根本没有签名。

常见坑与注意事项

  • 导出的私钥文件(private.asc 之类)绝不能进 Git 仓库或发到聊天工具,一旦泄露等于身份被完整克隆。
  • 把信任等级设为 ultimate 之前必须线下核对指纹,trust 是在声明「我确认这把钥匙属于这个人」,不是随手点的按钮。
  • 改过私钥密码后若仍只认旧密码或命令卡住,先 gpgconf --kill gpg-agent 重启代理,再排查别的原因。
  • 签名有效不等于身份可信:gpg --verify 通过后仍要看 WARNING 与信任等级,必要时用 gpg --fingerprint 核对。
  • 加密前先确认已导入对方公钥(gpg --recv-keys 后 gpg --list-keys 复查),缺公钥时不会报错,只是根本收不到。

提示

  • Git commit 签名:git config --global commit.gpgsign true,配合 GPG 密钥使用。
  • gpg --armor (-a) 可以生成 ASCII 格式的密钥或签名,方便文本传输。
  • 密钥备份:导出私钥 gpg --export-secret-keys -a KEYID > private.asc,妥善保管。
  • gpg-agent 可以缓存密码,避免每次解密都输入密码。
  • gpgconf --kill gpg-agent 可以重启 agent,解决密码缓存异常问题。
  • 密钥指纹是验证密钥真伪的重要方式,导入他人公钥后务必核对指纹。
  • 生成时带 --quick-generate-key "姓名 <邮箱>" 少一堆交互,subkey 的默认算法已够日常签名与加密使用。
  • gpg --list-keys --keyid-format LONG 显示完整 KEYID,撤销时用 --revoke 指定该 ID 比短指纹可靠。
  • 导入他人公钥后先 gpg --fingerprint 查看,信任等级用 --edit-key 设为 ultimate 前务必线下核对指纹。

常见问题

gpg --verify 明明说签名有效,却还是提示签名不来自这个密钥?

签名有效只说明数据和签名对得上,不说明你对签名者建立了信任。先用 gpg --fingerprint KEYID 核对指纹是否与对方线下提供的一致,再用 gpg --edit-key KEYID 把信任等级设上去。指纹对不上就不要继续,那说明密钥不是同一个人生成的那一把。

gpg --recv-keys 跑完没输出也没报错,公钥却不在本地?

最常见的原因是标识写错了,邮箱差一个字符时命令不会报错,只是静默地什么也没拉到。先用 gpg --search-keys "user@domain.com" 在密钥服务器上搜一遍确认标识拼写,再把搜索结果里的 KEYID 传给 --recv-keys。导入后用 gpg --list-keys 确认它确实出现在公钥列表里。

对称加密和用对方公钥加密该怎么选?

用密码的 gpg -c 不需要任何公钥,适合随手加密一个文件,缺点是密码得自己 securely 保管和传递。用公钥的 gpg -e -r user@domain.com 适合发给固定的人,你只持有他的公钥,密码由他自己的私钥解锁,多个收件人可以各自用自己的密钥解开。

分离签名和明文签名验证方式有什么不同?

gpg -b 生成的是分离签名,原文件不动、签名单独落在 .sig,验证时要把两个文件一起给它:gpg --verify document.txt.sig document.txt。gpg --clear-sign 生成的是明文签名,签名内嵌在文件里,验证只需给这一个文件:gpg --verify document.txt.asc。选哪种取决于接收方更在意原文可读还是原文件不被改动。

改了私钥密码之后 GPG 仍然只认旧密码,或者操作一直卡住?

这是 gpg-agent 的缓存没刷新,它还拿着改密码之前的口令在内存里。执行 gpgconf --kill gpg-agent 重启代理进程,之后所有涉及私钥的操作都会重新走一遍口令校验。git commit -S 之类的命令在终端里卡住不动,也是同一个原因,签名前把 agent 重启掉即可。

官方参考来源

下方为命令对应的官方权威文档,供你核对最新用法与深入查阅。

由 巧匠 维护

公开更新于 2026年7月21日,内容持续校对官方文档。

联系我们

命令或描述有误?提交反馈、商务合作或产品建议都可发送邮件给我们。

联系我们