请直接停止使用RSA加密

2021-01-21 13:45:39

让我先说一下,尽管我们要谈论的是一个最近提交给Hacker News的“ Show HN”部分的开源项目,但这篇文章的意图绝不是要让尝试过该死的开发者感到羞耻。做正确的事。他们是受害者,而不是罪魁祸首。

本周早些时候,一名HN用户共享了Facebook Messenger客户端的开源分支,并添加了加密功能。如自述文件所述,他们的动机是:

众所周知,Facebook会扫描您的消息。如果您需要继续使用Facebook Messenger,但又关心隐私,那么Zuccnet可能会有所帮助。非常简单:您和您的朋友都安装了Zuccnet。您的朋友给您他们的Zuccnet公钥。然后,当您在Zuccnet上将消息发送给您的朋友时,您的消息将在计算机上加密,然后再通过Facebook发送给您的朋友。然后,您朋友的Zuccnet将邮件解密。 Facebook永远不会看到您的消息内容。我不是安全人员,可能有一些我想念的东西–非常欢迎您提供任何帮助!这是Beta版,请不要太在意。

来自Zuccnet的非常谦虚的自述文件。

到现在为止还挺好。 Facebook对隐私的保护态度很糟糕,因此尝试将事情交给您自己来加密数据,以便从本质上讲,Facebook看不到您在说什么,这是一个绝妙的主意。

但是,该想法的执行存在问题。这不是Zuccnet特有的问题。每年几次,我遇到了一个很好的软件项目,该项目会犯同样的错误:用RSA直接加密消息是很糟糕的。

以Zuccnet作者的功劳,他们使用的是OAEP填充,而不是PKCS#1 v1.5填充。这意味着他们的代码不容易受到Bleichenbacher 1998年的padding oracle攻击的影响(n.b.我在野外遇到的大多数RSA代码都容易受到这种攻击)。

如果尝试使用2048位RSA公钥加密长度超过256个字节的消息,则该消息将失败。 (因为表情符号,这里的字节很重要,即使是英语使用者,字符也无关紧要。)

这种设计完全缺乏前瞻性。这与PGP加密很烂。

一些密码库使您可以将RSA视为ECB模式下的分组密码,并独立加密每个块。这是一个非常愚蠢的API设计选择:它很慢(非对称密码运算的速度比对称密码运算慢几十到十万倍),并且您可以丢弃/重排序/重播块,因为ECB模式不提供语义安全。

更好的策略是使用对称密钥加密数据,然后使用RSA加密该密钥。 (有关特殊处理选项的信息,请参阅文章末尾,这些选项对于使用PKCS#1 v1.5填充的RSA特别有用。)

解决第二个问题需要身份验证密钥交换(AKE),类似于我在《端到端加密指南》中介绍的内容。解决第二个问题也可以解决第一个问题,因此通常只实施前向机密密钥交换协议比尝试使RSA安全更为有效。

尽管AKEs非常有用,但是对于大多数软件开发人员来说,如果没有事先的加密经验,它们就会有些复杂。 (毕竟,如果它们更简单,那么将没有太多软件可以直接使用RSA直接加密邮件。)

首先,考虑不使用RSA。该死的时候,不要编写任何不必要的密码代码。

Libsodium可以为您完成大部分操作,并且可以轻松地转换成与Signal所使用的AKE相当的AKE。您必须编写的密码代码越少,灾难性的错误就越少,尤其是在生产系统中。

如果这不是入门者,那么您至少应该考虑参加针对软件开发人员的Dhole Moments承诺:

相反,如果您发现自己需要使用RSA加密消息,请提醒自己RSA用于加密对称密钥,而不是消息。然后相应地计划您的协议设计。

另外,我很确定RSA的随机密钥不强。询问您最喜欢的密​​码学家对您要建造的任何产品是否重要。

让我们问自己:“为什么我们强迫开发人员了解甚至关心这些细节?”

Libsodium不会妨碍开发人员采取不必要的决策。为什么加密模块内置在JavaScript中?为什么在大多数提供这种语言的编程语言中都内置了加密模块? (在这里,Go是一个明显的例外,因为他们的安全团队很棒而且很有远见。)

如果您被迫使用PKCS#1 v1.5填充,最好的解决方案是使用RSA加密32个随机字节,然后使用RSA加密密文的HMAC-SHA256(以随机字节作为HMAC密钥)来生成AES + HMAC(或AES-GCM)使用的对称密钥。

在解密过程中,请勿验证填充内容,而仅获取已解密明文的最低256位。 跳过填充检查(如果不跳过,可能会导致时间泄漏),再加上HMAC步骤,可以有效地将不对称步骤转换为全有或全无的转换,从而阻止自适应选择密文攻击的成功。 如果更改和中的这些值,t将失败。 改变b不会比改变n,c或t更快(就网络时序而言)。 因此,攻击者没有优势。 BB’98,请全力以赴。