如何将 gpg 子项添加到 GitLab

How to add a gpg subkey to GitLab

GitLab 9.5.0 添加了对检查提交的 gpg 签名的支持,并在提交哈希旁边显示验证状态(release note). This version, however, does not verify commits signed using subkeys (gitlab issue,计划支持)。

是否可以将gpg中的子键导出并转换成主键,这样这些主键就可以添加到GitLab中了?

编辑 2017 年 10 月

从 10.1 版本开始,GitLab 原生支持子键。您可以简单地添加 完整 public 键。如果您的密钥的电子邮件地址已在 GitLab 中得到验证,则使用子密钥签名的提交显示为 'verified'。


原回答

虽然原始密钥环应该不会改变,但我建议您先备份所有(public 和秘密)密钥环!这个解决方案是相当实验性的!

创建一个目录,例如sub2primary,然后改成它,因为下面的命令会创建很多临时文件,这可能会弄乱你的主目录。我将假设以下设置

frank@7777a258a48e:~/sub2primary$ gpg2 --list-keys
/home/frank/.gnupg/pubring.kbx
------------------------------
pub   rsa1024/34171358 2017-08-30 [SC]
uid         [ultimate] Frank <frank@example.com>
sub   rsa1024/320752EA 2017-08-30 [S]
sub   rsa1024/BBA338AD 2017-08-30 [E]

于 ubuntu 16.04.

导出子项

首先,您需要导出密钥(public 和私有密钥、主密钥和子密钥)并将它们分解成单独的数据包。

$ gpg2 --export frank@example.com | gpgsplit -vp pub
$ gpg2 --export-secret-keys frank@example.com | gpgsplit -vp sec

这两个命令创建了几个文件,每个文件对应一个数据包。您可以使用 pgpdump 检查数据包。我们对匹配 pub*.public_subkeysec*.secret_subkey 的文件感兴趣。检查其中一个文件显示

frank@7777a258a48e:~/sub2primary$ pgpdump sec000004-007.secret_subkey 
Old: Secret Subkey Packet(tag 7)(517 bytes)
...

这确实是一个私有子项。如果您有多个子密钥(例如,一个用于签名,一个用于加密),我不确定如何识别正确的子密钥。在此示例中,带有 *000004-* 的数据包将包含用于签名的密钥。 (有疑问选一个,选错了重新开始。)

编辑: gpg2 --list-packets <file> 显示有关包含密钥 ID 的数据包的更多信息。这有助于选择正确的数据包。

转换为主键

其次,我们需要将这些子密钥数据包(这里是pub000004-014.public_subkeysec000004-007.secret_subkey)转换成主密钥数据包。为此,您需要一个十六进制编辑器(vim -b 就足够了)并修改每个文件中的第一个字节。将 public 子项的第一个字节替换为 \x99,并将秘密子项的第一个字节替换为 \x95。如果您使用 vim -b,您可以从主键文件 pub000001-006.public_keysec000001-005.secret_key 复制第一个字节。 (不要混用 public 和 secret!)

完成此过程后 pgpdump 显示密钥现在是主密钥

frank@7777a258a48e:/~/sub2primary$ pgpdump sec000004-007.secret_subkey 
Old: Secret Key Packet(tag 5)(517 bytes)
...

导入主键

接下来,我们需要欺骗 gpg 来导入这些损坏的数据包(它们没有用户 ID,也没有自签名)。为此,只需复制它们,以便它们可以用作密钥环

frank@7777a258a48e:~/sub2primary$ cp pub000004-014.public_subkey ~/.gnupg/tmp
frank@7777a258a48e:~/sub2primary$ cp sec000004-007.secret_subkey ~/.gnupg/sec_tmp 

如下一个打印输出所示,可以告诉 gpg 使用这些修改后的密钥。

frank@7777a258a48e:~/sub2primary$ gpg2 --no-default-keyring --keyring tmp --secret-keyring sec_tmp --list-secret-keys
/home/frank/.gnupg/tmp
----------------
sec   rsa1024/320752EA 2017-08-30 [SCEA]

frank@7777a258a48e:~/sub2primary$ gpg2 --no-default-keyring --keyring tmp     --secret-keyring sec_tmp --list-keys
/home/frank/.gnupg/tmp
----------------
pub   rsa1024/320752EA 2017-08-30 [SCEA]

正在添加用户 ID

最后一步是编辑此键以添加用户 ID。

frank@7777a258a48e:~/sub2primary$ gpg2 --no-default-keyring --keyring tmp     --secret-keyring sec_tmp --edit-key 320752EA

子命令adduid 将提示必要的信息。完成后,save。这会添加用户 ID 并自动签名。

导出 sub/primary 密钥

最后,您可以导出与旧子项相同的新主键。输出可以添加到您在 GitLab 上的个人资料中。

frank@7777a258a48e:~/sub2primary$ gpg2 --no-default-keyring --keyring tmp     --secret-keyring sec_tmp --armor --export

您不应该将 tmp 钥匙圈或这个被操纵的钥匙用于任何其他目的!上传密钥后,您可以删除临时文件。使用您常用的子密钥签名的提交现在将在 GitLab 上显示为 已验证


致谢:此解决方案的灵感来自 http://atom.smasher.org/gpg/gpg-migrate.txt,它使用类似的工具来解决不同的问题。