指定长度的字符串的哈希

Hash of a string to be of specific length

本文关键字:字符串 哈希      更新时间:2023-10-16

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

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

编辑:感谢大家的快速和知识渊博的回复。我选择了MD5散列,它非常适合我的目的。唯一性是一个重要的问题,但我不认为这些哈希的数量在任何给定的时间都会很大——这些哈希代表家庭局域网上的软件服务器,所以最多会有5个,也许10个在运行。

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

是什么让你觉得自己现在很独特?是的,当你只使用33个字节而不是41个字节时,显然发生冲突的几率更高,但你需要充分意识到,对于任何首先使用哈希有意义的情况,冲突都是不可能的。如果你对超过41字节的数据进行散列,那么可能的组合显然比可用的散列更多。

现在,我不知道是截断SHA-1哈希还是使用MD5之类的较短哈希更好。我想我在保存整个哈希时会更有信心,但MD5有已知的漏洞,这些漏洞可能对您的特定应用程序有问题,也可能不是问题。

不幸的是,哈希的计算方式是不可能的。为了将哈希长度限制在33个字节,你必须将其剪切。你可以对第一个和最后33个字节进行异或,因为这可能会保留更多的信息。但是,即使有33个字节,发生冲突的可能性也不大。

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

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

由于哈希算法的设计方式(熵在生成的字符串中均匀分布),与子字符串(sha_hash,0,33)碰撞的可能性不比与任何其他33字节长的哈希碰撞的可能性大。

您可以使用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

Hashes根据定义仅对少量数据是唯一的(即使这样也不能保证)。不可能将大量信息唯一地映射到少量信息,因为你不能从语法上去除信息,然后再把它拿回来。请记住,这不是压缩正在进行。

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

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

我相信MD5哈希算法会产生一个32位数的数字,所以这个数字可能更合适。

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

这里是C.中的MD5实现

33字节冲突的几率是1/2^132(根据生日悖论)

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

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

使用Apache的DigestUtils:

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

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