【问题标题】:Hash of a string to be of specific length字符串的散列具有特定长度
【发布时间】:2010-09-15 16:42:39
【问题描述】:

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

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

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

【问题讨论】:

    标签: c++ algorithm hash


    【解决方案1】:

    您可以使用Elf hash(

    /*****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
    

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

        【解决方案3】:

        使用 Apache 的 DigestUtils:

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

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

        【讨论】:

          【解决方案4】:

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

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

          Also, yet another C implementation of MD5, by the people who designed it.

          【讨论】:

            【解决方案5】:

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

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

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

            【讨论】:

            • 与其说它有漏洞,不如说计算已经发展到现在只要有合适的工具,暴力破解就变得实用了。通过正确的预防措施,MD5 或多或少是安全的。 (阅读:添加盐)
            • 截断哈希不能保证它的唯一性,因此应该避免。
            • Andreas:你已经无法保证唯一性了。这是一个散列 - 它正在尽最大努力提出唯一性,但从根本上说,您应该始终认为散列是非唯一的。
            【解决方案6】:

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

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

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

            【讨论】:

            • 您的 BTW 才是真正的答案。如果您内存不足,请不要将哈希值存储为十六进制字符串!
            • md5 比 SHA1 和 sha256 更“坏”。你最好截断并使用额外的 12 个字节的熵。
            • 我喜欢将子字符串异或在一起的想法。至少,您将使用最初生成的其余字节“键入”子字符串。
            • 首先哈希不是字节,而是字符。其次 md5 是 32 个字符而不是 16 个字符。
            【解决方案7】:

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

            【讨论】:

            • 由于哈希的计算方式,这并不完全正确。涉及的数学很复杂,但部分碰撞比完全碰撞更容易生成。
            • 一氧化碳:是的,它们更容易与位数成正比。 16 字节的 SHA1 至少与 MD5 一样安全。否则,哈希将不安全。
            • 1/2 SHA1 现在实际上被认为更安全。 MD5 比 SHA1 更“破碎”
            • 1/2 SHA1(80 位)比 MD5(128 位)短。我怀疑它会更安全,因为它很短。 MD5(和 SHA1)的损坏取决于应用程序。不过,我同意 SHA1 通常是更好的选择。
            【解决方案8】:

            Here 是 C 中的 MD5 实现。

            【讨论】:

              【解决方案9】:

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

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

              【讨论】:

              • 是的 :) 你会知道我在哪里可以找到一些代码吗?谢谢!
              • 看起来 Staale 打败了我
              猜你喜欢
              • 2017-12-26
              • 2015-11-18
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多