【问题标题】:Is it safe to cut the hash?削减哈希是否安全?
【发布时间】:2013-04-24 11:15:39
【问题描述】:

我想存储大约 20 亿个字符串的哈希值。为此,我希望使用尽可能少的存储空间。

考虑一个理想的散列算法,它将散列返回为一系列十六进制数字(如 md5 散列)。 据我了解这个想法,这意味着我需要哈希不小于且不超过 8 个符号的长度。因为这样的散列能够散列 4+ 十亿(16 * 16 * 16 * 16 * 16 * 16 * 16 * 16)个不同的字符串。

所以我想知道将哈希切成一定长度以节省空间是否安全? (当然,哈希不应该冲突)

是/否/也许 - 我希望得到相关研究的解释或链接的答案。

附: - 我知道我可以测试 8 个字符的哈希是否可以存储 20 亿个字符串。但我需要将 20 亿个哈希值与它们的 20 亿个切割版本进行比较。这对我来说似乎并不简单,所以我最好在这样做之前先问清楚。

【问题讨论】:

  • 注意:将散列存储为 8 字节 字符串 将只允许 1
  • 20 亿个字符串的 32 位哈希不太可能不包含任何冲突。
  • 粗略的经验法则:要散列 n 事物而不发生冲突,您需要 n^2 垃圾箱。如果您有2^31 字符串,则需要2^62 箱以避免冲突。
  • 罗伯特·库珀:很抱歉,您所说的“垃圾箱”是什么意思?

标签: hash md5 keccak


【解决方案1】:

哈希是一个数字,而不是一串十六进制数字(字符)。在 MD5 的情况下,它是以有效形式保存的 128 位或 16 字节。如果您的问题仍然存在,您当然可以考虑截断数字(通过强制转换为一个单词或第一个位移)。好的哈希算法会均匀地分配到所有位。

附录:

通常,每当您处理哈希时,您都想检查字符串是否真的匹配。这处理了碰撞哈希的可能性。你削减的哈希越多,你就会得到越多的冲突。但最好在这个阶段做好计划。

【讨论】:

  • 好的,这是一个数字。但是 2^32 仍然是我上面写的 4+十亿个组合。哪些散列算法是“好”的? Md5 有碰撞。你指的是什么哈希算法?
  • @Termos:好吧,我误解了你的问题。也许您根本不需要任何散列。
【解决方案2】:

在只能表示 2x 个不同哈希值的哈希域中存储 x 值是否安全完全取决于您是否可以容忍冲突。

哈希函数实际上是随机数生成器,因此您计算的 20 亿个哈希值将平均分布在 40 亿个可能的结果中。这意味着您受制于Birthday Problem。

在您的情况下,如果您仅使用 2^32(40 亿)个可能的哈希值计算 2^31(20 亿)个哈希,则至少两个具有相同哈希(冲突)的机会非常非常接近100%。 (而且三个相同的可能性也非常非常接近 100%。依此类推。)我找不到根据这些数字计算可能发生碰撞次数的公式,但我怀疑这是一个巨大的数字.

如果在您的情况下哈希冲突不是灾难(例如在 Java 的 HashMap 实现中,它通过将哈希目标转换为共享相同哈希键的对象列表来处理冲突,尽管以降低性能为代价)然后也许你可以忍受大量碰撞的确定性。但是,如果您需要唯一性,那么您需要一个大得多的散列域,或者您需要为每条记录分配一个保证唯一的序列号,具体取决于您的目的。

最后,请注意 Keccak 能够生成任何所需的输出长度,因此花费 CPU 资源生成较长的哈希输出只是为了在之后将其缩减是没有意义的。你应该能够告诉你的 Keccak 函数只给出你需要的位数。 (另请注意,Keccak 输出长度的变化不会影响初始输出位,因此结果将与您之后手动按位修剪完全相同。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-10
    • 2012-11-14
    • 1970-01-01
    • 2018-11-04
    • 1970-01-01
    • 1970-01-01
    • 2011-06-08
    相关资源
    最近更新 更多