对称加密是否提供数据完整性?

信息安全 加密 哈希 密钥管理
2021-08-19 14:01:04

假设我有一台服务器使用对称密钥加密文件,例如 AES-CBC,并将其发送给解密它的客户端。解密时是否提供数据完整性?或者有人可能在文件仍然加密时篡改文件,然后当客户端解密它时,生成一个修改过的文件?

我通常会在使用数字签名或 MAC 方面讨论数据完整性和真实性,但从未在加密的背景下讨论过数据完整性和真实性。我还看到了显示加密比散列更昂贵的基准,但这不是我的主要考虑因素。

更新

我尝试了一个实验,我使用 Linux 中的 openssl 工具对文件进行加密。然后,我尝试以各种方式修改文件(更改字节、删除字节、附加字节)。在每种情况下,当我尝试解密时,都会收到“解密错误”消息。我使用的命令是:

openssl enc -aes-128-cbc -in test -out test.enc
openssl enc -d -aes-128-cbc -in test.enc -out test.dec
4个回答

对称加密不提供完整性。攻击者对加密数据的控制量取决于加密类型;如果攻击者想要进行手术修改,某些加密模式的一些具体细节可能会使他的生活更加艰难。使用 CBC,攻击者可以随意翻转任何位,前提是他不介意将其他十几个字节转换为随机垃圾。

最近的加密模式结合了对称加密和检查完整性(使用MAC)。这些模式确保机密性和完整性。AES-CBC不是其中之一。如果你想要一个完整的加密模式,我推荐EAX

更新:关于您的实验:CBC 是一种模式,其中源数据长度必须是块密码块长度的倍数(16 字节,对于 AES)。由于任意输入消息可能具有任意长度,因此添加了一些填充:几个字节,具有特定内容,以便在解密时可以明确删除它们。在您的情况下,OpenSSL 抱怨说,在解密时,它没有找到合适的填充结构。但是,如果攻击者不更改加密数据的最后 32 字节,则填充将不会损坏,因此除了最后 32 字节之外的所有更改都不会被检测到。即使是最后 32 个字节,也有一些方法可以以不那么小的概率逃避检测。

CBC 加密不提供数据完整性。原因如下:

修复一些密钥 k(攻击者不知道)。让 E(k,-) 和 D(k,-) 是一些分组密码的裸加密和解密函数。让 p 是一些单一的明文块。我将用 + 表示 XOR。修复一些 IV 后,我们加密如下:

c = E(k,p + IV)。

然后,我们通过网络发送 IV 和 c。为了解密,我们计算

p = D(k, c) + IV。

(请注意,这等效于语句 D(k,c) = IV + p。)

现在,假设攻击者知道一个明文/密文对。如上所述,我们将它们表示为 p 和 (IV, c)。现在,假设攻击者想要创建密文,该密文将解密为他选择的其他明文块——比如 p'。我声称 (IV + p + p', c) 解密为 p'。为什么?

好吧,我们只是按照上面的解密过程,将 IV 替换为 IV + p + p'。我们有

D(k,c) + (IV + p + p') = (IV + p) + (IV + p + p') = p'。

有趣的是,ECB 模式不容易受到这个问题的影响(尽管我也不赞成使用它)。

AES-CBC 加密不提供完整性。根据它的实现和使用方式,它可能会碰巧检测到对密文的一些意外修改,但它不能防御对密文的恶意篡改。

未经身份验证的加密是密码学使用中最常见的错误之一它导致了许多系统中的严重漏洞,包括 ASP.NET、XML 加密、Amazon EC2、JavaServer Faces、Ruby on Rails、OWASP ESAPI、IPSEC 和 WEP。有关更多信息,请参阅上一个链接。

修复:您应该使用经过身份验证的加密方案(不是 AES-CBC),例如 EAX,或者您应该在 encrypt-then-authenticate 模式下使用消息身份验证代码,例如 CMAC。

如果您打算自己实施密码学,我鼓励您阅读此处题为“关于加密和密码学的经验教训和误解”的问题,以帮助您避免一些最常见的错误。使用无需身份验证的加密就是其中之一。

对称密码本身并不提供完整性,因为它们不会检测到对密文的恶意或意外修改;解密将输出除原始明文之外的其他内容,除非这导致解密的有效负载出现某些协议违规,否则您将遇到完整性问题。

解决方案是将明文包装在包中,其中包含可用于验证包完整性的数据,通常是基于哈希的校验和(编辑: keyed HMAC)。这就是为传输层安全所做的事情。

这是一个在 Versile 平台安全字节传输协议中使用的明文保护方案的示例(免责声明:我参与了 VP 开发)。

编辑:我意识到消息封装对于涉及完整文件的场景来说是多余的,所以你最好只在完整的密文上添加一个键控 MAC。对于包保护格式,正如 DW 指出的细节问题,“校验和”应该作为密钥 MAC 执行。