“单向”意味着“很难”弄清楚 x 给出了哈希结果 h(x)。由于“硬”一词没有明确定义,因此也没有明确定义什么是单向函数。
“无冲突”意味着对于每对 x 和 y,h(x) 与 h(y) 不同,其中 x 与 y 不同。这是一个明确的定义,但很难证明 h(x) 是否真的是单向函数。您必须比较每对两个 32 位数字的哈希结果并测试它们是否不同。
最好的方法是计算所有可能的 h(x) 并将它们与它们的 x 一起存储在一个数组中。然后按 h(x) 对数组进行排序,然后遍历这个列表并测试两个邻居是否具有相同的 h(x)。如果您没有找到相同的邻居,则您的哈希函数不会发生冲突。
但是:如果你真的能做到这一点,你的函数就不能真正成为单向函数,因为你刚刚生成的证明无碰撞的列表是一个非常快速的查找-该表可让您在 log(n) 的搜索时间内找到每个 h(x) 的 x。这甚至可能比从 x 计算 h(x) 更快。
那么让我们来计算一下,这需要多长时间
32 位整数是 0 到 4294967295 之间的数字。假设从 x 计算 h(x) 需要 0.1 毫秒。根据散列算法,即使在便宜的笔记本上也是现实的。因此,在 1 秒内,您获得 10,000 个哈希数字,在一天内获得 864,000,000 个数字。您只需 5 天时间即可计算出所有可能的数字并将它们存储在磁盘上。
每个条目有 4 个字节用于 32 位数字,5 个字节用于 36 位哈希。制作 9 个字节。所以完整的表有 38,654,705,664 字节。这是 38 GB。您可以将其存储在每个低预算笔记本上。这张表的排序需要几分钟,这还不包括我们计算所需的 5 天。
因此,在 200 美元的二手笔记本上构建这张桌子绝对没有问题。一旦你有了它,很容易证明它是否真的没有碰撞,但是通过构建这个表你也证明了它不是一个单向函数!
那么最好的解决方案是什么?
- 生成一个包含 4,294,967,296 个随机 36 位数字的列表,为每个条目添加一个 32 位数字,即条目行号(从 0 开始)。
- 对列表进行排序。
- 重置 did-change-a-number-flag
- 浏览列表。将实际条目与前一个条目进行比较。如果它们不同,请转到第 7 步。
- 用新的随机 36 位数替换 36 位数
- 设置 did-change-a-number-flag
- 如果您到达列表末尾:是否设置了标志?如果是,请转到第 2 步。
- 按 32 位数字(前行号)对列表进行排序
在第 1 步之后,列表将包含 6.25% 的碰撞(约 2.684 亿次碰撞)。在每次迭代中,您将碰撞次数减少到第 16 部分。消除所有冲突大约需要 8 次迭代。
这个 38 GB 表现在是您超快速绝对无冲突的哈希函数。它与任何 32 到 36 位散列函数一样是单向的。含义:对于给定的 h(x),没有其他无冲突哈希函数更难找到 x。