OpenPGP / GPG

返回开发工具

OpenPGP 是开放的加密标准(RFC 4880),GPG(GNU Privacy Guard)是其最常用的开源实现。广泛用于邮件加密、文件签名、代码签名、软件包验证等场景。


PGP / OpenPGP / GPG 的关系

PGP(Pretty Good Privacy)
  └── Phil Zimmermann 1991 年发明的商业加密软件
  └── 后演变为标准 OpenPGP(RFC 4880 / RFC 9580)

OpenPGP
  └── 开放标准,任何软件可实现
  └── 描述数据格式、算法、操作语义

GPG(GnuPG,GNU Privacy Guard)
  └── OpenPGP 标准的开源免费实现
  └── 命令行工具 gpg / gpg2
  └── 跨平台:Linux / macOS / Windows

核心概念

非对称加密与密钥对

私钥(Private Key)→ 自己保密保存,用于:解密、签名
公钥(Public Key)  → 公开发布,用于:加密、验签

加密:用接收方公钥加密 → 只有接收方私钥能解密
签名:用自己私钥签名  → 任何人用你的公钥可验证

信任模型:Web of Trust vs PKI

模型代表说明
Web of Trust(信任网)OpenPGP人工互相签名对方公钥,形成去中心化信任网络
PKI(公钥基础设施)TLS 证书由 CA(证书颁发机构)中心化签发信任

密钥 ID 与指纹

密钥指纹(Fingerprint):40 位十六进制字符串,全局唯一标识一把密钥
  例:ABCD 1234 5678 90EF ABCD  1234 5678 90EF ABCD 1234

密钥 ID:指纹的后 8 位(Short)或后 16 位(Long),方便引用
  例:5678 90EF ABCD 1234(Long Key ID)

始终用完整指纹验证密钥,短 ID 可被伪造(碰撞攻击)

密钥结构

OpenPGP 密钥是一组子密钥的集合:

主密钥(Primary Key / Certification Key)
  └── 作用:认证其他子密钥、签名其他人的公钥
  └── 算法:Ed25519(推荐)或 RSA 4096
  └── 应离线保存,日常不使用

子密钥(Subkeys)
  ├── 签名子密钥(Sign)    → 签署文件、Git 提交
  ├── 加密子密钥(Encrypt) → 接收加密邮件/文件
  └── 认证子密钥(Authenticate)→ SSH 登录(可选)

UID(User ID):绑定到主密钥的身份信息
  格式:Name <email@example.com>
  可有多个 UID(多个邮箱)

使用子密钥的好处:主密钥可离线保存(甚至放 USB 或 YubiKey),日常操作用子密钥,子密钥泄露只需吊销该子密钥,主密钥安全不受影响。


安装

# macOS
brew install gnupg
 
# Ubuntu/Debian
sudo apt install gnupg
 
# Windows
# 下载 Gpg4win(含 Kleopatra 图形界面)
# https://www.gpg4win.org/

密钥管理

生成密钥

# 交互式生成(推荐,默认选 Ed25519)
gpg --full-generate-key
 
# 快速生成(Ed25519 签名 + Cv25519 加密子密钥)
gpg --quick-gen-key "张三 <zhangsan@example.com>" ed25519 default 2y
# 最后参数:有效期(2y=2年,0=永不过期)

查看密钥

gpg --list-keys                          # 列出所有公钥
gpg --list-secret-keys                   # 列出所有私钥
gpg --list-keys --keyid-format LONG      # 显示完整 Key ID
gpg --fingerprint zhangsan@example.com  # 查看指纹
 
# 输出示例:
# pub   ed25519/ABC1234567890DEF 2024-01-01 [SC] [expires: 2026-01-01]
#       ABCD1234ABCD1234ABCD1234ABC1234567890DEF
# uid           [ultimate] 张三 <zhangsan@example.com>
# sub   cv25519/DEF0987654321ABC 2024-01-01 [E] [expires: 2026-01-01]

导出与导入

# 导出公钥(分享给他人)
gpg --armor --export zhangsan@example.com > pubkey.asc
 
# 导出私钥(备份!请妥善保管)
gpg --armor --export-secret-keys zhangsan@example.com > privkey.asc
 
# 导入他人公钥
gpg --import their_pubkey.asc
 
# 从密钥服务器导入
gpg --keyserver hkps://keys.openpgp.org --recv-keys ABC1234567890DEF
 
# 上传公钥到密钥服务器
gpg --keyserver hkps://keys.openpgp.org --send-keys ABC1234567890DEF

吊销证书

# 创建吊销证书(密钥生成后立即做,存放在安全位置)
gpg --gen-revoke zhangsan@example.com > revoke.asc
 
# 吊销密钥(私钥丢失/泄露时使用)
gpg --import revoke.asc
gpg --keyserver hkps://keys.openpgp.org --send-keys ABC1234567890DEF

信任级别

# 设置信任级别(导入他人密钥后)
gpg --edit-key their_key_id
gpg> trust
# 选择:2=不信任 3=勉强信任 4=完全信任 5=绝对信任(自己的密钥)
gpg> quit

常用操作

文件加密与解密

# 加密文件(给指定收件人,需对方公钥)
gpg --recipient zhangsan@example.com --encrypt secret.txt
# 生成 secret.txt.gpg(二进制)
 
# ASCII 装甲格式(纯文本,便于邮件传输)
gpg --armor --recipient zhangsan@example.com --encrypt secret.txt
# 生成 secret.txt.asc
 
# 解密(需本机私钥)
gpg --decrypt secret.txt.gpg > secret.txt
gpg --output secret.txt --decrypt secret.txt.gpg

文件签名与验证

# 生成独立签名文件(.sig)
gpg --detach-sign --armor file.tar.gz
# 生成 file.tar.gz.asc
 
# 签名并嵌入(clearsign,签名与原文合并,适合文本)
gpg --clearsign message.txt
# 生成 message.txt.asc
 
# 验证签名(需签名者公钥已导入)
gpg --verify file.tar.gz.asc file.tar.gz
# 输出包含:Good signature from "..." 表示验证成功

Git 提交签名

# 配置 Git 使用 GPG 签名
git config --global user.signingkey ABC1234567890DEF
git config --global commit.gpgsign true    # 所有提交自动签名
git config --global tag.gpgsign true       # 所有标签自动签名
 
# 手动签名提交
git commit -S -m "feat: add feature"
 
# 验证提交签名
git log --show-signature -1
git verify-commit HEAD
 
# GitHub 显示绿色 "Verified" 标识
# 需要将公钥上传到 GitHub: Settings → SSH and GPG keys → New GPG key

Maven Central artifact 签名

发布到 Maven Central 时,所有构件必须用 GPG 签名:

# 签名 jar 文件(Maven 插件会自动调用 gpg)
gpg --armor --detach-sign library.jar
# 生成 library.jar.asc(签名文件需和 jar 一起上传)

→ 详细发布流程见 Maven Central发布


Linux 软件包验证

# 导入发行版 GPG 公钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor \
  -o /usr/share/keyrings/docker-archive-keyring.gpg
 
# 验证下载文件的 GPG 签名
gpg --verify sha256sum.txt.gpg sha256sum.txt
 
# APT 软件包签名(Debian/Ubuntu 自动验证)
apt-key list

SSH 认证(可选)

GPG 认证子密钥可替代 SSH 密钥,用于 SSH 登录:

# 启用 GPG agent 的 SSH 支持
echo "enable-ssh-support" >> ~/.gnupg/gpg-agent.conf
gpg-connect-agent reloadagent /bye
 
# 导出认证子密钥的 SSH 公钥
gpg --export-ssh-key zhangsan@example.com > gpg_ssh_key.pub
 
# 配置 SSH_AUTH_SOCK
export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)

密钥最佳实践

实践说明
设置过期时间建议 1~2 年,到期可延长;丢失也不会永久有效
立即生成吊销证书密钥生成后立刻做,存到 U 盘或打印纸存档
主密钥离线存储日常只用子密钥,主密钥放 U 盘或硬件令牌
使用硬件令牌YubiKey / Nitrokey 存储私钥,私钥永不离开硬件
定期轮换子密钥子密钥设置 1 年有效期,到期生成新子密钥
上传公钥到密钥服务器keys.openpgp.org 支持邮件验证
备份私钥加密存储导出私钥后再用强密码加密,多地备份

常用密钥服务器

服务器说明
hkps://keys.openpgp.org支持 HKPS,需邮件验证,推荐
hkps://keyserver.ubuntu.comUbuntu 维护,稳定可靠
hkps://pgp.mit.eduMIT 维护的经典服务器
hkps://keys.mailvelope.comMailvelope 邮件加密专用

相关

  • Git — 配置 GPG 签名提交与标签
  • Maven Central发布 — 发布到 Maven Central 需要 GPG 签名构件
  • TLS — PKI 体系与 Web of Trust 的对比
  • HTTPS — Web 上的 HTTPS 部署