比较通过不同渠道发布的据称相同的 OpenPGP 密钥

信息安全 公钥基础设施 密钥管理 pgp gnupg 密钥服务器
2021-09-10 23:03:35

tldr 版本:当我尝试比较应该用于同一实体的公钥时,我通过不同渠道获得的版本不一样,而我下载为像 somekey.sig.asc 这样的文件的版本是较小的文件。


我正在尝试学习整个 gpg 并练习正确使用它。一个关键步骤是验证公钥确实属于它应该属于的一方。在没有个人联系链的情况下,显而易见的事情是从不同来源获取多个副本并验证它们是否相同。我似乎永远无法做到这一点。我怀疑部分问题在于换行符、回车符、空格、制表符和其他由 SCOPTDUI(程序员的秘密阴谋使用户发疯)发明的字符。这是一个示例,我相当确定密钥是相同的,但我无法想出一个程序来证明它。

来自 MIT 密钥服务器的 Veracrypt 团队密钥: https ://pgp.mit.edu/pks/lookup?op=get&search=0xEB559C7C54DDD393

Veracrypt 网站的 Veracrypt 团队密钥: https ://www.idrix.fr/VeraCrypt/VeraCrypt_PGP_public_key.asc

我都直接下载了。我已将两者复制并粘贴到文本文件中。我已经去掉了序言和结尾,留下了每个以相同的乱码开头和以相同的乱码结束的块。

我已经通过各种 tr 过滤器运行它们,例如:

cat file | tr -d '\040\011\012\015' > file-tred

麻省理工学院的文件仍然大得多。我已经将它们加载到 gedit 中,我可以复制一个的大量块并在另一个块中搜索该块并找到一个相同的子字符串,但不是整个文件。

这不是一个孤立的例子。麻省理工学院并不是独一无二的。我检查的第二个密钥服务器(在新西兰,但我不允许在这里发布第三个链接)有同样的问题。Veracrypt 也不是一个特例。每次我决定学习以“正确的方式”做 gpg 并且在放弃前几天在同一堵墙上敲打我的头时,我都会遇到这个问题。这些东西没有以标准化形式发布是否有某些原因?有什么方法可以让这件事变得简单吗?我错过了一些明显的东西吗?是什么让 MIT 文件如此之大?

附录:作为一个实际问题:

gpg --keyserver address.like-this-with-no-protocol-prefix-and-no-trailing-slash.net --search SOMETHING

似乎正在检查我已经拥有的密钥的重复项并报告“没有变化”,前提是我选择了一些东西。所以,从功能上讲,我想这没问题。我仍然想知道为什么我的手动比较失败。

2个回答

PGP 密钥文件不是单个密钥字符串,而是包含多个条目(数据包)。而不是试图比较两个文件的 ASCII 表示,您应该使用适当的工具,例如gpg(1)比较指纹

有什么方法可以让这件事变得简单吗?

是的,像这样:

$ wget https://www.idrix.fr/VeraCrypt/VeraCrypt_PGP_public_key.asc
$ gpg --with-fingerprint VeraCrypt_PGP_public_key.asc
pub  rsa4096/54DDD393 2014-06-27
      Key fingerprint = 993B 7D7E 8E41 3809 828F  0F29 EB55 9C7C 54DD D393
uid                   VeraCrypt Team <veracrypt@idrix.fr>

两个文件显示的指纹应该相同。请注意,哈希的低几位如何表示密钥 ID ( EB559C7C54DDD393)。

这些东西没有以标准化形式发布是否有某些原因?

它们是,只需查看RFC 4880以了解OpenPGP 消息格式规范。

是什么让 MIT 文件如此之大?

它包含更多的签名包同样,来自 RFC:

OpenPGP 消息由许多传统上称为数据包的记录构成。OpenPGP 消息、密钥环、证书等由许多数据包组成。

--list-packets您可以通过(或使用pgpdump(1)更易读的版本)列出文件中的所有数据包。

$ gpg --list-packets VeraCrypt_PGP_public_key.asc

这将产生一个像这样的枚举:

# off=0 ctb=99 tag=6 hlen=3 plen=525
:public key packet:
    version 4, algo 1, created 1403892630, expires 0
    pkey[0]: [4096 bits]
    pkey[1]: [17 bits]
    keyid: EB559C7C54DDD393
# off=528 ctb=b4 tag=13 hlen=2 plen=35
:user ID packet: "VeraCrypt Team <veracrypt@idrix.fr>"
# off=1137 ctb=89 tag=2 hlen=3 plen=540
:signature packet: algo 1, keyid D6BE7DAF738161CE
    version 4, created 1403950017, md5len 0, sigclass 0x10
    digest algo 2, begin of digest 08 92
    hashed subpkt 2 len 4 (sig created 2014-06-28)
    subpkt 16 len 8 (issuer key ID D6BE7DAF738161CE)
...

如您所见,公钥数据包具有熟悉的密钥 ID EB559C7C54DDD393,而签名数据包带有各自的颁发者的密钥 ID(您也可以查看密钥服务器)。

旁注:您所说的“前导码”称为ASCII 装甲,用于通过难以处理任意二进制数据(例如电子邮件)的通道传输 PGP 消息。它是格式的一部分,您可以将其保留在文件中。

tl;dr:两个转储都包含相同的密钥,但是您从密钥服务器获得了一些额外的认证,这些认证不包括在 VeraCrypt 网站的最小导出中。

OpenPGP 数据包

OpenPGP 密钥由一组OpenPGP 数据包组成,可以用gpg --list-packets和列出pgpdump对于导出的密钥,有一个必需的数据包,即public key packet. 潜峰(解释如下):这对两个键都是一样的。

:public key packet:
  version 4, algo 1, created 1403892630, expires 0
  pkey[0]: [4096 bits]
  pkey[1]: [17 bits]
  keyid: EB559C7C54DDD393

如果没有任何用户 ID 数据包,密钥几乎无法​​使用。它无法通过名称查询,甚至无法接收认证(密钥上的签名指向公钥指纹和用户 ID 的元组)。

:user ID packet: "VeraCrypt Team <veracrypt@idrix.fr>"

最后,通常会发出自签名。密钥服务器通常拒绝加载没有自签名的密钥。

:signature packet: algo 1, keyid EB559C7C54DDD393
  version 4, created 1403892630, md5len 0, sigclass 0x13
  digest algo 2, begin of digest 7f 33
  hashed subpkt 2 len 4 (sig created 2014-06-27)
  hashed subpkt 27 len 1 (key flags: 0F) 
  hashed subpkt 11 len 6 (pref-sym-algos: 9 8 7 3 2 1)
  hashed subpkt 21 len 5 (pref-hash-algos: 8 2 9 10 11) 
  hashed subpkt 22 len 3 (pref-zip-algos: 2 3 1)
  hashed subpkt 30 len 1 (features: 01) 
  hashed subpkt 23 len 1 (key server preferences: 80) 
  subpkt 16 len 8 (issuer key ID EB559C7C54DDD393)
  data: [4096 bits]

最少的出口

这是密钥可用的或多或少所需的最小密钥部分。对于每个用户 ID,可以选择附加传入证书的列表,以帮助其他人验证密钥。这是不同输出的最可能原因。

比较键

现在,如何比较密钥?首先,让我们将它们都提取到本地文件mit.ascveracrypt.asc. diff这些将是比较文件的一般方式,但是 OpenPGP 文件很难读取,所以让我们首先列出它们的内容并区分它们:

gpg --list-packets mit.asc >mit.asc.list
gpg --list-packets veracrypt.asc >veracrypt.asc.list
diff mit.asc.list veracrypt.asc.list

差异揭示了密钥服务器转储中的许多其他签名。看着veracraypt.asc.list,它确实似乎veracraypt.asc是一个最小版本,所以让用户使用 GnuPG 的导出选项来创建一个最小副本mit.asc

gpg --dearmor mit.asc # Dearmor first, to use it as keyring file
gpg --export-options export-minimal --no-default-keyring --keyring ./mit.asc.gpg \
    --export 0xEB559C7C54DDD393 >mit-minimal.asc
gpg --list-packets mit-minimal.asc >mit-minimal.asc.list

现在,Diffing 揭示了它veracrypt.asc恰好拥有一个额外的签名:

:signature packet: algo 1, keyid D6BE7DAF738161CE
  version 4, created 1403950017, md5len 0, sigclass 0x10
  digest algo 2, begin of digest 08 92
  hashed subpkt 2 len 4 (sig created 2014-06-28)
  subpkt 16 len 8 (issuer key ID D6BE7DAF738161CE)
  data: [4091 bits]

一个签名至少声称属于 VeraCrypt 的作者(不过我没有验证密钥)。