情景:
我正在编写Web服务,它将像3pty应用程序的身份提供程序一样。我必须向这个3pty应用程序发送一些我们用户的唯一标识符。在我们的数据库中,唯一用户标识符是整数(4个字节,32个字符)。根据我们的安全规则,我不能以简单的形式发送 - 因此将它们发送出去(像MD5或SHA1这样的功能)是我的第一个想法。
问题:
MD5的结果是16个字节,SHA1的结果是40个字节,我知道它们对于较大的输入集不能是唯一的,但考虑到我的输入集只有4个字节长(小于散列结果) - 他们保证是独一无二的,还是我注定了一些穷人哈希函数(比如用一些数字来计算整数输入,转移咬合,添加预定义的咬合等)?
答案 0 :(得分:1)
对于您要实现的目标(阻止第三方确定您的用户标识符),直接MD5或SHA1哈希是不够的。 32位=大约40亿个值,第三方摧毁每个值(@ 1m哈希/秒)需要不到2个小时。我真的建议改用HMAC-SHA1。
至于碰撞,this question对他们的可能性有很好的答案。 tl; dr对于32位输入,碰撞过小。
如果您的用户标识符不是随机的(它们增加1或者有一个已知的算法来创建它们),那么就没有理由不能生成每个哈希以确保不会发生冲突。
这将检查与HMAC-SHA1发生冲突的前10,000,000个整数(运行大约需要2分钟):
public static bool checkCollisionHmacSha1(byte[] key){
HMACSHA1 mac = new HMACSHA1(key);
HashSet<byte[]> values = new HashSet<byte[]>();
bool collision = false;
for(int i = 0; i < 10000000 && collision == false; i++){
byte[] value = BitConverter.GetBytes(i);
collision = !values.Add(mac.ComputeHash(value));
if (collision)
break;
}
return collision;
}
答案 1 :(得分:0)
首先,SHA1是20个字节而不是40个字节。
其次,虽然输入很小,但仍可能发生碰撞。最好对此进行测试,但我不知道这样做的可行方法。
为了防止任何潜在的碰撞:
1 - Hash your input and produce the 16/20 bytes of hash
2 - Spray your actual integer onto this hash.
Like put a byte of your int every 4/5 bytes.
This will guarantee the uniqueness by using the input itself.
另外,请查看Collision Column part