如果我有一个动态生成的CSS文件,我应该使用哪个函数为整个文件内容生成一个简短的标识字符串?
md5还是crc32?其他
答案 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