0

设想:

我正在编写 Web 服务,它将充当 3pty 应用程序的身份提供者。我必须向这个 3pty 应用程序发送我们用户的一些唯一标识符。在我们的数据库中,唯一的用户标识符是整数(4 字节,32 位)。根据我们的安全规则,我不能以纯格式发送它们——所以我的第一个想法是发送散列(通过 MD5 或 SHA1 等槽函数)。

问题:

MD5 的结果是 16 个字节,SHA1 的结果是 40 个字节,我知道它们对于较大的输入集不能是唯一的,但考虑到我的输入集只有 4 个字节长(比散列结果小) - 他们保证是独一无二的,还是我注定要使用一些穷人的哈希函数(比如用一些数字对整数输入进行异或运算,移位咬合,添加预定义咬合等)?

4

2 回答 2

1

对于您要实现的目标(防止第 3 方确定您的用户标识符),直接 MD5 或 SHA1 哈希是不够的。32 位 = 大约 40 亿个值,第 3 方暴力破解每个值(@1m 哈希/秒)只需不到 2 小时。我真的建议改用HMAC-SHA1

至于碰撞,这个问题对它们的可能性有一个非常好的答案。tl;dr 对于 32 位输入,冲突非常小。

如果您的用户标识符不是随机的(它们以 1 递增或存在用于创建它们的已知算法),那么您没有理由不能生成每个散列以确保不会发生冲突。

这将检查前 10,000,000 个整数是否与 HMAC-SHA1 发生冲突(运行大约需要 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;
}
于 2013-07-27T15:38:53.613 回答
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.

另外,看看碰撞柱部分

于 2013-07-26T09:46:22.517 回答