6

有没有办法生成一个字符串的散列,以便散列本身具有特定的长度?我有一个生成 41 字节哈希 (SHA-1) 的函数,但我需要它最大为 33 字节(由于某些硬件限制)。如果我将 41 字节的散列截断为 33,我可能(当然!)会失去唯一性。

或者实际上,如果我能在您的帮助下找到一些 C 代码,我认为 MD5 算法会很合适。

编辑:谢谢大家的快速和知识渊博的回应。我选择使用 MD5 哈希,它非常适合我的目的。唯一性是一个重要问题,但我不希望这些哈希的数量在任何给定时间都很大 - 这些哈希代表家庭 LAN 上的软件服务器,因此最多会有 5 个,也许 10 个正在运行。

4

9 回答 9

7

如果我将 41 字节的散列截断为 33,我可能(当然!)会失去唯一性。

是什么让你认为你现在拥有独特性?是的,当你只玩 33 个字节而不是 41 个字节时,显然冲突的可能性更高,但你需要充分意识到,对于任何使用散列有意义的情况,冲突都是不可能的,而不是不可能的首先。如果您要散列超过 41 个字节的数据,那么可能的组合显然比可用的散列更多。

现在,我不知道是截断 SHA-1 散列还是使用更短的散列(如 MD5)更好。我认为在保留整个哈希时我会更有信心,但是 MD5 有已知的漏洞,这些漏洞对于您的特定应用程序可能是也可能不是问题。

于 2008-10-07T06:27:33.737 回答
5

不幸的是,计算哈希的方式是不可能的。要将哈希长度限制为 33 个字节,您必须将其剪掉。您可以对第一个和最后 33 个字节进行异或运算,因为这样可能会保留更多信息。但即使有 33 个字节,您也没有那么大的冲突机会。

md5:http ://www.md5hashing.com/c++/

顺便提一句。md5 是 16 字节,sha1 是 20 字节,sha256 是 32 字节,但是作为十六进制字符串,它们的大小都加倍。如果你可以存储字节,你甚至可以使用 sha256。

于 2008-10-07T06:17:55.020 回答
4

由于散列算法的设计方式(熵在结果字符串中均匀分布),与任何其他 33 字节长的散列相比,与 substring(sha_hash, 0, 33) 发生冲突的可能性不大。

于 2008-10-07T06:25:14.600 回答
3

您可以使用Elf 哈希(包括<- C 代码)或其他类似的简单哈希函数,而不是 MD5 或 SHA-X。它们不安全,但可以调整到您需要的任何长度

/*****Please include following header files*****/
// string
/***********************************************/

/*****Please use following namespaces*****/
// std
/*****************************************/

static unsigned int ELFHash(string str) {
    unsigned int hash = 0;
    unsigned int x = 0;
    unsigned int i = 0;
    unsigned int len = str.length();

    for (i = 0; i < len; i++)
    {
        hash = (hash << 4) + (str[i]);
        if ((x = hash & 0xF0000000) != 0)
        {
            hash ^= (x >> 24);
        }
        hash &= ~x;
    }

    return hash;
}

例子

string data = "jdfgsdhfsdfsd 6445dsfsd7fg/*/+bfjsdgf%$^";
unsigned int value = ELFHash(data);

输出

248446350
于 2008-10-07T06:20:31.397 回答
2

根据定义,散列仅对少量数据是唯一的(即使这样仍然不能保证)。不可能将大量信息唯一地映射到少量信息,因为您无法神奇地摆脱信息并在以后将其取回。请记住,这不是压缩。

就个人而言,在这种情况下,我会使用 MD5(如果您需要以文本形式存储)或 256b (32B) 哈希,例如 SHA256(如果您可以以二进制形式存储)。将另一种哈希算法截断为 33B 也可以,并且可能会增加产生哈希冲突的可能性。这很大程度上取决于算法。

此外,MD5 的另一个 C 实现,由设计它的人完成。

于 2008-10-07T06:23:20.300 回答
1

我相信 MD5 散列算法会产生一个 32 位的数字,所以也许那个更合适。

编辑:要访问 MD5 功能,应该可以挂钩到 openssl 库。但是,您提到了硬件限制,因此在您的情况下这可能是不可能的。

于 2008-10-07T06:17:15.100 回答
1

33 字节冲突的机会是 1/2^132(由生日悖论)

所以不要担心失去独特性。

更新:我没有检查 SHA1 的实际字节长度。以下是相关计算:仅当散列的字符串数量约为 sqrt(2^(32*4)) = 2^64 时,才会发生 32 个半字节的冲突(33 个字节的十六进制 - 1 个终止字符)。

于 2008-10-07T06:21:54.123 回答
1

是 C 中的 MD5 实现。

于 2008-10-07T06:21:56.620 回答
0

使用 Apache 的 DigestUtils:

http://commons.apache.org/codec/api-release/org/apache/commons/codec/digest/DigestUtils.html#md5Hex(java.lang.String)

将哈希转换为 32 个字符的十六进制字符串。

于 2008-10-07T06:36:24.750 回答