【问题标题】:Adler32 Repeating Very QuicklyAdler32 快速重复
【发布时间】:2012-07-20 19:36:34
【问题描述】:

我正在使用 adler32 校验和算法从数据库 id 生成一个数字。因此,当我在数据库中插入一行时,我会获取该行的标识并使用它来创建校验和。我遇到的问题是我只在数据库中插入了 207 次后才生成了一个重复校验和。这比我预期的要快得多。这是我的代码:

String dbIdStr = Long.toString(dbId);
byte[] bytes = dbIdStr.getBytes();
Checksum checksum = new Adler32();
checksum.update(bytes, 0, bytes.length);
result = checksum.getValue();

我在做什么/如何做有什么问题吗?我应该使用不同的方法来创建唯一的字符串吗?我这样做是因为我不想在 url 中使用 db id...对 db 结构的更改将破坏世界上所有的链接。

谢谢!

【问题讨论】:

  • 到目前为止,您的代码看起来是正确的。也许您的“结果”是“字节”而不是“长”?或者“dbId”并不像你想象的那么独特......实际上,我根本不明白你的问题。您需要一个唯一的 ID 来标识数据库。而且您的每个数据库已经具有一个名为“dbId”的唯一标识符,但您不想使用它,因为“???”。因此,您取而代之的是,您使用 非常相同的 dbId,并将其转换为字符串,并使用 Adler32 对其进行哈希处理,然后使用 that 作为您的“唯一”ID。但是该哈希仍然基于您不想使用的 dbId!
  • 假设我给你一个指向我系统中帖子的链接:example.com/posts/1。然后假设我需要重新组织数据库中的内容(或者可能完全转移到不同类型的存储),这会导致数据库 ID 发生变化。现在你有一个断开的链接。这就是我生成这些哈希的原因。另外,我刚刚检查了一些在线哈希工具,似乎在我的系统上发生冲突的两个 id(126 和 207)确实为这些工具产生了相同的 adler32 结果。例如:fileformat.info/tool/hash.htm
  • 只是为了增加我的推理,似乎许多流行的网站都在做同样的事情。例如:pinterest.com/pin/186758715768172705。我怀疑他们的网站上有超过 186 万亿个帖子!
  • 如果 dbId 发生变化,那么其哈希(或校验和)也将发生变化。散列 dbId 不会给您带来任何好处。
  • 如果您重新编号,您可以只存储旧 ID。

标签: java encryption cryptography checksum adler32


【解决方案1】:

您应该将 Adler-32 用作哈希码生成器。那不是它的用途。您应该使用具有良好哈希属性的算法,除其他外,该算法可以最大限度地减少冲突的可能性。

您可以简单地使用 Java 的 hashCode 方法(在任何对象上)。对于 String 对象,哈希码是字符串的字节值乘以 31 的连续幂的总和。很短的字符串可能会发生冲突,但这不是一个可怕的算法。作为哈希算法,它肯定比 Adler-32 好很多。

就执行时间和哈希码大小而言,使用加密安全哈希函数(如 SHA-256)的建议对于您的应用程序来说肯定是多余的。你应该试试 Java 的 hashCode 看看你得到了多少冲突。如果 2-n 概率似乎比您预期的要频繁得多(其中 n 是哈希码中的位数),然后你可以用更好的覆盖它。你可以找到一个链接here for decent Java hash functions

【讨论】:

  • 感谢您的提示,但我使用的是 Java,而 CityHash 是 C++。
  • @Miles:这不仅仅是一个提示,他似乎是发明校验和的阿德勒。
  • CRC 也没有作为散列算法进行优化。它有一些不错的特性,但也有更好的选择。
  • 一个 64 位数字可以用 10 个以 85 为基数的字符来表示。
  • 我认为你的意思是“可以变成负数”(不是“空”)。当然,你可以取绝对值,你基本上只是损失了一点。这将使个别碰撞的机会增加一倍。由于无论如何您都必须将整数编码为文本,所以我只保留负值并将符号位折叠到您的编码中。
【解决方案2】:

尝试使用 SHA-256 等安全哈希函数。如果您发现任何二进制不相等的数据发生冲突,您将在您的银行帐户中获得 1000 美元,并附上赞美。如果/当 SHA-2 被破解并且您故意进入冲突,则优惠结束。也就是说,输出是 32 字节而不是 32 位。

【讨论】:

  • 不幸的是,SHA-256 生成的字符串对于 url 来说太长了(就用户友好性而言)。我需要一些更短的东西,最好是所有数字。
  • 好的,但是对于 32 位和大型数据库,由于生日悖论,您可能会遇到大约 2^16 个元素(平均)的冲突,那是您使用完美哈希的时候算法。那是大约 64Ki ID。当然,如果你不走运,或者你使用了一个次优的散列(但我猜你已经遇到了最后一个),你可能会更早地遇到冲突。
猜你喜欢
  • 1970-01-01
  • 2015-02-05
  • 2016-06-16
  • 2013-05-30
  • 1970-01-01
  • 2012-07-17
  • 1970-01-01
  • 2012-08-08
  • 2016-11-14
相关资源
最近更新 更多