我需要从 type 的 ID 值生成唯一哈希Long
。我担心的是它不应该从两个不同的Long/long
值全局生成相同的哈希。
MD5 散列看起来是一个不错的解决方案,但散列字符串很长。我只需要人物
0-9
a-z and A-Z
只有 6 个字符,例如:j4qwO7
什么可能是最简单的解决方案?
无法满足您的要求。您有一个包含 62 个可能字符的字母表,以及 6 个可用字符 - 这意味着该形式有 62 6 个可能的 ID。
但是,有 256 8个可能的long
值。根据鸽洞原理,不可能为每个long
值赋予给定形式的不同 ID。
您不必使用十六进制表示。使用函数中的实际哈希字节构建您自己的哈希表示。您可以截断散列输出以简化散列表示,但这会使冲突更有可能发生。
编辑:
如果您确实需要整个范围long
,那么根据可能值的数量,说明您所要求的内容是不可能的其他答案在理论上是正确的。
如果您的 ID 从零开始自动递增,则根据您的需要,仅 62^6 = 56800235584
值对您来说可能就足够了。
第 1 步。切换到使用整数而不是长整数,或允许更长的“哈希”。请参阅所有其他答案以讨论为什么 6 个字符不足以处理长整数。
步骤 2. 使用不使用填充的算法加密您的号码。就个人而言,我建议使用 skip32 编码。我不保证这对于安全性来说足够强大,但如果你的目标是“制作看起来随机的 ID”,它会很好用。
步骤 3. 将您的号码编码为 base_62 号码(与 base_10 相对,而不是 base64 编码)。
你的问题没有意义。
“唯一哈希”在术语上是矛盾的。
Java 的“唯一散列”值long
必须是 64 位长度,就像它long
本身一样,当然最简单的散列函数f(x) = x,
就是long
值本身。
可以是 0-9、AZ 和 az 的 6 个字符只能产生62^6 = 56800235584
不同的值,这还不够。
更新:
无需使用哈希值。基数 36 就足够了。
long id = 12345;
String hash = Integer.toString(Math.abs((int)id), 36);
原始答案,带有哈希值:
您可能想使用哈希值
long id = 12345;
Hashids hashids = new Hashids("this is my salt");
String hash = hashids.encrypt(id); // "ryBo"
"ryBo"
将是独一无二的,因为它可以转换回你的长。Hashids
只是转换,不会进一步散列。
long[] numbers = hashids.decrypt("ryBo");
// numbers[0] == 12345
如果你真的有一个 64 位的值,哈希字符串会很长(大约 16 个字符,取决于字母表),但如果你不打算拥有超过 2^16 个东西,你可以离开将 64 位散列截断为 32 位(一个 int)。
long id = 12345;
String hash = hashids.encrypt(Math.abs((int)id));
您可以使用与哈希相同的长值本身(用于索引/搜索目的)。
如果您需要混淆/隐藏您的长值,您可以使用任何具有 64 位块的对称加密算法,例如 - ECB 模式下的 DES 或 AES。