我想自动生成 Java 的 serialVersionUID(很长,或 64 位)。要序列化的对象的区别是由大约 20 个整数决定的,但并不总是 20 个整数。我打算将整数转换为逗号分隔的数字字符串,并通过 SHA-256 哈希函数运行它。
由于 SHA-256 的长度为 32 字节(256 位),并且我需要它来适应 serialVersionUID(64 位),我如何将其转换为 64 位值并最大限度地减少良好哈希特性的损失?
我想自动生成 Java 的 serialVersionUID(很长,或 64 位)。要序列化的对象的区别是由大约 20 个整数决定的,但并不总是 20 个整数。我打算将整数转换为逗号分隔的数字字符串,并通过 SHA-256 哈希函数运行它。
由于 SHA-256 的长度为 32 字节(256 位),并且我需要它来适应 serialVersionUID(64 位),我如何将其转换为 64 位值并最大限度地减少良好哈希特性的损失?
只需切断多余的部分。没有必要使事情复杂化。如果有一种更好的方法来获取第一个(或任何其他)64 位,那么哈希首先会被破坏。
首先,你不可能在正常意义上压缩一个好的散列。压缩是关于减少冗余的可逆编码。在一个好的散列中不应该有冗余来减少,因此压缩将是无效的。
由于 SHA-256 的长度为 32 字节(256 位),并且我需要它来适应 serialVersionUID(64 位),我如何将其转换为 64 位值并最大限度地减少良好哈希特性的损失?
那么这些好的特性是什么?好的散列的主要特征是反转它是不切实际的。即,计算出导致散列的可能输入是不切实际的。一个相关的特征是,给定一个产生给定哈希的已知输入,产生另一个给出相同哈希的输入(即冲突)是不切实际的。
现在,当您从 256 位散列到 64 位散列时,您可以更轻松地反转散列或产生散列冲突……通过蛮力。基本上,64 位散列意味着2^64
任何随机输入都有一个给定散列的机会。这个概率足够大,以至于一些拥有足够核心的“坏人”有足够大的成功机会(在合理的时间内)使蛮力成为一个合理的选择。
但这真的重要吗?有人会通过创建一个冲突的 serialVersion 字符串来实现什么?这些字符串不是秘密,它们不会告诉你任何关于对象 API 的明确信息......
底线是,如果这些简化的散列被用作 serialVersion 字符串被设计使用,那么(例如)仅使用 SHA-256 散列的前 64 位不会有任何问题。不需要 XOR 或校验和或进行任何其他更复杂的转换。
您可以计算 SHA-256 摘要的循环冗余校验 (CRC)。
我会说要么使用 64 位校验和,或者如果你想坚持使用 SHA,那么对 64 位块进行异或。
用ripemd-160 对其进行哈希处理。
例如,
4727c1278432c388eea822904f008468c02fd543fc347391d1f2b9918ec9b5b9
变成
069e298ee9d1b14e7774434624703c0be1a47ee1
即 66 个字符,减少到 40 个。