如何为字符串生成唯一但一致的N位哈希(小于64位)?

时间:2018-10-17 03:47:49

标签: javascript c++ qt hash checksum

我想要以下机制:

int64_t MyHash (const std::string& value);
  • 提供任何std::string(通常为100字节)作为输入
  • 该函数输出64位整数值
  • 但是,该整数表示的最大值应在-2<sup>53</sup> to 2<sup>53</sup>-1范围内

我尝试使用std::hash();问题是:在每个平台上都不同。不仅如此,每次运行都会有所不同。

当前,使用Qt的{​​{1}}得到了QCryptographicHash校验和,并且我将其截断为64位。即使在这种截断中,碰撞的可能性也会增加。
无论如何,我的目标是在54位内获得该值。一种明显的解决方案是将该数字除以2048。

问题:是否有更好的解决方案来获取54位哈希值?
Javascript解决方案也很好。

目的:该值传递给Javascript。现在,它的数据类型SHA256可以容纳64位double,即54位。

1 个答案:

答案 0 :(得分:2)

获取54位哈希值,您可能会为了速度而牺牲质量。在SHA256中,最低的54位将以合理的可能度提供尽可能可靠的散列,但代价不是最佳性能。

其他可能性是64位CRC,可以通过快速的Google搜索轻松找到。这可能会更快,但对于任何合理的用例来说仍然可以。

对于截断到[-2 53 .. 2 53 -1]范围,我只使用带有合适位掩码的&,然后减去2 53

2 53 是0x20000000000000,所以它就是:

crc = crc-0x20000000000000LL;

对于64位CRC本身,以下代码直接取自http://andrewl.dreamhosters.com/filedump/crc64.cpp,这是一个可下载的.cpp文件。原始文件是使用Windows数据类型编写的,在这里我已将其转换为普通的stdint.h类型。

unit64_t const poly = 0xC96C5795D7870F42ULL;
uint64_t table[256];

void generate_table()
{
    for(int i = 0; i < 256; ++i)
    {
        uint64_t crc = i;

        for(int j = 0; j < 8; ++j)
        {
            if(crc & 1)
            {
                crc >>= 1;
                crc ^= poly;
            }
            else
            {
                crc >>= 1;
            }
        }
        table[i] = crc;
    }
}

您将希望在程序启动时仅调用一次generate_table()。要么,要么运行在一个很小的工具中,它会打印出结果,并使用这些值直接初始化表。

要实际评估crc,请将字节序列和长度传递给它:

uint64_t calculate_crc(uint8_t *stream, size_t n)
{
    uint64_t crc = 0;

    for(size_t i = 0; i < n; ++i)
    {
        uint8_t index = stream[i] ^ crc;
        uint64_t lookup = table[index];

        crc >>= 8;
        crc ^= lookup;
    }
    return crc;
}

根据您的好奇程度,可能值得看一下链接源,其中有大量注释可以解释发生了什么情况。