【问题标题】:Hash Function MD5 30 length哈希函数 MD5 30 长度
【发布时间】:2020-12-11 12:38:19
【问题描述】:

从给定的字符串中,我使用MD5 生成 32 位唯一哈希码

    MessageDigest.getInstance("MD5")
             .digest("SOME-BIG-STRING").map("%02x".format(_)).mkString

    //output: 47a8899bdd7213fb1baab6cd493474b4

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

还有其他哈希算法可用于支持 30 个字符长和 1 万亿个唯一字符串的冲突概率吗?

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

【问题讨论】:

  • 这能回答你的问题吗? Hash function to produce a code of 30 chars?
  • md5 不安全。有一些方法可以故意生成碰撞输入。如果您的代码依赖 md5 不产生冲突,那可能是没有根据的。尤其是在以任何方式涉及用户提供的数据时。
  • 我有 1 万亿个唯一字符串,想生成每个字符串对应的唯一哈希。最好的方法是什么?

标签: java scala md5


【解决方案1】:

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

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

但是,如果可能的输入字符串集大于可能的输出字符串集,则由于 @ 987654322@.

另请参阅此问题:How to generate a GUID with a custom alphabet, that behaves similar to an MD5 hash (in JavaScript)?

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

但是 MD5 和其他哈希函数并不是做你想做的事情的正确方法。这将在后面讨论。


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

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

【讨论】:

  • 我有一个 1 万亿个不同的字符串,每个字符串的长度为 800。对于每个字符串,我想生成 30 长度的唯一哈希。
  • 在这种情况下,您通常不能将所有 800 个字符的字符串与所有 30 位字符串一对一映射(根据鸽巢原理),除非您限制 800 个字符的格式以某种方式串起来。您将不得不以某种方式利用 800 个字符的输入字符串中的冗余,以保证它们无损压缩为 30 个十进制数字,这可能会也可能不会。但是,您可以轻松地将 1 万亿个唯一值映射为每个包含 14 个或更多十进制数字的字符串。输入字符串的格式是什么?
  • (续)您的应用程序能否容忍为不同的输入字符串生成相同 ID 的风险?
  • 47a8899bdd7213fb1baab6cd493474b4-name-47a8899bdd7213fb1baab6cd493474b4........
  • -NAME-- 像这样 10 次是每个字符串,应用程序不能冒两次相同 id 的风险
【解决方案2】:

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

  1. 是的。

  2. 您将发生碰撞的概率增加了 2 倍8

还有其他哈希算法可用于支持 30 个字符长和 1 万亿个唯一字符串的冲突概率吗?

大概吧。取任何加密强度哈希算法产生的哈希的前 30 个十六进制数字具有大致相同的唯一性属性。

安全不重要,需要唯一性?

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

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

【讨论】:

  • 所以如果我生成 30 位 md5 哈希,那么碰撞概率是 1/ 2^30 ?我说的对吗
  • 没有。一个十六进制数字是 4 位。 1 in 2^120
  • UUID stackoverflow.com/questions/24876188/… 可能发生相同的概率
  • 我不知道有一个。但正如我所说,实施起来很简单。使用常规 MD5 生成哈希,并丢弃 2 个十六进制数字/8 位/1 个字节。
  • 像生日悖论问题,你能帮我找出至少有一次碰撞的记录吗?
猜你喜欢
  • 2011-05-05
  • 1970-01-01
  • 2012-08-17
  • 1970-01-01
  • 2012-05-28
  • 2010-09-22
  • 1970-01-01
  • 2018-07-14
  • 2020-12-08
相关资源
最近更新 更多