3

我需要从 type 的 ID 值生成唯一哈希Long。我担心的是它不应该从两个不同的Long/long值全局生成相同的哈希。

MD5 散列看起来是一个不错的解决方案,但散列字符串很长。我只需要人物

0-9
a-z and A-Z

只有 6 个字符,例如:j4qwO7

什么可能是最简单的解决方案?

4

6 回答 6

13

无法满足您的要求。您有一个包含 62 个可能字符的字母表,以及 6 个可用字符 - 这意味着该形式有 62 6 个可能的 ID。

但是,有 256 8个可能的long值。根据鸽洞原理,不可能为每个long值赋予给定形式的不同 ID。

于 2013-07-29T09:57:27.827 回答
1

您不必使用十六进制表示。使用函数中的实际哈希字节构建您自己的哈希表示。您可以截断散列输出以简化散列表示,但这会使冲突更有可能发生。

编辑:

如果您确实需要整个范围long,那么根据可能值的数量,说明您所要求的内容是不可能的其他答案在理论上是正确的。

如果您的 ID 从零开始自动递增,则根据您的需要, 62^6 = 56800235584值对您来说可能就足够了。

于 2013-07-29T09:55:14.280 回答
0

第 1 步。切换到使用整数而不是长整数,或允许更长的“哈希”。请参阅所有其他答案以讨论为什么 6 个字符不足以处理长整数。

步骤 2. 使用不使用填充的算法加密您的号码。就个人而言,我建议使用 skip32 编码。我不保证这对于安全性来说足够强大,但如果你的目标是“制作看起来随机的 ID”,它会很好用。

步骤 3. 将您的号码编码为 base_62 号码(与 base_10 相对,而不是 base64 编码)。

于 2013-07-29T19:31:55.300 回答
0

你的问题没有意义。

  1. “唯一哈希”在术语上是矛盾的。

  2. Java 的“唯一散列”值long必须是 64 位长度,就像它long本身一样,当然最简单的散列函数f(x) = x,就是long值本身。

  3. 可以是 0-9、AZ 和 az 的 6 个字符只能产生62^6 = 56800235584不同的值,这还不够。

于 2013-07-29T10:07:31.207 回答
0

更新

无需使用哈希值。基数 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));
于 2014-03-17T19:43:50.610 回答
0
  1. 您可以使用与哈希相同的长值本身(用于索引/搜索目的)。

  2. 如果您需要混淆/隐藏您的长值,您可以使用任何具有 64 位块的对称加密算法,例如 - ECB 模式下的 DES 或 AES。

于 2013-08-03T01:15:52.140 回答