我们不能创建一个与 SHA-256 中的另一个字符串产生相同哈希的字符串吗?

信息安全 哈希 密码破解 sha256
2021-09-01 06:23:11

假设我们有一个名为 s2 的单独散列算法,它将转换Hellodug84nd8.

如果我们可以采用算法并对其进行逆向工程以生成类似的字符串8GN492MD也会输出dug84nd8,难道不是这样说(s2("Hello") = s2("8GN492MD")) == true),让黑客进入吗?

我觉得我错过了一些东西,但我不知道它是什么。

4个回答

你的前提有缺陷。您说您想对哈希函数进行“逆向工程”。无需对其进行逆向工程 - 它的实现是公开的。

你不能做的是反转它(也许这就是你的意思),因为它不可逆。您可以很容易地看出它不是一个可逆函数,因为域的大小(可能的输入数量)大于范围的大小(可能的输出数量)。范围是 2^256(可能的输出状态),输入空间的大小是无限的(技术上显然是 2^(2^64),但比 2^256 大得多)。这正是允许碰撞的原因(根据鸽洞原理,每个输出必须有多个可能的输入 - 至少对于其中一个输入)。

散列函数的整个设计使得在计算上很难找到这些冲突。散列的三个属性(第一抗原像性、第二抗原像性和抗碰撞性)更准确地描述了该属性。

因此,您的问题的答案是,即使您确切知道该功能的工作原理,该功能的设计也故意使其难以实现。

有关函数如何令人惊讶地执行的详细信息(在稍微不同的上下文中)(例如,为什么不可能“向后退一步”来反转它们),请参阅此处的答案。

您正在混合对哈希函数的攻击。可以在P. Rogaway 和 T. Shrimpton的Cryptographic Hash-Function Basics: Definitions, Implications, and Separations for Preimage Resistance、Second-Preimage Resistance 和 Collision Resistance中找到对密码散列函数的一般攻击的正式定义。可以简单地给出;

  • 原像攻击:给定一个哈希值h,找到一条消息 m 使得h=Hash(m). 考虑将密码的哈希值存储在服务器上。例如,攻击者将尝试找到您帐户的有效密码。

  • 第二个原像攻击(也称为弱碰撞):给定一条消息m1,找到另一条m2消息m1≠m2Hash(m1)=Hash(m2)一个例子是伪造给定的消息。

  • 碰撞攻击(也称为强碰撞):找到两个散列到相同输出的输入:a并且b使得H(a)=H(b), a≠b.

SHA-256 还没有被任何这些通用攻击破坏。请参阅:是什么让 SHA-256 安全?在crypto.stackexchange上。

如果我们可以采用算法并对其进行逆向工程以生成类似的字符串8GN492MD也会输出dug84nd8

  • 如果我们只考虑这是前映像攻击,成本是O(2^256)SHA-256。请注意,原像攻击的目的不是找到原始输入,而是找到具有相同哈希值的输入。如果没有对输入进行外部测试,则无法确定找到的原像就是原像。而且,原像的实际搜索空间可能比原像攻击句柄大得多。

    原像攻击有一种变体,当消息空间不足时会发生这种攻击,例如对电话号码进行哈希处理在这种情况下,很容易找到原像。

如果我们可以采用该算法并对其进行逆向工程以生成一个类似 8GN492MD 的字符串,该字符串也会输出dug84nd8,它不会这样说(s2("Hello") = s2("8GN492MD")) == true),让黑客进入吗?

  • 如果我们以更简单的方式考虑以上内容;给定Hellodug84nd8=SHA256(Hello)找到与您请求的哈希值相同的另一条消息,那么这是第二次预映像攻击,成本是O(2^256)SHA256。

第二个原像是您正在寻找的。这是不可行的,不仅 SHA-256,而且没有任何加密散列函数以这种方式被破坏。

  • SHA-256 的碰撞攻击成本是O(2^128)由于生日攻击的概率为 50%。在碰撞攻击中,攻击者可以自由选择ab这不是您的情况,因为您从固定消息开始。

结论是,截至 2020 年,这些攻击中的任何一种对于 SHA-256 都是不可行的。


在这些错误最上面的答案

范围是 2^256(可能的输出状态),输入空间的大小是无限的(技术上显然是 2^(2^64),但比 2^256 大得多)。这正是允许碰撞的原因(根据鸽洞原理,每个输出必须有多个可能的输入 - 至少对于其中一个输入)。

由于 NIST 的填充标准,SHA256 输入空间受到限制。一个人最多可以散列 2^64 位,因此最多有 2^(2^64) 个不同的消息,因为消息的大小在填充的末尾以 64 位编码。

鸽笼原理只说至少有一个鸽笼有不止一只鸽子。它不谈论其他可以为空或不为空的。有了这个,我们可以说至少必须有一次碰撞。有趣的是,我们不知道限制为 64 位的 SHA256 获得所有 64 位值。我们对 SHA256 的期望是它与均匀随机没有区别。

您可以很容易地看出它不是一个可逆函数,因为域的大小(可能的输入数量)大于范围的大小(可能的输出数量)。

那也不对。取模 2^256 作为哈希,那么它是不可逆的。然而,一个给定的哈希值可以很容易地计算出原像,给定x, a;; x+k 2^265是前图像。换句话说,我们颠倒了地图。正确的定义是一个在计算上无法求逆的函数

让黑客进来?

当然。但问题是我们实际上不知道如何找到另一个以有效方式产生相同哈希的字符串。至少对于 SHA-256 和其他广泛使用的散列算法。请注意,这些算法是公开的,不需要逆向工程,这不会改变任何东西。这简直太难了,实际上那些算法是故意以这种方式设计的。

整个问题归结为求解一些函数 f 和一些 y 的 f(x)=y 方程。一种可能性是扫描所有 x,假设域是可枚举的。但这是低效的,只有在我们已经知道存在解决方案的情况下才有效(我不确定 SHA 的所有值是否都多次获得)。其他可能性通常是未知的。

也许这是一个教育问题。在学校里,我们经常被告知要解方程。线性、多项式、对数、正弦等。他们没有告诉你的是,他们选择这些方程的方式是可解的,而且方式相对简单。但事实上,即使是现在最聪明的人也不知道如何解决大多数方程。在这里,您偶然发现了一个这样的(极其重要的)示例。

请注意,这种情况将来可能(并且已经对其他哈希函数)发生变化。

我相信@kelalaka 的回答是最准确的,但我想添加一个示例,希望能对这个问题有所了解。

首先,您完全准确,您可以追溯电路中的所有逻辑并最终发生冲突。 然而,一个好的密码散列函数的特征之一是这个练习基本上和随机猜测一样困难。

考虑以下电路。M1-M3 是消息的位。给定一条消息101和 的种子1,我们得到 的输出1

电路中的三个链式异或。

101现在,让我们尝试通过回溯电路来找到与之冲突的不同消息。从输出中,我们知道 M3 可能是10让我们选择0; 这意味着另一条腿必须是11XOR01)。现在我们来到M2。我们也会0再次选择。现在我们看看M1。我们会选择1M1。但是,哦。种子现在必须是0. 100仅当种子为0.

显然,在这个非常简单的示例中,我们可以简单地将 M1 分配为0,然后我们的种子就会1如我们预期的那样。但是这个例子的重点是强调反馈和链接元素,这些元素使得这种简单的“只是回溯电路”方法在真正的密码散列算法中变得更加复杂。实现这些算法所需的“电路”非常复杂,因为它由乘法、求幂、模运算等组成。其中一些计算的递归性质使得向后追踪电路成为一项大规模的分支练习。同样,这并非不可能。相反,它就像随机猜测一样难。