2026 年,用最硬核的方式打开 GPG(一)

本文是《2026 年,用最硬核的方式打开 GPG》系列文章的第 1 篇。本文将详细介绍如何从头开始,创建属于自己的 GPG 密钥对,并生成对应的吊销证书,以及导出对应的备份文件。

下一篇文章将会介绍如何使用生成的密钥。

§00. 前言

关于 GPG,PGP,非对称加密等等这些概念,各种百科和科普文章已经很多了,本文不再赘述。

这里简单解释一下俺为什么要折腾这个:

  1. 基于可靠的数学原理,它有能力在赛博空间证明“俺是谁”(安全的鉴权)。
  2. 基于可靠的数学原理,它有能力证明俺的文件未经篡改(安全的签名)。
  3. 基于可靠的数学原理,它有能力避免俺不想公开的文件被窃取(安全的加密)。

本系列暂不会涉及 Yubikey 等硬件的配置(因为俺没有……),如果后续有涉及,会更新新的文章来记录。

本文较长,各位可以根据目录自行跳转到感兴趣的部分查看。

§01. 生成密钥对

在开始操作之前,可能有比较帅的网友要问了:“哎,你不是在 《使用 GPG 签名 Git Commit》 这篇文章中已经生成过 GPG 密钥对,而且已经用它来给 GitHub 上的 commit 签名了吗?”

确实,但是:

  1. 当时生成的密钥对是 RSA4096 算法,性能较差,而且公钥导出时很长,不方便粘贴。
  2. RSA 算法依赖随机数生成器的质量,安全性不够。
  3. 当时图方便,只生成了一个全功能的主密钥,没有分离权限,不够安全。
  4. Key ID 不够靓,不能装逼,而且换电脑时忘了备份,找不到了……

所以这次从头开始,使用性能更好安全性也更高的 Ed25519 算法,生成一个四合一的密钥对,进行一次充分兼顾当下环境的安全和效率的最佳实践。

通过本小节的操作,将会生成一个四合一的密钥:

  1. 主密钥(后续称为 EC):Ed25519 算法,具有 C(Certify,认证)权限
  2. 签名子密钥(后续称为 ES):Ed25519 算法,具有 S(Sign,签名)权限
  3. 鉴权子密钥(后续称为 EA):Ed25519 算法,具有 A(Authenticate,身份验证 / 鉴权)权限
  4. 加密子密钥(后续称为 CE):Cv25519 算法,具有 E(Encrypt,加密)权限

如果你对密钥的指纹(40 位十六进制数字,末 16 位作为 Key ID)没有特殊要求,或者你看不懂这句话,那么直接按照【普通操作】这一小节的步骤操作,然后跳过【高端操作】小节,从【生成吊销证书】继续阅读。

如果你也想像俺一样使用类似 2BB2666666666666 这样 炫酷 的指纹,那么可以跳过【1.1 普通操作】这一小节,详细研究【1.2 高端操作】小节。

§1.1 普通操作

  1. 终端输入 gpg --full-generate-key.
  2. 选择 ECC (sign and encrypt), 俺这里是输入 9, 回车确认。
  3. 选择 Curve 25519, 俺这里是输入 1, 回车确认。
  4. 选择密钥的过期时间,俺选择 0 也就是永不过期,各位可以按需选择。
  5. 输入 y 后回车确认。
  6. Real name 不一定使用真名,可以随便填写一个想要展示给别人看的名字。
  7. Email address 输入邮箱地址。
  8. Comment 个性签名或者别的想展示给别人看的信息,没什么想写的可以留空,直接回车跳过。
  9. 此时会将 uid 信息再展示一次,确认无误后输入 O 确认。
  10. 设定一个高强度密码,用键盘的方向键切换选项,输入两次后选择 OK 保存。

此时 gpg 会输出类似下面的信息:

1
2
3
4
5
6
7
8
gpg: directory '/home/he-sb/.gnupg/openpgp-revocs.d' created
gpg: revocation certificate stored as '/home/he-sb/.gnupg/openpgp-revocs.d/67992DB2CEA0D623DC761430E379BEB325A8928D.rev'
public and secret key created and signed.

pub   ed25519 2026-02-01 [SC]
      67992DB2CEA0D623DC761430E379BEB325A8928D
uid                      he-sb <[email protected]>
sub   cv25519 2026-02-01 [E]

这里的 67992DB2CEA0D623DC761430E379BEB325A8928D 就是主密钥和公钥的指纹,最后 16 位 E379BEB325A8928D 就是 Key ID,也就是最后展示给别人的公钥 ID.

注意到这里生成的密钥对,主密钥同时具有 SC 权限,而且只有一个 E 权限的子密钥,不符合权限分离的要求。所以接下来需要去掉主密钥的 S 权限,然后新增 ESEA 子密钥:

  1. 编辑主密钥:gpg --edit-key <EC_ID>, 其中 <EC_ID> 是主密钥的 Key ID.
  2. 修改主密钥的权限,去掉 S, 只保留 C.
    1. 输入 change-usage 后回车,然后输入 S 回车,仔细查看 Current allowed actions: 这行,后面只有 Certify 说明 S 权限去掉了。
    2. 输入 Q 回车,输入刚才设定的密码后回车确认。
  3. 添加 ES 子密钥。输入 addkey 回车确认。
    1. 选择 ECC (sign only), 俺这里是输入 10, 回车确认。
    2. 选择 Curve 25519, 俺这里是输入 1, 回车确认。
    3. 选择子密钥的过期时间,俺选择 0 也就是永不过期,各位可以按需选择。
    4. 输入两次 y 回车,输入刚才设定的密码后回车确认。
  4. 添加 EA 子密钥。因为 A 权限的子密钥没法直接添加,所以先添加一个 S 子密钥,然后再修改它的权限(因为这两种权限的密钥,加密算法都是 Ed25519,所以生成时不需要区分,只需生成后修改权限)。
    1. 先按上一步的操作,再添加一个 S 子密钥。
    2. 然后输入 key 3 选择第 3 个子密钥,也就是最后添加的,第 2 个 S 子密钥,此时这个子密钥的 Key ID 旁会多出一个 * 号。
    3. 输入 change-usage, 回车。
    4. 先输入 S 后回车,接着输入 A 后再回车(顺序不重要,这一步目的是去掉原本的 S 权限,添加 A 权限)。
    5. 输入两次 y 回车,输入刚才设定的密码后回车确认。
  5. 最后输入 save 保存并退出。

最后执行 gpg --list-keys --keyid-format LONG 确认一下生成的密钥,输出应该类似这样:

1
2
3
4
5
6
7
8
/home/he-sb/.gnupg/pubring.kbx
--------------------------------
pub   ed25519/E379BEB325A8928D 2026-02-01 [C]
      67992DB2CEA0D623DC761430E379BEB325A8928D
uid                 [ultimate] he-sb <[email protected]>
sub   cv25519/98D55538F914D4A9 2026-02-01 [E]
sub   ed25519/84B2DB48987F8778 2026-02-01 [S]
sub   ed25519/030F72DCC734450B 2026-02-01 [A]

其中 E379BEB325A8928D 就是 EC 的 Key ID, 98D55538F914D4A9CE 的 Key ID, 84B2DB48987F8778ES 的 Key ID, 030F72DCC734450BEA 的 Key ID.

  1. 公开的公钥信息,别人看到的是主密钥的 <EC_ID>.
  2. 加密时,对方看到的加密指纹是 <CE_ID>.
  3. 签名时,比如 git commit, 对方看到的是 <ES_ID>.
  4. 鉴权时,对方看到的是 <EA_ID>.

§1.2 高端操作

计算 GPG 靓号的原理部分,可以参考 @DejavuMoe 大佬的 某科学的 PGP 算号指南 这篇文章,本文就不再赘述。

至于具体用来算号的工具,这里要特别感谢 @TransparentLC 大佬的 GPU 算号项目:

这两个项目原理是一样的,只是实现方式不同。webgl-vanity-gpg 只需要浏览器打开一个网页就可以开始算,通过 WebGL 调用显卡的图形能力;而 opencl_vanity_gpg 提供了编译好的二进制可执行文件,支持 Windows, Mac, Linux 三个平台的命令行环境,通过 OpenCL 调用显卡的计算能力。

基准性能对比可以参考两个项目的 README,俺这里提供一下自己的实测值(系统均为 Windows 11 LTSC 2024 IoT 版):

显卡WebGL 速率 (hash/s)OpenCL 速率 (hash/s)
AMD RX 7700 XT7.14B13.67B
AMD Radeon 680M1.12B2.41B

实测下来 OpenCL 版的效率明显要更高,算号速度是 WebGL 版的 2 倍左右。如果你条件有限,只能用 WebGL 版,那么也是可以的,不过有条件的话还是推荐使用 OpenCL 版,指定靓号格式更加方便,性能也显著更好。

§1.2.1 算号

这部分最为枯燥,任选上面提到的两个项目之一,参考项目文档,指定你喜欢的靓号格式,开始挂机。

俺这里使用的是 OpenCL 版,在 PowerShell 中开始算号:

1
2
3
4
5
6
# 假设想要的靓号是 13 连号的 Ed25519 类型的密钥
# 用作 C 权限的主密钥或 S/A 权限的子密钥
.\opencl_vanity_gpg.exe --output opencl-keys --pattern 'Z ZZZZ ZZZZ ZZZZ'
# 如果需要生成 13 连号的 Cv25519 类型的密钥
# 用作 E 权限的子密钥
.\opencl_vanity_gpg.exe --output opencl-keys -c cv25519--pattern 'Z ZZZZ ZZZZ ZZZZ'

命令执行后,会开始不断循环算号,每个生成的靓号对应的私钥文件都会保存在当前路径下的 opencl-keys 文件夹内,文件名都是类似 8A01DEE8BE638FCE17191021799BBBBBBBBBBBBB-sec.asc 的形式,其中 -sec.asc 之前的部分,即 8A01DEE8BE638FCE17191021799BBBBBBBBBBBBB 是完整的 40 位密钥指纹,这部分的最后 16 位,即 799BBBBBBBBBBBBB 是 Key ID,也就是期待中的靓号。定期查看其中有没有中意的,生成了满意的靓号之后就可以回到 PowerShell 窗口 Ctrl + C 结束算号程序了。

中间等待的时长取决于你指定的靓号格式,以及一点运气。一般指定的位数越多,时间越长。

WebGL 版查看项目说明即可,操作上更为简单直观,此处不再赘述。如果你使用其他算号项目,那么自行研究。

最终会得到 4 个密钥文件:

  1. 准备用作主密钥的 EC-sec.asc
  2. 准备用作签名子密钥的 ES-sec.asc
  3. 准备用作鉴权子密钥的 EA-sec.asc
  4. 准备用作加密子密钥的 CE-sec.asc

由于算号程序生成的密钥都是一个 Ed25519 主密钥和一个 Cv25519 子密钥成对生成的,所以这 4 个密钥文件其实是 4 个密钥对:

  • EC ES EA 这三个密钥对,其中的 Ed25519 主密钥的 Key ID 都是靓号,而他们绑定的 Cv25519 子密钥的 Key ID 都是随机的。后续会通过一些操作剥离这三个 Cv25519 子密钥,仅保留三个 Ed25519 靓号。
  • CE 这个密钥对,比较特殊。它的 Ed25519 主密钥的 Key ID 是随机的,而 Cv25519 子密钥的 Key ID 是后续待使用的靓号(当然了,这是因为生成它时,将筛选靓号的规则仅应用在了子密钥上)。后续操作会剥离它的 Ed25519 主密钥,仅保留 Cv25519 靓号。
    • 不过这会导致一个不便的情况,密钥对的文件名是主密钥的指纹,只看文件名是看不出来 Cv25519 子密钥的 Key ID 是否是想要的靓号的。俺个人建议:
      • 要么生成 CE 子密钥时使用 WebGL 版本的算号程序,网页内点击每个主密钥指纹时,下方会同时显示主密钥和子密钥的指纹,方便查看。
      • 要么查看 PowerShell 内输出的日志,确定哪个密钥对中的 Cv25519 子密钥是准备使用的靓号。

保留好这 4 个密钥文件,下面开始缝合操作,把他们合并为一个完整的密钥对。

§1.2.2 缝合密钥

消耗一些电费和时间后,终于得到了 4 个满意的靓号。下面来将它们合并起来,将三个 Ed25519 类型的靓号的其中一个作为主密钥,另外两个和 Cv25519 类型的靓号一起作为子密钥组合起来,最终得到一个四合一的密钥。

首先必须确认每个密钥的创建时间,作为主密钥的 EC 必须是创建时间最早的那个,三个子密钥的创建时间则互不影响。

下面先合并 ECES,其中 EC 作为主密钥,ES 作为子密钥:

  1. 导入两个密钥:gpg --import EC-sec.asc ES-sec.asc.
  2. 查看密钥的时间戳信息:gpg --list-keys --keyid-format LONG --with-colons.
    • 输出的信息中,在 16 位 Key ID 右侧的 10 位数字就是时间戳,找到子密钥 ES 的时间戳,记为 T_ES.
  3. 查看密钥的 keygrip: gpg --list-keys --keyid-format LONG --with-keygrip.
    • 输出的信息中,找到子密钥 ES 的 keygrip, 记为 K_ES.
  4. 编辑主密钥:gpg --expert --faked-system-time="T_ES\!" --ignore-time-conflict --edit-key <EC_ID>.
    • 注意 T_ES 后面紧跟着的 \!,一定不能漏掉。
    • <EC_ID> 是主密钥 EC 的 Key ID.
  5. 首先删除不需要的子密钥。由于当前只有一个子密钥,所以输入 key 1 选中第 1 个子密钥,如果有多个,按照子密钥的序号修改数字来选中,选中后的子密钥旁会有一个 * 号。输入 delkey 删除这个子密钥,回车确认。询问是否确认时,输入 y 回车确认删除。
  6. 然后输入 addkey 添加子密钥,回车确认。
    1. 选择从现有密钥导入(Existing key),俺这里是输入 13, 回车确认。
    2. 输入第 3 步记录的 K_ES, 回车确认。
    3. 此时需要选择导入的子密钥的权限,因为 ES 是 Ed25519 算法,可选的有 S 或者 A 权限,默认是 S,不需要修改,输入 Q 后回车完成。
      • 如果此时缝合的是 EA, 那么需要先输入 S 后回车,接着输入 A 后再回车(顺序不重要,这一步目的是去掉默认的 S 权限,添加 A 权限)。
      • 如果此时缝合的是 CE, 因为是 Cv25519 算法,权限只能是 E, 不需要修改)。
    4. 选择子密钥的过期时间,俺选择 0 也就是永不过期,各位可以按需选择。
    5. 输入两次 y 确认。
  7. 修改主密钥的权限,默认是 SC, 这里需要去掉 S, 只保留 C.
    1. 输入 change-usage 后回车,然后输入 S 回车,仔细查看 Current allowed actions: 这行,后面只有 Certify 说明 S 权限去掉了。
    2. 输入 Q 退出。
  8. 修改 uid 信息。算号程序默认的 uid 是 Dummy <[email protected]>, 需要修改成自己的信息。
    1. 输入 adduid 后回车。
    2. Real name 不一定使用真名,可以随便填写一个想要展示给别人看的名字。
    3. Email address 输入邮箱地址。
    4. Comment 个性签名或者别的想展示给别人看的信息,没什么想写的可以留空,直接回车跳过。
    5. 此时会将 uid 信息再展示一次,确认无误后输入 O 确认。此时应该有两个 uid 信息,第一个是默认的 Dummy <[email protected]>, 第二个是刚刚添加的自己的信息。
      • 如果有想修改的,可以根据提示输入字母修改对应的信息。
    6. 输入 uid 1 选中第 1 个 uid, 此时 Dummy <[email protected]> 左侧会多出一个 * 号,输入 deluid 删除这个 uid, 再输入 y 确认删除即可。
  9. 输入 save 保存并退出。

这样 ECES 就合并好了,接下来参考上面的步骤,分别将 EACE 也作为子密钥合并给 EC.

全部缝合完后,执行 gpg --list-keys --keyid-format LONG 查看主密钥和三个子密钥的 Key ID 和权限信息是否正确无误,输出应该类似下面这样:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
gpg: checking the trustdb
gpg: no ultimately trusted keys found
/home/he-sb/.gnupg/pubring.kbx
--------------------------------
pub   ed25519/<EC_ID> 2016-07-20 [C]
      <EC_fingerprint>
uid                 [ unknown] he-sb <[email protected]>
sub   ed25519/<ES_ID> 2022-01-21 [S]
sub   ed25519/<EA_ID> 2022-01-21 [A]
sub   ed25519/<CE_ID> 2022-01-21 [E]

pub   ed25519/<ES_ID> 2022-01-21 [SC]
      <ES_fingerprint>
uid                 [ unknown] Dummy <[email protected]>
sub   cv25519/<random_ID> 2022-01-21 [E]

pub   ed25519/<EA_ID> 2018-03-14 [SC]
      <EA_fingerprint>
uid                 [ unknown] Dummy <[email protected]>
sub   cv25519/<random_ID> 2018-03-14 [E]

pub   ed25519/<random_ID> 2025-11-04 [SC]
      <random_fingerprint>
uid                 [ unknown] Dummy <[email protected]>
sub   cv25519/<CE_ID> 2025-11-04 [E]

忽略下面的三个密钥对信息,后续会清理掉。只关注 <EC_ID> 的权限,uid, 子密钥及其权限。确认无误后:

  1. 导出合并完成的四合一密钥:gpg --armor --export-secret-keys <EC_ID> > EC.asc, 其中 <EC_ID> 是主密钥的 Key ID.
  2. 删除整个 gpg 数据库,清理掉无用的中间数据:sudo rm -rf ~/.gnupg.
  3. 重新导入四合一密钥:gpg --import EC.asc.

再次执行 gpg --list-keys --keyid-format LONG 查看密钥信息,应该只有很干净的四合一密钥了,类似这样:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
gpg: checking the trustdb
gpg: no ultimately trusted keys found
/home/he-sb/.gnupg/pubring.kbx
--------------------------------
pub   ed25519/8FF6666666666666 2016-07-20 [C]
      ************************8FF6666666666666
uid                 [ unknown] he-sb <[email protected]>
sub   ed25519/2BB2666666666666 2022-01-21 [S]
sub   ed25519/5201111111111111 2022-01-21 [A]
sub   ed25519/00CCFFFFFFFFFFFF 2022-01-21 [E]

§1.2.3 编辑密钥

缝合完密钥后,四合一密钥还不能直接使用。因为刚才 DIY 出来的密钥对,主密钥和子密钥没有交叉签名,后续使用时会导致子密钥无法被信任,而且还没有给密钥配置密码,缺少一道安全保险。下面来分别善后。

首先来看交叉签名:

  1. 终端输入 gpg --edit-key <EC_ID>, 其中 <EC_ID> 是 EC 主密钥的 Key ID.
  2. 输入 toggle, 回车确认,进入私钥编辑模式。
  3. 观察 ES 子密钥的顺序,假设是第 1 个,那么输入 key 1 (同理,如果 ES 子密钥是第 2 个,那么这一步输入 key 2, 以此类推), 选中 ES 子密钥,此时 ID 旁会出现一个 * 号。
  4. 输入 cross-certify, 进行交叉签名。如果之前已经配置过了密码,此时会要求验证。
  5. 完成后输入 save 保存并退出。

这一步是必需的,如果没有交叉签名,有可能会出现 ES 子密钥被盗,然后挂在别人的主密钥下面,冒充你来签名的情况。而且没有交叉签名的 ES 子密钥,在签名 git commit 时,git log 中会警告 gpg: WARNING: signing subkey <ES_ID> is not cross-certified.

然后是配置密码:

  1. 终端输入 gpg --edit-key <EC_ID>, 其中 <EC_ID> 是 EC 主密钥的 Key ID.
  2. 然后输入 passwd, 回车确认。
  3. 在接下来的交互式界面中,依次给主密钥和子密钥配置密码。可以给主密钥和每个子密钥配置相同的密码,也可以各不相同。使用键盘的方向键来切换选项。
  4. 配置完成后输入 save 保存并退出。

这一步理论上不是必需的,如果不担心私钥文件泄露的问题,或者确信私钥文件不会被盗,那么可以不配置密码,不影响使用。但是风险在于,万一日后私钥文件真的泄露了,没有密码的私钥,攻击者是可以直接使用的。

而给密钥配置密码后,万一私钥文件泄露,攻击者在不知道密码的情况下是无法使用的。设置一个高强度的密码,可以在私钥文件泄露后,密码被黑客破解前,争取到一段足够长的时间,来发布吊销声明,或者做一些别的补救措施。

特别地,如果是给已有的没有密码的密钥配置密码,或者需要修改密码的话,需要确保主密钥是导入的状态,配置好密码后,需要重新导出私钥,旧的私钥文件是不包含新的密码信息的。

  • 吊销证书,公钥和 SSH 公钥不需要重新导出,它们不包含密码信息。

§02. 生成吊销证书

现在来做最后一份保险措施。万一日后因为某种原因,主密钥被盗了或者丢了,需要废弃整个密钥对,那么就需要一个吊销证书:

1
gpg --armor --output EC_revocation.asc --gen-revoke <EC_ID>

然后 GPG 会提示选择一个理由,按需选择即可。然后输入主密钥的密码(如果有的话)。

最终生成的 EC_revocation.asc 是明文的文本文件,一定要离线保存在安全的介质中。

后续如果有一天(希望永远不要有这么一天……),电脑丢了或者私钥泄露了,需要用到吊销证书:

  1. 在已导入了待吊销密钥的公钥的电脑上,导入吊销证书:gpg --import EA_revocation.asc.
  2. 分发通告,将更新后的公钥上传到密钥服务器:gpg --keyserver hkps://keys.openpgp.org --send-keys <EC_ID>.

这样就完成了密钥的吊销。之后当别人尝试使用你之前分发出去的公钥加密,或验证你的签名时,他们的 GPG 客户端会自动收到“该密钥已作废”的警告。

这一步生成的吊销证书是用来吊销主密钥的,吊销主密钥后,整个密钥对(包括主密钥对应的所有子密钥)都会被宣布作废。

如果只想作废某个子密钥,那么不需要用到吊销证书:

  1. 在导入了主密钥的电脑上,编辑密钥:gpg --edit-key <EC_ID>.
  2. 选中子密钥:key 2 (假设要吊销第 2 个子密钥),被选中的子密钥 ID 旁会有个 * 号。
  3. 输入 revkey 吊销选中的子密钥。
  4. 输入 save 保存并退出。

§03. 导出备份

珍贵的四合一密钥至此已经准备好了,但是最好不要直接开始使用,先做好备份措施:

  1. 导出完整的四合一私钥备份:gpg --armor --export-secret-keys <EC_ID> > EC_full_secret.asc.
  2. 上一节生成的吊销证书 EC_revocation.asc.
  3. 导出仅包含子密钥,不含主密钥的三合一私钥文件:gpg --armor --export-secret-subkeys <EC_ID> > subkeys_only.asc.
  4. 导出用于复制到远程服务器鉴权的 SSH 公钥:gpg --export-ssh-key <EC_ID> > EA_openssh.txt. 这个命令会自动提取出 EA 子密钥并转为 OpenSSH 格式,然后写入 EA_openssh.txt 文件。
  5. 导出完整公钥,用于 GitHub 或个人网站等地方公开:gpg --armor --export <EC_ID> > EC_public.asc.

§04. 清理善后

确认备份完成后,直接删除本地的 GPG 数据库:

1
sudo rm -rf ~/.gnupg

这一步是为了:

  1. 确保本地数据库的干净,避免中间缝合密钥时,伪装的时间戳信息残留导致的一些奇怪 bug.
  2. 剥离主密钥。后续使用时,仅导入子密钥使用,主密钥始终离线保存,只在需要时才导入使用(比如添加或吊销子密钥),更加安全。

然后彻底删掉除了【03. 导出备份】小节提到的 5 个文件之外的所有文件,比如算号程序生成的原始靓号文件,中间缝合密钥过程中导出的 EC.asc 等。

§05. 结语

经过本文的操作,现在本地的 GPG 数据库应该是还未使用的干净状态,且有以下文件以备使用:

  1. 完整的四合一私钥备份 EC_full_secret.asc
  2. 吊销证书 EC_revocation.asc
  3. 仅包含子密钥,不含主密钥的三合一私钥文件 subkeys_only.asc
  4. 用于复制到远程服务器鉴权的 SSH 公钥文件 EA_openssh.txt
  5. 用于 GitHub 和个人网站的公钥文件 EC_public.asc

其中 12 请确保离线保存在安全的存储介质中,除非万不得已,否则不会用到。

下一篇文章将会具体介绍如何使用 3 4 5 这三个文件。


参考链接:

  1. 某科学的 PGP 算号指南 | Dejavu's Blog
  2. Signing Subkey Cross-Certification --- GnuPG.org
  3. TransparentLC/webgl-vanity-gpg
  4. TransparentLC/opencl_vanity_gpg