GnuPG 实现了 OpenPGP,用于文件和电子邮件的签名与加密、许多 Linux 发行版中的软件包签名,以及 Git 提交签名。本页的事实基于 Alpine 3.24.2 的软件包检查得出,即 GnuPG 2.4.9 搭配 libgcrypt 1.12.2。只给出用户 ID 时,gpg --quick-gen-key 会创建一个用于签名和认证的 Ed25519 主密钥,外加一个 Curve25519(cv25519)加密子密钥,两者都是版本 4 的密钥;除非指定过期时间,主密钥会在 1095 天——即三年——后过期。可以用 OpenPGP 查看器查看密钥和签名。
ECDSA 密钥可以在 P-256、P-384、P-521、secp256k1 以及三条 Brainpool r1 曲线上创建;nistp224 会报错“Unknown elliptic curve”。签名包把 r 和 s 作为两个 OpenPGP MPI 携带,既不是 DER,也不是定宽的 r‖s。P-256 签名默认使用 SHA-256;对 P-384 密钥指定 SHA-256 会报错“signing failed: Invalid length”,而对 P-256 密钥指定 SHA-512 则可以接受。
nonce 是确定性的:冻结时钟(--faked-system-time)后,对同一文件的两次签名逐字节相同,r 也与一个独立的 RFC 6979 实现一致,因此对同一数据签名两次不会以危险的方式重用 nonce。s 没有经过规范化,把 s 替换为 n − s 的签名也被判定为有效——凡是要求签名唯一的场合,这一点都需要注意。
Ed25519 签名使用旧版 EdDSA 格式(算法 22):R 和 S 是 MPI,而 Ed25519 签名的对象是对文件和签名中参与哈希的字段计算的 SHA-512 摘要,而不是文件本身。把 R 和 S 各自左侧填充到 32 字节后,R‖S 用 OpenSSL 针对该摘要验证通过,针对文件则验证失败——用通用的 Ed25519 库验证 gpg 签名,必须先计算 OpenPGP 摘要。Ed448 密钥以版本 5 的密钥包创建,这是 GnuPG 所遵循的 LibrePGP 草案的格式,而本次检查的默认密钥、ECDSA 密钥和 Ed25519 密钥都是版本 4;选择 Ed448 之前,应确认对方能读取版本 5。此版本没有后量子算法:公钥算法列表为 RSA、ELG、DSA、ECDH、ECDSA 和 EDDSA,ky768_cv25519 会作为未知曲线被拒绝。
在脚本中,应读取机器可读的 --status-fd 输出,而不是面向人的文本:有效签名给出 GOODSIG 和 VALIDSIG,退出状态为 0;针对其他数据的签名给出 BADSIG,退出状态为 1;截断的包给出 NODATA,退出状态为 2。gpg --export-ssh-key 加上指纹和 ! 时,会为 ECDSA 和 Ed25519 密钥写出一行 OpenSSH 公钥,而 --export 和 --export-secret-keys 写出的是 OpenPGP 包。