我需要从Long
类型的ID值生成唯一哈希。我担心的是它不应该从两个不同的Long/long
值全局生成相同的哈希值。
MD5哈希看起来很不错,但哈希字符串非常长。我只需要字符
0-9
a-z and A-Z
只有6个字符,如:j4qwO7
什么是最简单的解决方案?
答案 0 :(得分:13)
无法满足您的要求。您有一个包含62个可能字符的字母表,并且有6个字符可用 - 这意味着该表单中有62个 6 可能的ID。
但是,有256个 8 可能的long
值。通过pigeon-hole principle,不可能为每个long
值赋予给定表单的不同ID。
答案 1 :(得分:1)
您不必使用十六进制表示法。使用函数中的实际哈希字节构建自己的哈希表示。您可以截断哈希输出以简化哈希表示,但这会使冲突更有可能。
修改强>
其他答案表明,根据可能的long
值的数量,您提出的要求是不可能的,从理论上来说是正确的, 如果 您实际上需要整个范围。
如果您的ID从零开始自动递增, 62^6 = 56800235584
值可能对您来说绰绰有余,具体取决于您的需求。
答案 2 :(得分:0)
你的问题没有意义。
'Unique hash'是一个矛盾。
Java long
的'unique hash'值必须长度为64位,就像long
本身一样,当然最简单的哈希函数是{{1} }即f(x) = x,
值本身。
可以是0-9,A-Z和a-z的6个字符只能产生long
个不同的值,这是不够的。
答案 3 :(得分:0)
步骤1.切换到使用in而不是long,或允许更长的“哈希”。请参阅每个其他答案,以讨论为什么6个字符不足以处理多头。
步骤2.使用不使用填充的算法加密您的号码。就个人而言,我建议使用skip32编码。我没有承诺这对于安全性来说足够强大,但如果你的目标是“制作具有随机性的ID”,那么效果很好。
步骤3.将您的号码编码为base_62号码(与base_10相反,而不是与base64编码相对)。
答案 4 :(得分:0)
您可以使用长值iself与hash相同(用于索引/搜索)。
如果您需要混淆/隐藏长值,可以使用任何对称 64位块的加密算法,例如 - ECB模式下的DES或AES。
答案 5 :(得分:0)
更新:
无需使用Hashids。基地36足够了。
long id = 12345;
String hash = Integer.toString(Math.abs((int)id), 36);
原始答案,Hashids:
您可能想要使用Hashids
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));