Hash MD5摘要与hexdigest碰撞风险

Hash MD5摘要与hexdigest碰撞风险,hash,md5,digest,Hash,Md5,Digest,我通过散列一个包含所有这些信息的字符串,并比较散列对象的摘要,来比较个人信息,特别是他们的姓名、生日、性别和种族。这将生成一个32位的十六进制数,我将其用作数据库中的主键。例如,使用我的标识字符串的工作方式如下: >> import hashlib >> id_string = "BrianPeterson08041993MW" >> byte_string = id_string.encode('utf-8') >> hash_id = hash

我通过散列一个包含所有这些信息的字符串,并比较散列对象的摘要,来比较个人信息,特别是他们的姓名、生日、性别和种族。这将生成一个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时,冲突的风险不是增加了吗?还是我错了?

一个缩写的32位十六进制摘要(8个十六进制字符)不够长,无法有效地保证用户数据库的无冲突性

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

使用32位密钥意味着您的软件将在大约10000个用户时开始崩溃。在那之后,情况很快变得更糟。在100000个用户的情况下,碰撞概率为69%

64位密钥和100亿用户是另一个约2.7%冲突率的断点

对于1000亿用户(在可预见的未来,这是地球人口的一个慷慨上限),96位密钥在我看来有点冒险:真的,你需要一个128位的密钥,它给你

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

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

现在,我相信hexdigest是对摘要的压缩(也就是说,它存储在更少的字符中),所以在比较hexdigest时,冲突的风险不是增加了吗?还是我偏离了基地

[……]

我想我的问题是:不同的表示方式是否有不同的机会成为非唯一的,这取决于它们使用多少信息单位来进行表示,而原始消息需要多少信息单位来编码?如果是的话,最好的表达方式是什么?嗯,让我为你的下一个答案做个开场白:像我10岁一样跟我说话

老问题,但是的,可以说你有点不对劲

重要的是随机位数,而不是演示文稿的长度

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

"340106575100070649932820283680426757569" (base 10)
"ffde24cb47ecbff8d6e461a67c930dc1" (base 16, hexadecimal)
"7vroicmhvcnvsddp31kpu963e1" (base 32)
Shorter是更好、更方便的(在auth令牌等中),但每个表示都有完全相同的信息和冲突机会。较短的表示形式较短,其原因与“55”比“110111”短的原因相同,但仍然编码相同的内容

可能还会澄清一些事情,以及玩弄以下代码:

new BigInteger("340106575100070649932820283680426757569").toString(2)
…或其他语言中的等效语言(上面的Java/Scala)

在更实际的层面上,

[…]我将其用作数据库中的主键


我不明白为什么不使用普通的自动递增id列(MySQL中的
BIGINT AUTO_INCREMENT
,PostgreSQL中的
BIGSERIAL
)来消除任何冲突机会。

32个字符·4位/字符=128位AH。所以hexdigest是表示散列的正确方法,并且不会增加非唯一性的风险?只返回二进制的十六进制表示形式。对。我想我的问题是:不同的表示方式是否有不同的机会成为非唯一的,这取决于它们使用多少信息单位来进行表示,而原始消息需要多少信息单位来编码?如果是的话,最好的表达方式是什么?嗯,让我为你的下一个答案做个开场白:像我10岁一样跟我说话。我只想知道:散列的大小与字符串的大小几乎相同。。。为什么要计算它,而不是用它作为密钥?这是一个很好的答案-谢谢!关于为什么不使用普通的自动递增ID的问题,如果使用哈希,只需知道底层数据即可在数据库中找到相关记录。但是,如果使用自动递增键(我确实出于某些目的使用了该键),则需要该键来查找记录(即,除非您已经知道该键,否则无法直接访问该记录)。当您希望快速搜索长字段组合而不必枚举查询中的每个字段时,哈希还提供了速度优势。