为什么 AES 不用于安全散列,而不是 SHA-x?

信息安全 加密 密码学 哈希
2021-08-17 15:37:09

据我了解,AES 被认为是非常安全的。(我在某处读到过,未来20年肯定不会被破解,但我仍然不确定作者是不是认真的。)

DES 对于旧密码来说仍然不是那么糟糕,并且仍然使用 3DES(可能不是那么多,但至少我在 Firefox 的 about:config 中看到了 3DES)。

看起来(好)块密码受到加密社区的信任。

OTOH,发现了许多与密码散列函数有关的问题。

从非加密专家的角度来看:散列函数和对称密码实际上是同一件事:“随机”函数(具有不同的输入和输出)。

那么,为什么不只使用 AES 进行散列呢?这似乎是为了获得 AES 哈希的强大安全性而要做的显而易见的事情。作为奖励,AES 的硬件实现有帮助吗?

对哈希函数和对称密码之间的真正区别有简单的解释吗?

4个回答

分组密码有一个密钥;密钥的保密性是密码安全性的基础。另一方面,散列函数根本没有密钥,也没有建立散列函数安全性的“秘密数据”。

分组密码是可逆的:如果您知道密钥,就可以解密加密的内容。从技术上讲,对于给定的密钥,分组密码是可能的分组值空间的排列散列函数是不可逆的,它们不是以任何方式排列的。

分组密码在固定大小的块(AES 为 128 位块)上运行,用于输入和输出。哈希函数具有固定大小的输出,但应接受任意大的输入。

所以分组密码和散列函数真的是不同的动物。与其试图区分它们,不如更容易看出它们的共同点:即知道如何设计分组密码的人也相当擅长设计散列函数,因为分析数学工具是相似的(相当很多线性代数和布尔函数,真的)。

让我们来看看更正式的定义:

分组密码是由密钥选择的一系列排列。对于n的某个固定值,我们考虑n位块的空间B然后B的大小为2 n键是来自空间K的值,通常是另一个m序列的空间( m不一定等于n)。一个键k在2 n中选择一个排列B的可能排列

一个分组密码被认为是安全的,只要它在计算上与在2 n中均匀随机选择的排列没有区别!可能的排列。为了对此建模,假设攻击者可以访问两个黑盒,一个使用攻击者不知道的密钥实现分组密码,另一个是真正的随机排列。攻击者的目标是分辨哪个是哪个。他可以让每个盒子加密或解密他想要的任何数据。可能的攻击是尝试所有可能的密钥(有2 m个这样的密钥),只找到一个,它产生与其中一个框相同的值;这平均花费2 m-1 次密码调用。一个安全块密码是一种这样的通用攻击是最好的攻击。

AES 在 128 位块 ( n = 128) 和 128、192 和 256 位密钥上定义。

散列函数是一个单一的、完全定义的、可计算的函数,它将任意长度的位序列作为输入,并输出固定长度r的值(例如,对于 SHA-256, r = 256 位)。没有密钥,没有函数族,只有一个任何人都可以计算的独特函数。

如果满足以下条件,则认为哈希函数h是安全的:

  • 找到原像在计算上是不可行的:给定一个r位值x,找到m使得h(m) = x是不可行的。
  • 找到第二个原像在计算上是不可行的:给定m,找到与 m不同的m '是不可行的,这样h(m) = h(m')
  • 找到冲突在计算上是不可行的:找到彼此不同的mm'是不可行的,使得h(m) = h(m')

有一些通用攻击可以找到原像、第二原像或碰撞,成本分别为2 r2 r2 r/2因此,只有当r足够大以至于2 r/2是非常巨大的成本时,才能达到实际的安全性。在实践中,这意味着r = 128(一个 128 位的哈希函数,例如 MD5)是不够的

以一种非正式的方式,如果散列函数“看起来”是在接受相同输入的可能函数中随机且一致地选择的,那将是很好的。但这是一个定义不明确的属性,因为我们谈论的是一个独特的函数(概率总是隐含地表示平均值和重复的经验;你不能真正拥有一个函数的概率)。此外,作为一个随机函数与抵抗碰撞和原像并不完全相同。这是关于随机预言机模型的争论


然而,可以从分组密码中构建散列函数。这就是Merkle-Damgård构造的作用。这需要使用输入消息作为密钥块加密的; 所以分组密码根本没有按原意使用。使用 AES,这证明令人失望:

  • 它产生了一个 128 位输出的散列函数,对于 2011 年可用技术的安全性来说太小了。
  • 散列函数的安全性依赖于对分组密码没有相关密钥攻击相关密钥攻击在用于加密时对分组密码没有任何实际意义;因此,AES并不是用来抵御此类攻击,而事实上,AES一个几个弱点在这方面-而不是用于加密的担心,但一大隐忧,如果AES是在梅克尔- Damgard结构中使用。
  • 性能不会很好。

Whirlpool散列函数是一种基于AES启发的分组密码的设计,而不是真正的密码。该分组密码具有大大改进(和更重)的密钥调度,可以抵抗相关密钥攻击并使其可用作散列函数的核心。此外,该分组密码适用于 512 位块,而不是 128 位块。惠而浦被认为是安全的。众所周知,Whirlpool 非常慢,所以没有人使用它。

一些最近的哈希函数设计试图重用AES 的一部分——准确地说,是使用一个内部操作,该操作很好地映射到最近的 Intel 和 AMD 处理器所具有的AES-NI指令上。参见例如ECHOSHAvite-3作为SHA-3 竞赛的一部分,这两个功能都获得了相当多的曝光,并且被认为“相当安全”。最近的 Intel 和 AMD 处理器速度非常快。在其他较弱的架构上,如果散列函数性能有一定的机会实际上很重要,那么这些函数非常慢。

还有其他构造可以从块密码中生成散列函数,例如Skein中使用的构造;但它们也往往需要比 AES 所定义的更大的块。

总结:不仅分组密码和散列函数完全不同;但是用 AES 构建散列函数的想法被证明是有问题的。这并不容易,有限的 AES 块大小是主要障碍。

基本答案是它们是不同类型的算法。AES 是一种对称密钥算法。您不能将它用作与 RSA(一种公钥算法)或 SHA-256(一种散列算法)相同的角色。它们是不同的系统,其设计具有非常不同的特性和弱点。

然而,我停了下来,虽然很认真地解释了这个想法,但我只是说:“就是这样。” 毕竟,普遍意义上的散列是固定或缩小大小的数据的可重复表示。AES 可以通过 CBC 模式提供。然而,安全散列还有比简单归约更多的属性。

安全散列算法是一种单向系统。AES 以相同的方式加密和解密(对称密码),您可以为每个块进行 1-1 映射,使用给定密钥会发生什么。除非数据被链接并因此有损,否则您可以简单地将 AES“哈希”解密为源数据。

除了尝试不同的输入数据之外,无法合理地反转 SHA 过程。由于您不能使用 SHA-x 来加密某些东西,因此您不能使用 AES 来散列某些东西。

对哈希函数和对称密码之间的真正区别有简单的解释吗?

  • 密码是可逆的,散列函数是不可逆的
  • 密码输出的长度取决于输入的长度;无论输入如何,散列函数都会产生相同长度的输出
  • 加密散列函数中任何位置的单个位更改都会在散列输出中产生级联(剧烈)变化。通常,这不适用于密码。
  • 密码需要密钥,哈希不需要

两者的设计和目的根本不同,不可互换。

您基本上可以使用 Merkle-Damgard-construction 将任何块密码转换为散列函数,如果您按以下方式定义 Feistel 函数 F,则基本上可以使用 Feistel 网络将任何散列函数转换为块密码。

F(half_block, round_key) = 哈希(连接(half_block, round_key))

但是它的效率很低(计算时间很长),因为 F 的计算成本已经很高(它是一种迭代算法,例如在 SHA-512 的情况下使用 80 个内部“轮”),并且对于 Feistel 结构,F 本身被迭代多次。假设您有一个具有 80 轮轮函数 F 的 20 阶段 Feistel 网络,您每个块执行 1600 次 SHA-2“轮”。它还会导致相当大的块大小(散列函数输出大小的两倍),例如,如果您使用 SHA-512 作为散列函数,则使用 1024 位块密码。

但实际上,它不一定是“不安全的”。只是容易获得的“块密码”(而不是伪随机排列 - 不是比特/字节排列中的排列,而是“所有可能的输入块”和“所有可能的输出块”之间的双射映射意义上的排列)要多得多高效,更广泛使用,因此对良好伪随机排列的特性进行了更彻底的分析。如果您有计算能力可以浪费,请在 Feistel 网络中使用 SHA-512 作为分组密码。至少它的安全性可能不会低于 AES(前提是您添加了一个好的密钥计划来导出“轮密钥”),但是处理一个块需要大量的 CPU 周期。