GNU:一种不良密码学的启发式算法

2020-07-13 21:10:09

如果您在系统设计中看到字母GNU,并且该系统与密码学相交,我几乎可以保证它的设计将糟糕到令人震惊的程度。

GnuPG(以及一般的PGP)都是如此,就像建议的GNU名称系统(IETF草案)和加密库(如GNUTLS和libgcrypt)这样的设计一样。事实上,我想不出有哪一个GNU品牌的加密项目不是一堆熊熊大火。

GNS中的区域由公钥/私钥ECDSA密钥对(d,zk)定义,其中d是私钥,zk是相应的公钥。GNS采用曲线25519[RFC7748](也称为。Edwards25519)与ECDSA方案([RFC6979])。

GNU名称系统IETF草案,第2节。

这非常奇怪:特意使用RFC 7748中的edwards25519曲线,但不使用Ed25519签名算法,但仍然选择使用确定性ECDSA(RFC6979)。

(如果你迷路了,我在之前的一篇博客中写过关于数字签名算法的文章。)。

作者在RFC草案的第9.1节中承认了他们的设计选择的非常规性质:

GNS在曲线25519上使用ECDSA。这是一个非常规的选择,因为ECDSA通常与其他曲线一起使用。然而,由于Curve25519和EdDSA论文中描述的一系列原因,传统的ECDSA曲线存在问题。直接使用EdDSA也是不可能的,因为在私钥上使用散列函数会破坏GNU名称系统所依赖的线性。据我们所知,没有人建议使用曲线25519而不是另一条类似大小的公共曲线会降低ECDSA的安全性。GNS使用256位曲线,因为这样编码的(公共)密钥适合单个DNS标签,这有利于可用性。

GNU名称系统IETF草案,第9.1节。

粗体的说法(我强调的)是无稽之谈:在任何使用数字签名算法的设计中,您的系统都应该将私钥(一些不透明的字节字符串)映射到公钥(其他一些不透明的字节字符串),并且签名也应该是不透明的字节字符串。在签名算法的幕后包含哈希函数是一个值得商榷的问题,特别是因为RFC 6979还使用HMAC-SHA2来生成确定性随机数,从而使他们选择RFC 6979与其声明的目标相矛盾。编辑:见下文。

使用带有32字节私钥(而不是64字节私钥)的Ed25519也很简单。也就是说:LibNa为此提供了crypto_sign_seed_keypair()。

但更糟糕的是:由于算法的实现方式,即使使用相同的曲线,ECDSA也不如EdDSA安全且速度慢。除了这个散列函数非顺序性之外,RFC的作者并没有为这个设计选择辩护。

在我最初发布这篇文章后,Rededitor Steve132通知我,我忽略了他们做出这个设计决定的原因。

从这里开始,按顺序递归执行以下步骤:从要查找的名称中提取最右边的标签。使用4.1节中定义的标签和ZK计算Q。

如果转到4.1节,他们做h=H(<;Address string>;),(r,R)是某个根密钥对,然后做C(子公钥),C=HR,然后Q=H(C)。

Q计算背后的思想是使用根公钥仅从根公钥导出子公钥,利用线性性质,在椭圆曲线中,如果BG=B,则(b+s)G=(SG+B)

这允许第三方在不知道根的私钥的情况下导出子公钥。这项技术也用于比特币的bip32(https://en.bitcoin.it/wiki/BIP_0032)表示“未硬化”的派生方案。

Steve132更正的一部分。

我完全承认,在我第一次通过RFC选秀时,我没有吸收这个细节。第9节(旨在证明他们的密码学决定是正当的)中没有清楚地阐明这一点,我也没有仔细阅读其他章节。这是我的错。

然而,即使记住了这个解释,我最初的观点仍然有效,即这种设计选择既是非常规的,也是不必要的,因为BIP32-Ed25519已经存在(尽管它仍然需要精心设计的实现来保护自己免受主动攻击者的攻击)。

因此,GNU名称系统开发人员不需要推出他们自己的设计,他们可以使用已经在实际部署中看到的设计。为什么要承担不必要的风险呢?

此外,正如泰国Duong指出的那样,试图推动ECDSA在edwards25519上的实施不仅是不必要和奇怪的,而且可能也是危险的:

虽然我不同意ECDSA比Ed25519更差-两者都有利弊-但实施ECDSA胜过Edward25519需要勇气。你知道他们有没有发布任何代码?这段不幸的婚姻可能会带来有趣而独特的虫子。

-thaidn(@XorNinja)2020年7月9日

当然,所有的密码学开发都可以说是危险的,但GNU名称系统设计还存在其他一些基本问题,这些问题使任何偏离良好道路的行为都非常可疑。

GNU名称系统项目并没有止步于此。它进一步将Ind-CCA2安全性抛诸脑后,并使用密码反馈(CFB)模式在密码级联中指定使用AES和TwoFish进行加密。

作者甚至没有试图为这一决定辩护。通常,当作者不了解所涉及的风险时,就会发生这种情况。我真诚地怀疑他们在自学过程中是否听说过“自适应选择密文攻击”这个词。

(因为,您知道,如果由于数据损坏而发生运行时异常,攻击者肯定永远无法重放UDP流量。)。

密码级联通常是“我们想要防御背道而驰或破解的密码”的结果。请记住,密码本身很少是密码系统的第一个被破解的部分。

在这一点上,TwoFish不是AES级联合作伙伴的最差选择,但我更喜欢采用不同范例的设计(因为AES是SPN置换块密码,像Salsa20或ChaCha这样的基于ARX的流密码似乎是合理的)。

AES是一个乏味的选择,因为它是行业标准。我不是特别喜欢aes(因为它在纯软件实现中不是快速和恒定的时间),但是如果您在认证模式(aes-gcm、aes-ccm、aes-eax、aes-ocb3、…)中使用它。我不知道,Poly1305-AES?只要使用EAD模式就可以了!),这很好。

如果您要在2020年发布一个不符合密码末日原则的密码设计,您需要重新开始。

如果你想了解为什么GnuPG(以及整个PGP生态系统)很糟糕,我推荐Latacora‘s Take。

GNUTLS是由创建(然后放弃)libmcrypt的人创建的SSL/TLS库,libmcrypt多年来一直是PHP生态系统中糟糕密码术的祸害(直到它最终在PHP7.2中被删除)。因此,该项目的CVE历史应该不足为奇。

快速故事:许多年前,在Freenode的##加密频道中的常规聊天中,在libgcrypt中发现了一些计时攻击。这导致我们中的许多人在libgcrypt上寻找更多的bug。

随后的IRC讨论的总体共识大致是,“我们可能不应该试图修复它们,因为a)这太费力了,因为有太多的坏处,b)这个库将是即将到来的密码分析研究人员发表他们多年以来的第一篇论文的成熟目标”。(B)对于即将到来的密码分析研究人员来说,这个库将是一个成熟的目标,让他们多年来发表他们的第一篇论文。事实上,多年来公布的影响libgcrypt的攻击文件并没有让人失望。

需要明确的是,在这种情况发生的时候,我的C语言写得一塌糊涂(不知何故,自信比能力更差),勉强维持收支平衡,所以“放下一切,自愿修复所有libgcrypt的坏处”对我来说不是一个站得住脚的选择。由于世界在很大程度上正在远离GnuPG和libgcrypt,老实说,当一个更简单的修复是“使用好的东西来代替”时,尝试修复所有的坏东西是不值得的。

如果您在任何与密码学交叉的项目中看到字母GNU-除了它的公共许可证-几乎可以肯定这是一个容易出错的密码设计。

要替换GNUTLS或libgcrypt(取决于您使用它的用途),您需要以下选项之一:s2n、OpenSSL/LibreSSL或LibNa。

对于嵌入式系统来说,BearSSL现在是一个很好的选择,而libhrv2发布后将是一个有吸引力的选择。

标题图像,就像这里找到的GnuNet徽标一样,可以在Creative Commons和Attribution-Share Alignment 4.0国际版权许可证下获得。