哈希函数是否保证唯一性?

3
在我们的应用中,我们将会收到一个png图像和一个大约200个字符长度的字节数组。我想要将图片保存,并以与该字节数组对应的文件名保存,但不是保存字节数组本身,因为我不想让文件名达到200个字符。所以,我的想法是将字节数组保存到数据库中,然后使用MD5算法得到一个短文件名。当需要显示特定的图像时,我查找其字节数组,进行MD5计算,然后查找该文件。
到目前为止都还好。问题在于潜在地两个不同的字节数组可以哈希为相同的MD5值。那么,一个文件实际上将覆盖另一个文件。或者它们能吗? 我的问题是:
  • 两个大约200个字符长度的字节数组是否可能哈希成相同的字符串?
  • 如果可能,那是每10个宇宙年一次这样的事情,还是可以在我的应用中可能发生?
  • 有没有一个哈希算法可以产生一个(比如)32个字符长的独一无二的字符串?

1
我不理解通过某些任意计算自动确定文件名的必要性。只需创建一些关键字...文件名或其他内容,并将其存储在200个字符字节数组旁边,然后将其用作文件名。这样可以避免计算混乱,并使底层代码更简单... - John Sobolewski
请按照惯例使用大写字母。 - thb
jsobo - 我想使用哈希(或类似)函数的原因是,在许多情况下,源字节数组(和PNG)对于不同的用户将是相同的,因此我可以避免在该实例中保存多个版本的相同PNG。也就是说,如果100个人都有相同的字节数组(由于相同的选项集),那么他们都共享同一个PNG文件。 - Max Williams
8个回答

8

从一个200字节的源中逻辑上不可能得到一个32字节的代码,这个代码在所有可能的200字节源中都是唯一的,因为你可以在200字节中存储更多的信息而不是32字节。

唯一的例外是,在这200字节中存储的信息也适合于32字节,即此时你的源数据格式极其低效且浪费空间。


6

哈希(与加密相反)时,您正在减少被哈希数据的信息空间,因此总会存在碰撞的可能性。

在哈希函数中,最好的情况是所有哈希值都均匀分布在哈希空间中,并且您的哈希输出足够大,以提供您所说的“每十亿年一次的事件”!

因此,哈希对您是否足够“好”的影响取决于碰撞的后果。您始终可以将唯一ID添加到校验和/哈希中,以获得两全其美的效果。


2
如果您想仅从数据源计算代码,则无法这样做。如果您可以使用唯一标识符,则可能不需要哈希。 - JohnB

4
为什么不使用数据库中的唯一ID呢?可以参考自增ID示例

唯一标识符并不总是整数。一些关系型数据库具有uuid功能。 - Shiplu Mokaddim

4

两个哈希值发生碰撞的概率取决于哈希大小。MD5生成128位哈希值,因此对于2128+1个哈希,至少会有一个碰撞。

SHA1的这个数字为2160+1SHA512的这个数字为2512+1

这里有一个规则适用。输出位数越多,独特性越强,计算量也越大。因此需要在独特性和计算量之间做出权衡,选择最佳方案。


1
在从上述数字得出任何结论之前,您应该先了解生日攻击。http://en.wikipedia.org/wiki/Birthday_attack - John Sobolewski
结论是正确的。对于2^128+1个输入,将会发生碰撞(至少一个)。生日悖论表明你很可能更早地得到一个。 - Thilo

3

两个大约200个字符的bytearrays是否可以MD5哈希到相同的字符串?

考虑到200字节的字符串比32字节的字符串(MD5摘要)更多,这是肯定会发生的。

所有哈希函数都有这个问题,但有些比MD5更强大。请尝试SHA-1。git正在使用它来达到同样的目的。


2

就像其他人所说的那样。哈希算法不会为您提供所需的内容,除非您可以接受冲突风险。

数据库对此很有帮助。 您可以为每个200个字符长的字符串获取唯一索引。这里没有冲突,并且您需要将这些200个字符的名称设置为索引,以便它将使用额外的内存但会为您排序,使搜索非常快速。您将获得一个独特的标识符,可以轻松用于文件名。


2
可能会出现两个MD5哈希值相同的情况。1996年,MD5算法被发现存在漏洞,密码分析专家建议改用SHA-1哈希算法。
因此,我建议您切换到SHA-1(40个字符)。但不要担心:我怀疑您的两张图片会得到相同的哈希值。我认为您可以在应用程序中承担这种风险。

0

我对哈希算法的工作并不是很熟悉,但据我理解,在哈希算法中总会存在碰撞的可能性,即两个不同的对象可能被哈希到相同的哈希值,但可以保证每次一个对象都将被哈希到相同的哈希值。还有其他技术可用于解决这个问题,比如线性探测。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接