【问题标题】:Generate Unique hash from Long id从 Long id 生成唯一哈希
【发布时间】:2013-07-29 01:23:38
【问题描述】:

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

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

0-9
a-z and A-Z

只有 6 个字符,例如:j4qwO7

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

【问题讨论】:

  • 如果它是唯一的,那么它就不是正常意义上的哈希。
  • 您真的需要绝对零概率来获得不同值的相同哈希值,还是一个非常低的概率就足够了?
  • long 值是哈希值。 long 值的每个数字都在 (0-9) 范围内。这是您要求的一个子集;太成功了!
  • @DwB:是的,但最终会超过 6 个字符。

标签: java algorithm hash


【解决方案1】:

无法满足您的要求。您有一个由 62 个可能字符组成的字母表,并且有 6 个可用字符 - 这意味着该形式有 626 个可能的 ID。

但是,有 2568 个可能的 long 值。通过pigeon-hole principle,不可能为每个long 值赋予给定表单的不同ID。

【讨论】:

  • @xybrek:我看不出这如何使我的论点无效。正如我在回答中所证明的那样,该代码无法满足您的要求。
  • @JonSkeet 当然可以,但是如果您稍微放宽要求并说可以接受 8 个字符的字符串,那么 Hashids 就是要走的路。
【解决方案2】:

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

编辑:

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

如果您的 ID 从零开始自动递增,只是 62^6 = 56800235584 值可能对您来说绰绰有余,具体取决于您的需要。

【讨论】:

    【解决方案3】:

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

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

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

    【讨论】:

      【解决方案4】:

      你的问题没有意义。

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

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

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

      【讨论】:

        【解决方案5】:
        1. 您可以自己使用长值作为哈希(用于索引/搜索目的)。

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

        【讨论】:

          【解决方案6】:

          更新

          无需使用哈希值。 Base 36 就够了。

          long id = 12345;
          String hash = Integer.toString(Math.abs((int)id), 36);
          

          原始答案,带有哈希值:

          您可能想使用Hashids

          long id = 12345;
          Hashids hashids = new Hashids("this is my salt");
          String hash = hashids.encrypt(id); // "ryBo"
          

          "ryBo" 将是独一无二的,因为它可以转换回您的 long。 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));
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-08-09
            • 2017-04-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多