确定数据是否发生变化的最佳方法是什么?

时间:2014-07-15 11:17:05

标签: php string md5 checksum

如果我有一个动态生成的CSS文件,我应该使用哪个函数为整个文件内容生成一个简短的标识字符串?

md5还是crc32?其他

1 个答案:

答案 0 :(得分:1)

对你的问题的简短回答就是:md5就足够了。

答案越长越好:

取决于......我们谈论的文件数量。使用md5生成的唯一哈希值的理论最大值为2 ^ 64,但您必须考虑生日问题 但是,如果有几百万个文件哈希值,则哈希冲突的可能性会增加超过一个简单的1/2 ^ 64th(2 -128 )。

如果您正在处理“浩大”数量的文件,我会选择更安全的哈希算法。我会说使用sha1是有道理的。特别是考虑到现代计算机上增加的开销/成本可以忽略不计 如果我们谈论十几个文件,那么md5就足够了。但是,使用sha1并不是愚蠢的。这是一个相当快速,非常可靠的哈希。虽然理论上它不再被视为安全,但在AFAIK野外并没有观察到碰撞。
Wikipedia支持这一点,并说:

  

Marc Stevens的2011年攻击可能会产生复杂的2 61 操作的哈希碰撞。尚未产生实际碰撞。

无论哪种方式,2 61 应该绰绰有余。

哦,如果你想知道:The birthday problem在这里解释

应用于您的用例
由于您正在散列文件,因此使用像md5_file这样的php函数看起来很诱人。但是,可能因为md5被证明是不安全的,PHP带有a sha1_file函数 首先,使用crc32似乎是一个有效的选项,因为它是为了生成哈希来检查文件完整性而开发的。但它真的很老了,因为散列本身只有32位,所以碰巧的风险大于md5或sha1的风险。

比较

|-------+-------+-------+--------+
| Comp. | CRC32 |  MD5  |  SHA1  |
+-------+-------+-------+--------+
| Bits  |  32   |  128  |  160   |
+-------+-------+-------+--------+
| c.rest|  2^16 |  2^18 |  2^61  | (sha1 in theory)
+-------+-------+-------+--------+
| crypt |  No   |  No   |  No    |
+-------+-------+-------+--------+
| cost  |   1   |   2   |  3.1   | (crc32 used as base)
+-------+-------+-------+--------+
 * c.rest: collision resistance
 * crypt: Cryptographically secure

关于成本价值的说明:
我运行了一些PHP脚本来比较计算哈希值所需的时间。一百万个随机字符串的哈希值约。 15个字符长度超过0.25微秒。 md5哈希计算时间超过半秒(结果范围从0.43到0.56,收敛于0.55)。 sha1哈希值在0.78微秒内生成(结果范围为0.76至0.8001)。所花费的时间是指生成所有 1,000,000个哈希值所花费的时间。

更多:

CRC32碰撞的公式here
md5 collision resistance quoted on the wiki

这是一个随机字符串生成器,允许您测试“常见”哈希冲突的方式:

<?php
class RSGen
{
    private $pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    private $max = 61;
    private $hashed = array();

    public function randomUniqueString($len = 15)
    {
        $str = '';
        for ($i=0;$i<$len;++$i)
        {
            $str .= substr($this->pool, mt_rand(0, $this->max),1);
        }
        $hash = crc32($str);
        if (isset($this->hashed[$hash]))
        {
            for ($i=0,$j=count($this->hashed[$hash]);$i<$j;++$i)
            {
                if ($this->hashed[$hash][$i] === $str)
                {
                    return $this->randomUniqueString($len);
                }
            }
            echo 'Collision: ', $hash, PHP_EOL, $str, PHP_EOL, implode(', ', $this->hashed[$hash]), PHP_EOL;
            return false;
        }
        else
            $this->hashed[$hash] = array();
        $this->hashed[$hash][] = $str;
        return $str;
    }
}
$gen = new RSGen();
for($i=0;$i<1000000;++$i)
{
    $str = $gen->randomUniqueString();
    if ($str === false)
    {
        echo PHP_EOL,'Collision after ', $i, ' tries', PHP_EOL;
        break;
    }
}

在vim中打开它,并用您选择的哈希替换所有哈希函数调用。使用crc32,几乎总能找到碰撞 测试md5

:%s/crc32/md5/g

sha1相同:

:%s/crc32/sha1/g