导入中毒密钥后如何修复 GnuPG(不只是删除它)

Mic*_*eld 5 security thunderbird privacy enigmail gnupg

我的 GnuPG 客户端自动从密钥服务器刷新其密钥环中的密钥,并导入了中毒密钥。如何在不删除中毒公钥的情况下修复我的密钥环?

上个月,一些备受瞩目的 pgp 证书通过证书攻击 ( CVE-2019-13050 ) 受到攻击,他们将带有数万(或数十万)个签名的公钥发送垃圾邮件并将其中毒公钥上传到密钥服务器。

例如,如果您的密钥环中有“ Tor 浏览器开发人员(签名密钥) ”,并且您--refresh-keys在 2019 年 6 月 30 日之后尝试从密钥服务器(当时他们的密钥充斥着 121,000 个虚假签名),那么您的 gpg(和因此,您的电子邮件(例如,如果您使用带有 enigmail 的 Thunderbird)将挂起并变得无法使用

大多数的报道这个问题说,解决办法是只删除键-但我怎么可以在本地清洁公共密钥,无需下载一个新的副本(它引入了不必要的载体篡改)?

Mic*_*eld 5

我花了一些时间研究如何解决这个问题,并在我的网站上发表了一篇关于它的文章。下面总结一下这个问题的解答。

1. 识别中毒密钥

首先,我们可以使用以下命令列出密钥环中公钥的大小(以字节为单位)(如GnuPG 问题跟踪器上报告的那样):

user@disp1754:~$ gpg --export | gpg --list-packets | awk -F= -v oldoff=-1 -v keyid=unset '
/^# off=/{ off = $2 + 0 }
/^:public key/{ if (oldoff>-1) { print (off - oldoff) " " keyid }; oldoff = off; keyid = "unset"; }
/keyid:/ {if (keyid == "unset") { keyid = $1; } }
END { print (off - oldoff) " " keyid ; };' | sort -n
7284    keyid: 1DCBDC01B44427C7
119748  keyid: 4E2C6E8793298290
124557  keyid: 403C2657CD994F73
16934647    keyid: F20691179038E5C6
user@disp1754:~$ 
Run Code Online (Sandbox Code Playgroud)

如果上面的命令运行时间超过几秒钟,那么就有问题了。等 20 分钟左右,您就会在底部看到有问题的按键。任何 8 位数字 (>10 MB) 的内容都是危险信号。

ⓘ 注意:在上面的示例中,我们看到 id = 的公钥的F20691179038E5C6大小为16934647bytes = 16M。这是我们中毒的钥匙。

本文中的命令使用此keyid ( F20691179038E5C6) 来操作密钥环。您应该将以下命令中的该字符串替换为keyid您计算机上上述命令中找到的相应字符串。  

2.导出中毒密钥

现在我们已经确定了中毒密钥,让我们在删除它之前将其导出以安全保存。

user@disp1754:~$ time gpg -a --export 'F20691179038E5C6' > pubkey.asc

real    3m30.950s
user    3m24.430s
sys 0m0.322s
user@disp1754:~$ du -sh pubkey.asc 
22M pubkey.asc
user@disp1754:~$ 
Run Code Online (Sandbox Code Playgroud)

几分钟后,该命令将完成,您应该有一个pubkey.asc以中毒公钥内容命名的文件。请注意,这个仅包含一个公钥的 ASCII 装甲文件有 22M!

3.删除中毒密钥

现在我们已经在磁盘上安全备份了中毒密钥,让我们将其从密钥环中删除。

user@disp1754:~$ time gpg --delete-key 'F20691179038E5C6'
gpg (GnuPG) 2.1.18; Copyright (C) 2017 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

pub  ed25519/F20691179038E5C6 2019-01-19 Daniel Kahn Gillmor <dkg@fifthhorseman.net>

Delete this key from the keyring? (y/N) y

real    12m15.265s
user    11m54.242s
sys 0m0.715s
user@disp1754:~$ 
Run Code Online (Sandbox Code Playgroud)

4. 重新导入清理后的密钥

要重新导入公钥的干净副本,我们将使用参数gpg删除--import-filters在证书被签名淹没之日所做的所有签名 ( )。drop-sig

给定一个公钥文件(如我们上面刚刚导出的备份),我们可以使用以下命令列出该证书每天收到的签名数量:

user@disp1754:~$ time gpg --list-packets pubkey.asc | grep -i 'sig created ' | sort -n | uniq -c
     11     hashed subpkt 2 len 4 (sig created 2019-01-19)
      2     hashed subpkt 2 len 4 (sig created 2019-01-20)
      4     hashed subpkt 2 len 4 (sig created 2019-01-21)
      2     hashed subpkt 2 len 4 (sig created 2019-01-28)
  14400     hashed subpkt 2 len 4 (sig created 2019-06-17)
  40200     hashed subpkt 2 len 4 (sig created 2019-06-18)

real    0m23.061s
user    0m17.803s
sys 0m0.150s
user@disp1754:~$ 
Run Code Online (Sandbox Code Playgroud)

上面的输出表明

  1. 2019 年 6 月 17 日对密钥进行了 14,400 个签名,
  2. 2019-06-18 密钥有 40,200 个签名

我们可以导入密钥,同时忽略这两天的垃圾邮件签名,如下所示(请务必将日期替换为上述命令在您的计算机上打印的相应日期):

user@disp1754:~$ time gpg --import-filter drop-sig="sig_created_d=2019-06-17 || sig_created_d=2019-06-18" --import pubkey.asc
gpg: key F20691179038E5C6: 54614 signatures not checked due to missing keys
gpg: key F20691179038E5C6: public key "Daniel Kahn Gillmor <dkg@fifthhorseman.net>" imported
gpg: Total number processed: 1
gpg:               imported: 1
gpg: no ultimately trusted keys found

real    3m12.091s
user    3m6.991s
sys 0m0.284s
user@disp1754:~$ 
Run Code Online (Sandbox Code Playgroud)

现在事情应该更加理智了:

user@disp1754:~$ time gpg --export | gpg --list-packets | awk -F= -v oldoff=-1 -v keyid=unset '
> /^# off=/{ off = $2 + 0 }
> /^:public key/{ if (oldoff>-1) { print (off - oldoff) " " keyid }; oldoff = off; keyid = "unset"; }
> /keyid:/ {if (keyid == "unset") { keyid = $1; } }
> END { print (off - oldoff) " " keyid ; };' | sort -n
7284    keyid: 1DCBDC01B44427C7
8930    keyid: F20691179038E5C6
119748  keyid: 4E2C6E8793298290
124557  keyid: 403C2657CD994F73

real    0m0.063s
user    0m0.059s
sys 0m0.016s
user@disp1754:~$ gpg -a --export '403C2657CD994F73' > pubkey2.asc
user@disp1754:~$ du -sh pubkey2.asc 
168K    pubkey2.asc
user@disp1754:~$ 
Run Code Online (Sandbox Code Playgroud)

5. 更新你的 GnuPG 配置

正如 Robert J. Hansen(他的 pgp 密钥在 2019 年 6 月 19 日被垃圾邮件发送了 149,100 个签名)在其关于此问题的出色综合要点中指出的那样,您可以通过以下方式防止您的 gpg 客户端崩溃:

  1. 删除“gpg.conf”文件中以“keyserver”开头的任何行,并
  2. 更新 `dirmngr.conf`,使其只有 1 个 `keyserver` = `keyserver hkps://keys.openpgp.org`

keys.openpgp.org密钥服务器是一个新的实验服务器(有趣的是,它在这些中毒证书上传前几周才上线),对这些攻击具有更强的抵抗力。请注意,它提供的证书完全没有第三方签名,并且它还会从密钥中剥离 UID 数据包,除非用户明确选择加入

6. 更新您的 MUA 配置

您可能还需要更新您的 MUA。例如,thunderbird 中的 enigmail 也可以配置为更新密钥环中的密钥。

为了防止 enigmail 从密钥服务器刷新您的密钥,请转到您的 Thunderbird 首选项 -> 高级 -> 配置编辑器... -> 我接受风险!

并设置extensions.enigmail.keyRefreshOnfalse

附录

请注意,密钥箱密钥环格式将拒绝导入定位密钥,因为它的最大密钥大小为 5 MiB,并且使用旧安装的用户应考虑将其密钥环迁移到密钥箱格式。

这可以在基于 debian 的系统中使用migrate-pubring-from-classic-gpg命令轻松完成