substr md5碰撞

时间:2011-01-13 15:42:43

标签: hash md5 substr hash-collision

我需要一个4个字符的哈希值。目前我正在使用md5()哈希的前4个字符。我正在散列一个长度不超过80个字符的字符串。这会导致碰撞吗?或者,碰撞的几率是多少,假设我的哈希值小于65,536(16 4 )不同的元素?

3 个答案:

答案 0 :(得分:4)

好吧,md5的每个字符都是十六进制位。这意味着它可以具有16个可能值中的一个。因此,如果您只使用前4个“十六位”,则表示您可以拥有16 * 16 * 16 * 1616^4或65536或2^16种可能性。

因此,这意味着结果的总可用“空间”仅为16位宽。现在,根据Birthday Attack/Problem,碰撞有以下几率:

  • 50%偶然 - > 300条目
  • 1%偶然 - > 36条目
  • 0.0000001%偶然 - > 2条目。

因此碰撞的可能性非常大。

现在,你说你需要一个4个字符的哈希值。根据具体要求,您可以:

  • 16^4(65,536)个可能值的4个十六进制位
  • 26^4(456,976)个可能值的4个字母位
  • 36^4(1,679,616)个可能值的4个字母数字位
  • 4个ascii可打印位,约为93^4(74,805,201)个可能的值(假设ASCII 33 - > 126)
  • 256^4(4,294,967,296)个可能值的4个完整字节。

现在,您选择的将取决于实际用例。哈希是否需要传输到浏览器?你是如何存储的等等。

我将举一个例子(在PHP中,但应该很容易翻译/看看发生了什么):

4个Hex-Bits

$hash = substr(md5($data), 0, 4);

4位字

$hash = substr(base_convert(md5($data), 16, 26)0, 4);
$hash = str_replace(range(0, 9), range('S', 'Z'), $hash);

4个字母数字位

$hash = substr(base_convert(md5($data), 16, 36), 0, 4);

4个可打印的Assci位

$hash = hash('md5', $data, true); // We want the raw bytes
$out = '';
for ($i = 0; $i < 4; $i++) {
    $out .= chr((ord($hash[$i]) % 93) + 33);
}

4个完整字节

$hash = substr(hash('md5', $data, true), 0, 4); // We want the raw bytes

答案 1 :(得分:1)

Surprisingly high indeed.正如您从this graph of an approximate collision probability(来自wikipedia page的公式)所看到的那样,只有几百个元素,您发生碰撞的概率超过50%。

当然,请注意,如果您面临攻击者提供字符串的可能性,您可能会认为它是100% - 在16位搜索空间中发现碰撞的扫描几乎可以在任何时候完成现代PC。或者甚至是任何现代手机。

答案 2 :(得分:0)

4个第一个字符包含4 * 4 = 16位数据,因此碰撞肯定会达到65536个元素,并且由于生日攻击,它将被发现更快。你应该使用更多的哈希值。