【问题标题】:Are fragments of hashes collision-resistent?散列碎片是否抗碰撞?
【发布时间】:2010-05-01 03:42:24
【问题描述】:

如果您只使用 MD5 哈希的前 4 个字节,这是否意味着理论上只有 255^4 中的 1 个发生冲突的机会?也就是说,哈希是否设计为只需要使用返回哈希的一小部分(比如哈希是某个大小的文件)?

【问题讨论】:

    标签: algorithm hash md5


    【解决方案1】:

    请记住,即使不考虑聪明的攻击者故意试图引起冲突,一旦您散列的对象数量与 正方形相当,您也需要开始担心意外冲突散列空间的根...对于一个 32 位散列键,只有几万个对象。这来自所谓的birthday paradox

    【讨论】:

    • 我需要知道的事情,谢谢。看起来我应该把它增加到 8 个字节。
    • @Mark:即使有 8 个字节,在 2^32 = 400 万个哈希之后,您仍然会(有 50% 的可能性)发生冲突
    【解决方案2】:

    是 256,而不是 255。

    假设 MD5 是一个安全的散列函数(事实证明它是安全的,但是为了便于讨论,我们假设它是安全的),那么它的行为应该像一个random oracle,一个输出均匀随机值的神话对象,唯一的约束是它“记住”其先前的输出并在给定相同输入的情况下再次返回相同的值。

    截断随机预言的输出会产生另一个随机预言。因此,如果保留 32 位,则与两个不同输入消息发生冲突的概率为 2^32 中的 1(即 256^4 中的 1)。

    现在有一个称为birthday paradox 的东西,它表示,对于大约 2^16 个不同的输入,2^16 个对应的输出中的两个很有可能发生冲突。

    MD5 已被证明在某些方面是不安全的——尤其是与冲突有关的任何事情。当前的默认建议是SHA-2(一个包含四个函数的系列,输出大小分别为 224、256、384 和 512 位)。目前正在通过公开竞争定义一个新的(美国)标准,代号为SHA-3。这是一个漫长的过程;新职能应在 2012 年年中选定。剩下的一些候选者(目前是 14 个,最初的 51 个)比 SHA-2 快得多,一些在性能上接近 MD5,同时更加安全。但这有点新,所以现在你应该默认使用 SHA-2。

    【讨论】:

    • “MD5 已被证明在某些方面是不安全的——尤其是与碰撞有关的任何事情。”我一直在阅读它的方式是,md5 不是关于意外碰撞的问题 - 只有故意(与安全相关的)碰撞。
    【解决方案3】:

    假设我们有一个预先确定的消息1。 hash1 = md5(message1)

    现在随机选择一个message2,并设置hash2 = md5(message2)。

    理论上,hash2 的前四个字符与预先确定的 hash1 的前四个字符匹配的概率为 1/255^4。

    知道 message1 的攻击者也很难想出具有相同哈希值的不同 message2。这称为第二原像电阻。但是,即使使用完整的 MD5,也存在比理论上更好的原像攻击。

    MD5 是completely broken 用于冲突。这意味着攻击者(在几个小时内)提出两条具有相同哈希值的消息(更不用说相同的前四个字节)是非常可行的。攻击者可以选择两条消息,但这仍然会造成重大损害。例如,参见 poisoned message 示例。

    【讨论】:

    • 谢谢,这就是我的假设,所以想知道 16 个字节的意义是什么(在 md5 的情况下)我假设额外的字节可能只是算法的产物,而不是绝对必要的东西。一个人应该使用多少位才安全。
    • 嗯,数字越多,需要的冲突就越少;为什么要截断哈希?
    • 255^4 在许多散列应用程序中实际上并不是那么大的数字。只有大约 40 亿;有许多应用程序使用散列来记录数百万甚至数十亿的记录,即使是总计约 1/1000 的碰撞机会也是一件坏事。
    • 我会截断,因为我需要一个合理长度的字母数字文件名,而 16 个字节对应的有效字符数是 2-3 倍。
    • 32 个字符对于文件名来说太长了? Git 到处使用哈希作为文件名
    【解决方案4】:

    如果您要生成唯一标识符,您可能希望改用 UUID。这些旨在最大限度地减少碰撞的变化,以便在实践中它们永远不会发生。

    如果您担心文件名太长,当大多数操作系统支持长达 255 个字符的名称时,这是一个需要注意的特殊问题,您可以随时将文件名拆分为路径和文件名组件。这样做的好处是将文件拆分到不同的目录中:

    fdadda221fd71619e6c0139730b012577dd4de90
    
    fdadda221fd71619e6c/0139730b012577dd4de90
    
    fdad/da22/1fd7/1619/e6c0/1397/30b0/1257/7dd4/de90
    

    【讨论】:

    • 找不到 UUID 的任何平台 sdk 函数。我目前正在使用 CryptCreateHash - 工作正常。
    【解决方案5】:

    取决于散列的目的。

    在哈希表中使用的哈希函数往往在低位(用于查找数组索引)中比在高位中具有更多的“随机性”。校验和和加密哈希函数分布更均匀。

    【讨论】:

    • 好吧,我正在使用 Windows 的 md5 哈希。当您说较低的位时,您是指返回的字节数组中的较低索引吗?
    • 我认为两个字符串之间某种明显的相似性不会使它们的哈希值更容易发生冲突(只要它们实际上不同)。
    • 除非散列算法缺少diffusion,否则不会。见avalanche effect
    猜你喜欢
    • 2015-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多