哈希函数采用可变长度的输入数据并生成固定长度的输出值。 我们通常将其称为哈希代码、摘要、哈希或简称为哈希。
优秀作者列表的顶部具有哈希函数的几个重要属性:
哈希是一个单向过程。 因此,我们无法从其哈希中检索原始数据。
哈希函数是确定性的。 因此,当我们将相同的输入传递给哈希函数时,它总是生成相同的输出哈希代码,例如 sha-1 哈希值的长度为 160 位。
一致性 – 哈希值应均匀分布在可能的值上。
特定的哈希函数始终生成固定大小的输出。
它应该足够复杂,以最大限度地降低碰撞风险。
举个例子,我们来分析一下 j**a 的 String 类中使用的哈希函数:
在《有效的 J**A》一书中,约书亚·布洛赫 (Joshua Bloch) 解释说,值 31 是有意选择的,因为它是一个奇数素数。 使用偶数可能会导致信息丢失,因为乘以 2 类似于移位。 简而言之,使用具有多个除数的值可能会导致更多冲突。 因此,使用除数较小的数字更安全。
让我们看看 hashcode() 方法的实际效果:
分析结果,我们可以看到提到的哈希函数的一些属性。
首先,调用 hashcode() 是一个单向过程。 我们无法从生成的哈希值 (int) 中检索原始字符串。
其次,该方法是确定性的。 我们在测试变量上调用它两次,并得到相同的哈希值。
最后,它总是生成一个固定长度的哈希代码,因为 J**A 的 int 类型是一个固定大小,正如我们在 J**A VM 文档中读到的那样。
加密哈希函数是一组专用的哈希函数。 它们提供更高级别的安全性。 因此,它们被用于密码学目的,例如密码验证、数据完整性验证、区块链(加密货币)。
除了标准哈希函数的属性外,它们还可以满足以下条件,具体取决于其用途:
抗碰撞性:加密哈希函数必须完全防冲突。我们已经知道,标准哈希函数应该将冲突的风险降到最低。 然而,最小化并不意味着它们不会发生。 前面我们分析了一个 hashcode() 函数。 由于它返回一个 int 值,因此哈希值的变化受 int 范围 -2147483648 到 2147483647 的限制。 因此,当我们用完所有可能的值时,就会发生冲突(在某些情况下,甚至可能在此之前)。 因此,在加密哈希函数中,不可能发生任何可能的冲突情况。
前映像阻力:对于任何带有摘要的加密哈希函数,都不应该有任何快速的方法来查找其中的消息。
第二预像电阻:如果给定的函数具有抗碰撞性,则它始终具有第二前像抗性,但不能抗原成像。 出于加密目的,缺乏 prepimage 抵抗的哈希函数被认为是不安全的。
与随机预言的不可区分性“:应该不可能找到具有两个略有不同的哈希值的消息(输入值)。
计算任何消息的哈希值都应该很快。
如果消息已更改,即使它是次要消息,新哈希值也应与旧哈希值有很大不同。 换句话说,我们不应该能够找到新旧哈希码之间的任何相关性。
伪随机性。 简而言之,加密哈希函数应该是安全、有效和可靠的。