使用我的webapp,我在各个子目录中存储带有哈希生成文件名的缓存文件,以优化性能级别。我知道我可以提高性能的另一种方法是确保生成的名称遵循8.3文件名结构,因此NTFS不必生成短文件名(我将无法在注册表中设置它)。
为了做到这一点,虽然我不得不将哈希(我认为SHA1)修剪为8个字符,显然这会大大增加碰撞的概率。我想知道的是碰撞的概率是多少?
我已经看到了关于完整SHA1哈希冲突率的答案here,但我的数学很糟糕,因此计算该值远远超出了我。
答案 0 :(得分:5)
由于SHA-1
的输出均匀分布,您可以使用生日悖论来估算碰撞率:
假设您保留n
输出的SHA-1
位,在包含2^(n/2)
条记录的集合中有大约50%的机会发生碰撞,或者换句话说,碰撞率约为1/2^(n/2)
如果您需要更准确的答案,您可以随时在问题中引用的答案中使用公式。
所以在这里,如果我们假设每个字符都是1个字节(8位),那么如果你有〜2^(8*8/2) = 4294967296
个记录,你很可能会遇到冲突(因此碰撞率将是{{1}这是非常小)。
考虑到您使用测试程序发现的冲突率,2.32 * 10^-8
函数返回一个十六进制字符串,这意味着它的8个字符的子字符串仅代表4个字节,因此基于上述的近似冲突率公式为ToSHA1Fingerprint()
或1/2^(4*8/2) = 0.000015258789
。
答案 1 :(得分:0)
看起来碰撞率对我的需求来说太高了,我使用以下代码进行了~0.004%的测试。
const int Iterations = 10;
const int Maxitems = 360000;
for (int i = 0; i < Iterations; i++)
{
List<string> paths = new List<string>();
for (int j = 0; j < Maxitems; j++)
{
string path = Path.GetRandomFileName().ToSHA1Fingerprint()
.Substring(0, 8);
paths.Add(path);
}
int count = paths.Distinct().Count();
double collisionRate = ((Maxitems - count) * 100D) / Maxitems;
collisions.Add(collisionRate);
}
double averageCollisionRate = collisions.Average();