我有一个对象集合,我希望从这个对象集合中生成一个哈希值(使用 SHA256)。
散列这些对象的过程是零知识证明系统的一部分,证明者生成证明,稍后由验证者验证。这个证明实际上是一个哈希函数的输出。
这些对象都包含 3 或 4 个大的 BigInteger 值(大约 2048 位)。对象的数量是可变的,但它会在 4 到 10 之间。
我编写了以下方法来从可变数量的对象生成哈希值:
public byte[] buildHashFromHashcodes(final Object... listOfObjects) {
for (Object obj : listOfObjects) {
if (obj == null) {
throw new Exception(
"Input objects cannot be null");
}
_md.update(intToBytes(obj.hashCode()));
}
return _md.digest();
}
private byte[] intToBytes(final int intValue) {
return new byte[] {(byte) (intValue >> 24),
(byte) (intValue >> 16), (byte) (intValue >> 8),
(byte) intValue };
}
我的问题与此代码中 hashCode 方法的使用有关。具体来说,我试图确定使用 hashCode 方法是否会削弱系统的安全性,因为它只生成一个 32 位的数字,因此在每次迭代期间,哈希仅更新 32 位的信息。所以我不确定在这个过程中信息的丢失是否真的削弱了系统。
这些对象的 hashCode 方法的实现使用大的 BigInteger 值来生成它们的哈希码,但是该数字在返回之前会被截断为 int。
我的部分担忧源于这样一个事实,即某些对象的哈希码之间相对可能会发生冲突。但是话又说回来,哈希在循环内会更新几次,因此单个冲突不会是一个大问题。
让我们假设对象集合中有 4 个对象。在循环的第一次迭代中,将使用 32 位来更新哈希,在第二次迭代中,将使用另外 32 位来更新它,等等。
据我了解,哈希算法是在调用更新方法之后执行的。不是将 128 位(4 个对象)存储在缓冲区中,然后使用这 128 位作为输入执行散列算法。
因此,我们是否可以说在最终更新后哈希将处于的状态总数为 (2^32) * (2^32) * (2^32) * (2^32)?(在实践中这当然不会发生,因为它会在某些时候被截断)。
我相信使用 hashCode 是一种安全的方法,因为在每次迭代期间都会调用 update 方法。
为了避免对象之间发生冲突的风险,另一种方法是使用每个对象的 toString() 方法,该方法返回一个包含每个对象的全部熵的字符串(大的 BigInteger 数字的值包含在字符串)。这意味着在循环的每次迭代期间,哈希都会更新更多信息,但我不确定这是否有必要。
那么,我的问题是,在这段代码中使用 hashCode 方法会削弱系统的强度吗?