是否有可能获得相同的 SHA1 哈希? [复制]

Posted

技术标签:

【中文标题】是否有可能获得相同的 SHA1 哈希? [复制]【英文标题】:Is it possible to get identical SHA1 hash? [duplicate] 【发布时间】:2011-01-29 13:51:23 【问题描述】:

给定两个不同的字符串 S1 和 S2 (S1 != S2),是否有可能:

SHA1(S1) == SHA1(S2)

是真的吗?

    如果是 - 概率是多少? 如果不是 - 为什么不呢? 输入字符串的长度是否存在上限,其重复概率为 0?或者 SHA1 的计算(因此重复的概率)与字符串的长度无关?

我试图实现的目标是散列一些敏感的 ID 字符串(可能与父 ID 等其他一些字段连接在一起),以便我可以使用散列值作为 ID(例如在数据库中)。

例子:

Resource ID: X123
Parent ID: P123

我不想公开我的资源标识的性质以允许客户看到“X123-P123”。

相反,我想创建一个新的列哈希(“X123-P123”),假设它是 AAAZZZ。然后客户端可以请求 id 为 AAAZZZ 的资源并且不知道我的内部 id 等。

【问题讨论】:

由于 SHA-1 的长度是 160 位,因此对于固定字符串的概率总是高于 2^-160。 假设暴力攻击,均匀分布 是的,冲突是可能的。但你更有可能赢得强力球。更有可能。除非您使用哈希作为键,否则我看不出这怎么会成为一个问题,虽然这是一个非常有吸引力的提议,但不建议这样做。 确实,我正在考虑使用哈希作为我的资源的 id。 这个想法看起来不错,但为什么呢?不过你可以。 【参考方案1】:

您所描述的称为碰撞。冲突必然存在,因为 SHA-1 接受更多不同的消息作为输入,它可以产生不同的输出(SHA-1 可以吃掉最多 2^64 位的任何位串,但只输出 160 位;因此,至少有一个输出value 必须弹出多次)。这个观察对于任何输出小于输入的函数都是有效的,不管这个函数是否是一个“好”的散列函数。

假设 SHA-1 的行为类似于“随机预言机”(一个基本上返回随机值的概念对象,唯一的限制是一旦它在输入 mv /em>,此后它必须始终在输入 m 上返回 v),那么对于任何两个不同的字符串 S1 和 S2,碰撞的概率应该是 2^(- 160)。仍然假设 SHA-1 表现得像一个随机预言机,如果您收集了许多输入字符串,那么您将在收集大约 2^80 个这样的字符串后开始观察冲突。

(这是 2^80 而不是 2^160,因为使用 2^80 个字符串,您可以制作大约 2^159 对字符串。这通常被称为“生日悖论”,因为大多数人在应用于生日碰撞。请参阅the Wikipedia page 的主题。)

现在我们强烈怀疑 SHA-1 确实真的表现得像随机预言机,因为生日悖论方法是随机预言机的最佳碰撞搜索算法。然而,有一个公开的攻击应该在大约 2^63 步内发现碰撞,因此比生日悖论算法快 2^17 = 131072 倍。这种攻击不应该在真正的随机预言机上可行。请注意,这种攻击实际上尚未完成,它仍然是理论上的(一些人 tried but apparently could not find enough CPU power)(更新:截至 2017 年初,有人确实计算了 SHA-1 collision使用上述方法,它完全按照预期工作)。然而,这个理论看起来很合理,看起来 SHA-1 确实不是随机预言机。相应地,至于碰撞的概率,好吧,所有的赌注都没有了。

至于您的第三个问题:对于具有 n 位输出的函数,如果您可以输入超过 2^n 条不同的消息,则必然存在冲突,即如果最大输入消息长度大于n。如果 m 低于 n,那么答案就不那么简单了。如果函数表现为随机预言机,那么发生碰撞的概率会随着 m 而降低,而不是线性降低,而是在 m=n/2附近有一个陡峭的截止值>。这与生日悖论的分析相同。对于 SHA-1,这意味着如果 m 则很可能没有碰撞,而 m > 80 使得至少存在一次碰撞的可能性很大(对于 m > 160,这是肯定的)。

请注意,“存在碰撞”和“您发现碰撞”之间存在区别。即使碰撞必须存在,每次尝试时您仍然有 2^(-160) 的概率。上一段的意思是,如果你不能(从概念上)尝试 2^160 对字符串,那么这样的概率是毫无意义的,例如因为您将自己限制为少于 80 位的字符串。

【讨论】:

那么...您的意思是,对于长度超过 80 位的字符串,可能至少存在一次冲突?如果我采用 40 位字符串或 20 位字符串怎么办?我知道这很愚蠢 - 但是否有一个功能可以确保没有重复?我想这将只是一个常规映射函数,而不是哈希(即用 A 等替换数字 1)——这使得我为此目的使用 SHA1 毫无意义。 @drozzy:如果您采用 40 位输入字符串,那么其中两个哈希到相同值的概率非常低。但是如果不彻底尝试它们,您就无法确定(使用 40 位字符串,这是可行的,使用大型 PC 和几天或几周)。当然,如果您没有冲突,那么您真正拥有的是从所有字符串到不同的 160 位值的映射。对于“隐藏敏感信息”,关键字是“机密性”,你应该研究加密而不是散列。 我发现这有助于意识到赢得大多数国家公共彩票的几率非常小,但奖金通常每周或几周内发放,所以无论几率多么小,它们会发生。 2^-x 可能是一个非常小的数字,但无论哪种方式,都无法确定碰撞是否会发生。或者准确地说:2^-x 既不是一也不是零。同样,尽管机会很小,但无论您如何约束 hash(1) 匹配 hash(2),都无法阻止它。 在撰写本文时,单向函数是否存在仍然是一个开放的理论问题。如果他们不这样做,那么在多项式时间内可计算的每个哈希函数都容易受到碰撞攻击。 security.googleblog.com/2017/02/…【参考方案2】:

是的,因为pigeon hole principle 是可能的。

大多数散列(也包括 sha1)具有固定的输出长度,而输入是任意大小。因此,如果您尝试足够长的时间,您可以找到它们。

但是,加密哈希函数(如 sha 系列、md 系列等)旨在最大限度地减少此类冲突。已知的最佳攻击需要 2^63 次尝试才能找到碰撞,因此机会为 2^(-63),在实践中为 0。

【讨论】:

我在编辑答案时只是要提到鸽子洞原理。大声笑我要把它拿回来,因为它看起来像我抄袭你。 最佳攻击需要 2^63 工作这一事实并不意味着任何两个哈希冲突的机会是 2^63 中的 1 - 所有已知的攻击都需要构造两个冲突消息,而不是找到一个原像。【参考方案3】:

git 使用 SHA1 哈希作为 ID,仍然在 2014 年没有已知的 SHA1 冲突。显然,SHA1 算法很神奇。我认为对于您的长度的字符串不存在碰撞是一个不错的选择,因为它们现在已经被发现了。但是,如果您不相信魔法并且不是赌徒,您可以生成随机字符串并将它们与您在数据库中的 ID 相关联。但是,如果您确实使用 SHA1 哈希并成为第一个发现冲突的人,您可以更改您的系统以使用随机字符串,将 SHA1 哈希保留为旧 ID 的“随机”字符串。

【讨论】:

截至今天,已发布 SHA1 冲突:shattered.it【参考方案4】:

在散列函数中几乎总是可能发生冲突。迄今为止,SHA1 在生成不可预测的冲突方面非常安全。危险在于,当可以预测碰撞时,无需知道原始哈希输入即可生成相同的哈希输出。

例如,去年针对 MD5 的攻击是针对 SSL 服务器证书签名进行的,例如 Security Now 播客第 179 集。这使得老练的攻击者能够为流氓网站生成伪造的 SSL 服务器证书,并且似乎成为真正的东西。因此,强烈建议避免购买 MD5 签名的证书。

【讨论】:

【参考方案5】:

您所说的称为碰撞。这是一篇关于 SHA1 冲突的文章: http://www.rsa.com/rsalabs/node.asp?id=2927

编辑:所以另一个回答者比我提到鸽子洞原理大声笑,但要澄清这就是为什么它被称为鸽子洞原理,因为如果你有一些洞可以让信鸽筑巢,但你有更多鸽子比洞,那么一些鸽子(输入值)必须共享一个洞(输出值)。

【讨论】:

以上是关于是否有可能获得相同的 SHA1 哈希? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

散列哈希是不是使其更安全? [复制]

是否可以将 40 个字符的 SHA1 哈希转换为 20 个字符的 SHA1 哈希?

我的 SHA1 字符串是不是有可能是非唯一的? [复制]

SHA256、SHA1、SHA384 哈希到 JSON Web 令牌

如何生成随机 SHA1 哈希以用作 node.js 中的 ID?

1.2常用安全加密