MD5消化与hexdigest碰撞风险

时间:2013-08-15 20:02:58

标签: hash md5 digest

我通过散列包含所有这些信息的字符串,并比较哈希对象的hexdigest来比较个人的个人信息,特别是他们的姓名,出生日期,性别和种族。这会产生一个32位十六进制数,我将其用作数据库中的主键。例如,使用我的识别字符串将如下所示:

>> import hashlib
>> id_string = "BrianPeterson08041993MW"
>> byte_string = id_string.encode('utf-8')
>> hash_id = hashlib.md5(bytesring).hexdigest()
>> print(hash_id)
'3b807ad8a8b3a3569f098a575091bc79'

此时,我正在努力确定碰撞风险。我的理解是MD5没有明显的碰撞风险,至少对于相对较小的字符串,我的是(长度约为20-40个字符)。但是,我没有使用128位摘要对象,而是32位hexdigest。

现在,我认为hexdigest是对摘要的压缩(也就是说,它存储在更少的字符中),因此在比较hexdigests时是否存在增加冲突的风险?还是我离开基地?

2 个答案:

答案 0 :(得分:3)

  

现在,我认为hexdigest是对摘要的压缩(也就是说,它以较少的字符存储),因此在比较hexdigests时,是否存在增加冲突的风险?还是我离开基地?

     

[...]

     

我想我的问题是:根据他们用于表示的信息单元数量与原始消息编码的信息单元数量不同,不同的表示形式有不同的机会是非唯一的?如果是这样,最好的代表是什么?嗯,让我为你的下一个答案做准备:跟我说话,比如我10岁

老问题,但是,你有点偏离base,可以这么说。

重要的是随机位的数量,而不是演示的长度。

摘要只是一个数字,一个整数,可以使用不同数量的不同数字转换为字符串。例如,在某些不同的基数中显示的128位数字:

"340106575100070649932820283680426757569" (base 10)
"ffde24cb47ecbff8d6e461a67c930dc1" (base 16, hexadecimal)
"7vroicmhvcnvsddp31kpu963e1" (base 32)

更短更好更方便(在auth令牌等),但每个表示具有完全相同的信息和碰撞的机会。较短的表示形式较短的原因与为什么" 55"比" 110111"更短,但仍然编码相同的东西。

This answer也可能澄清事情,并使用以下代码进行操作:

new BigInteger("340106575100070649932820283680426757569").toString(2)

...或其他语言中的等价物(上面的Java / Scala)。

在更实际的层面上,

  

[...]我用作数据库中的主键

我不明白为什么不通过使用普通的自动增量id列(MySQL BIGINT AUTO_INCREMENT,PostgreSQL中的BIGSERIAL)来消除任何碰撞的可能性

答案 1 :(得分:2)

缩写的32位十六进制(8个十六进制字符)不足以有效保证用户的无冲突数据库。

生日碰撞概率的公式如下:

What is the probability of md5 collision if I pass in 2^32 sets of string?

使用32位密钥意味着您的软件将开始在大约10,000个用户中断。 The collision probability would be about 1%.之后很快就会变得更糟。在100,000个用户中,碰撞概率为69%。

64位密钥和100亿用户是碰撞率约2.7%的另一个突破点。

对于1000亿用户(在可预见的未来,这是地球人口的慷慨上限),96位密钥在我看来有点风险:collision chance is about one in 100 million.真的,你需要一个128 -bit键,为您提供a collision rate of about 1X10^-17.

128位密钥长度为128/4 = 32个十六进制字符。如果您想使用较短的按键,为了美观,您需要使用23个字母数字字符才能超过128位。或者,如果您使用可打印字符(ASCII 32-126),您可以使用20个字符。

因此,当您谈论用户时,您需要至少128位用于无冲突随机密钥,或20-32字符长字符串,或128/8 = 16字节二进制表示。