6字符短哈希算法

本文关键字:算法 哈希 字符 | 更新日期: 2023-09-27 18:29:13

我的目标是为长度为42个不区分大小写的字母数字字符的字符串生成一个6个字符的短哈希字符串(可能包含字符[a-Z][a-Z][0-9])。唯一性是关键要求。安全性或性能并不那么重要。

有没有一个特定的算法会给出这个结果,或者我应该坚持截断MD5哈希或SHA-1哈希(就像这个问题中一样)?如果是,发生碰撞的概率是多少?

6字符短哈希算法

您最好的选择是截断众所周知的哈希函数(MD5或SHA家族),因为这些算法在统计上具有良好的哈希值均匀分布(还使用完整哈希,而不仅仅是6个字符)。

现在碰撞概率的一些计算

-英语字母表中的字母数:26-加大写:26-添加数字:10--------------总共得到26+26+10=62个字符。现在你有6个位置,这给了你62^6个可能的组合。这是56.800.235.584~570亿个组合。这是一个可能的散列值-N的空间。--------------要计算碰撞,让我们使用以下公式P碰撞=K^2/2N这是碰撞概率的一个非常粗略的近似值

现在让我们看看一个表中许多项目的结果表-K

#items |碰撞概率---------------------------------------10|1.7*10^-9100 | 1.7*10^-71K |1.7*10^-510K |1.7*10^-3100K|0.17

这个公式只能用于较小的K,但它表明,如果哈希表中有100K个条目,则大约有17%的机会发生冲突。

链接

碰撞概率

简单散列:)

private string Hash(string str)
{
    var allowedSymbols = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".ToCharArray();
    var hash = new char[6];
    for (int i = 0; i < str.Length; i++)
    {
        hash[i % 6] = (char)(hash[i % 6] ^ str[i]);
    }
    for (int i = 0; i < 6; i++)
    {
        hash[i] = allowedSymbols[hash[i] % allowedSymbols.Length];
    }
    return new string(hash);
}

最好的解决方案几乎肯定是使用SHA1,转换到Base62(尽管Base64会更容易,因为它内置在框架convert.ToBase64String中。你必须寻找一个像样的Base62库),然后将输出截断为6字节。

我不会使用GetHashCode(),因为它有冲突问题的历史。(我并不是想说这个特定的错误会适用于你,只是把它作为GetHashCode在过去没有得到很好实现的证据。)

我也不会实现自定义哈希算法,意外地编写一个冲突率很高的算法是非常容易的。对SHA1和其他主要的哈希算法进行了大量的研究和审查,你很难想出更好的算法。