hash - 子字符串 md5 碰撞

标签 hash md5 substr hash-collision

我需要一个 4 字符的哈希值。目前我正在获取 md5() 哈希值的前 4 个字符。我正在对长度不超过 80 个字符的字符串进行哈希处理。这会导致碰撞吗?或者,假设我将散列少于 65,536 (164) 个不同元素,碰撞的可能性是多少?

最佳答案

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

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

  • 50% 机会 -> 300 条目
  • 1% 机会 -> 36 条目
  • 0.0000001% 机会 -> 2 条目。

因此发生碰撞的可能性相当高。

现在,您说您需要 4 个字符的哈希值。根据具体要求,您可以执行以下操作:

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

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

我将给出每个示例(在 PHP 中,但应该很容易翻译/看看发生了什么):

4 个十六进制位:

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

4 个 Alpha 位:

$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

关于hash - 子字符串 md5 碰撞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4681913/

相关文章:

ruby - 有没有更好的方法来判断一个 ruby 是否在另一个 ruby 中散列?

XSLT:获取或匹配 base64 编码数据的哈希值

ruby-on-rails - Ruby 语法错误,意外 '=' ,期望 ')'

java - Java 中的最大 SHA-1 哈希性能技巧

amazon-web-services - 使用curl获取S3文件的MD5值

c# - DotNet Core - 加密哈希函数返回不一致的结果

hash - 将 32-char md5 字符串转换为整数

regex - Oracle REGEXP_SUBSTR - 分号字符串提取

PHP 从右到左回显字符串的一部分

mysql - 需要按 varchar length() 进行子字符串化