哈希函数 MD5 30 长度

Hash Function MD5 30 length

我使用 MD5

从给定的字符串生成 32 位唯一哈希码
    MessageDigest.getInstance("MD5")
             .digest("SOME-BIG-STRING").map("%02x".format(_)).mkString

    //output: 47a8899bdd7213fb1baab6cd493474b4

是否可以生成 30 位而不是 32 位,如果这样做会有什么问题?

使用任何其他哈希算法来支持 30 个字符长和 1 万亿个唯一字符串冲突概率?

安全性并不重要,唯一性是必需的。

Is it possible to generate 30 digit long instead of 32 digit and what will be problem if it do so?

  1. 是。

  2. 您将碰撞概率提高了 2 倍8

Any another hash algorithm to use to support 30 character long and 1 trillion unique strings collision probability ?

可能吧。取由任何加密强度哈希算法生成的哈希的前 30 个十六进制数字具有大致等效的唯一性属性。

Security is not important, uniqueness is required ?

在这种情况下,MD5 不再被认为是安全的这一事实没有实际意义。 (请注意,MD5 不再被认为是安全的原因是 设计 碰撞在计算上是可行的;即 找到 第二个输入给定的 MD5 哈希。)

但是,无法保证哈希值的唯一性。即使使用生成 N 位哈希的“完美”加密强度哈希函数,任意 2 个任意(不同)输入发生冲突的概率也是 2N 中的一个。对于足够大的 N 值,概率非常小。但它永远不会为零。

对于从字符串生成唯一 ID,散列函数永远不是正确的答案。

您需要定义文本字符串(例如“v1.0.0”)到 30 个字符长的字符串(例如“123123...”)的一对一映射。这也称为 双射 ,尽管在您的情况下是 射入 (从输入到输出的简单一对一映射,不一定上)可能就足够了。作为撰写本文时的另一个答案,哈希函数不一定确保此映射,但还有其他可能性,例如全周期 linear congruential generators (如果它们采用种子,您可以映射一个 -对一到输入字符串值)或其他可逆函数。

但是,如果可能的输入字符串集大于可能的输出字符串集,则您无法将所有输入字符串与所有输出字符串一对一映射(不创建重复项),因为pigeonhole principle.

另见这个问题:How to generate a GUID with a custom alphabet, that behaves similar to an MD5 hash (in JavaScript)?

确实,如果使用散列函数,冲突的可能性将接近于零,但绝不会完全为零(这意味着重复的风险将始终存在)。如果我们以MD5为例(产生2^128个hash码中的任何一个),那么粗略地讲,只有在产生2^64个ID之后,意外碰撞的可能性才变得不可忽略,这远远超过1万亿

但是 MD5 和其他哈希函数并不是做你想做的事情的正确方法。接下来讨论这个。


如果您不能将输入字符串的格式限制为 30 位,也不能将它们压缩到 30 位或更少,并且不能容忍重复的风险,那么下一个最好的办法是创建一个数据库 table 将您的输入字符串映射到随机生成的 ID。

此数据库 table 应该有两列:一列包含您的输入字符串(例如“<UUID>-NAME-<UUID>”),另一列包含随机生成的与这些字符串关联的 ID。由于随机数不能确保唯一性,每次创建新的随机 ID 时都需要检查随机 ID 是否已存在于数据库中,如果存在,则尝试使用新的随机 ID(但有可能重复发现会随着 ID 大小的增长而缩小)。