【问题标题】:How to shorten a 64-bit hash value down to a 48-bit value?如何将 64 位哈希值缩短为 48 位值?
【发布时间】:2015-12-31 00:02:47
【问题描述】:

我在库中已经有一个 64 位哈希函数(C 编码),但我只需要 48 位。我需要将 64 位哈希值缩减为 48 位值,但它必须以安全的方式进行,以尽量减少冲突。

散列函数是一个非常好的64位散列函数。它已经用 SMHasher(“DieHarder”哈希测试)进行了测试,证明比 Murmur2 更好。根据我的同事的说法,在 lib 中实现的 64 位散列算法是 xxHash,用 SMHasher 测试并获得了 10 的 Q.Score!想看的人可以在 github.com 上找到 xxHash 的源代码:github.com/Cyan4973/xxHash/releases/latest

基本思想是让 64 位散列值中的所有位(或其中一部分)对生成的 48 位散列值产生影响。有没有办法做到这一点?

[后期编辑]:
所以我实现了自己的 48 位(准)-UUID 生成器。
请在此处查看完整的工作解决方案(包括源代码):https://stackoverflow.com/a/47895889/4731718

【问题讨论】:

  • 如果它真的是一个 64位散列函数,那么它本质上是随机位,所以你可以随意抓取其中的48个。
  • 2^64 64 位哈希。您不能将它们放入 2^48 48 位散列中,至少有 2^16 堆积在同一个位置。
  • 我认为您收到的回复没有帮助(和反对票),因为您不太清楚自己在寻找什么。 “'保留'所有 64 位的信息”意味着您希望能够撤消 64->48 转换,这意味着没有冲突。 “最小化碰撞”意味​​着您愿意接受一些碰撞(但不是很多)。您对 Lee Daniel Coker 的评论(不是答案)的支持意味着您对任何可以最大限度地减少冲突的解决方案感到满意,无论有多少冲突。这是三种不同的可能性。
  • 他可能正在尝试构建自己的 UUID 版本 1 生成器的实现。这是我在计算机世界中所知道的 48 位哈希的唯一用途。 RFC 4122 确实允许将版本 1(或 2)UUID 中的 MAC 地址替换为随机的 48 位节点 ID,因为该节点没有 MAC 地址,或者因为不希望公开它。出于安全考虑,他可能不想透露他正在用哈希算法替换 UUID MAC 地址部分(48 位)。
  • @Teepeemm:因此,这个问题并不像看起来那么奇怪。全球许多程序员在尝试根据 RFC 4122 实现这个 UUID v1 48 位问题时都会遇到这个问题。我会投票赞成这个问题。

标签: c algorithm math hash uuid


【解决方案1】:

如果 64 位散列是好的,那么选择任何 48 位也是一个好的散列。 @Lee Daniel。当然,信息会丢失且不可逆。

unsigned long long Mask48 = 0xFFFFFFFFFFFFu;
unsigned long long hash48 = hash64 & Mask48;

如果 64 位散列函数较弱,则用 pow(2,48) 正下方的最大素数取模。一些桶会丢失。这不会损害良好的散列,但肯定会使弱散列更好。

unsigned long long LargestPrime48 = 281474976710597u;  // FFFFFFFFFFC5
unsigned long long hash48 = hash64 % LargestPrime48;

【讨论】:

  • 终于有一位精通数学的人了... :)
【解决方案2】:
hash >>= 16;

但如果您觉得随意保留其他 16 位更好,只需使用 XOR。

hash = (hash >> 16) ^ (hash & 0xFFFF);

【讨论】:

  • 谢谢,我正在考虑类似/相同的东西......但仍然需要看看也许有人会提出一些绝妙的想法。数学能力强的人可能:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-28
  • 2011-11-02
相关资源
最近更新 更多