【发布时间】:2013-09-21 21:30:36
【问题描述】:
TL;DR:我有一个 CMS 系统,它使用文件内容的 SHA-1 作为文件名来存储附件(不透明文件)。鉴于我已经知道两个文件的 SHA-1 哈希匹配,如何验证上传的文件是否真的与存储中的一个匹配?我想要高性能。
加长版:
当用户向系统上传新文件时,我会计算上传文件内容的 SHA-1 哈希值,然后检查存储后端中是否已存在具有相同哈希值的文件。 PHP 在我的代码运行之前将上传的文件放在/tmp 中,然后我对上传的文件运行sha1sum 以获取文件内容的SHA-1 哈希。然后,我从计算的 SHA-1 哈希计算扇出,并在 NFS 挂载目录层次结构下确定存储目录。 (例如,如果文件内容的 SHA-1 哈希是 37aefc1e145992f2cc16fabadcfe23eede5fb094,则永久文件名是 /nfs/data/files/37/ae/fc1e145992f2cc16fabadcfe23eede5fb094。)除了保存实际文件内容之外,我将 INSERT 在 SQL 数据库中换行用户提交的元数据(例如Content-Type、原始文件名、日期戳等)。
我目前正在解决的极端情况是,新上传的文件的 SHA-1 哈希值与存储后端中的现有哈希值相匹配。我知道这种意外发生的变化是天文数字的低,但我想确定一下。 (特意案例请见https://shattered.io/)
给定两个文件名$file_a 和$file_b,如何快速检查两个文件的内容是否相同?假设文件太大而无法加载到内存中。对于 Python,我会使用filecmp.cmp(),但 PHP 似乎没有类似的东西。我知道这可以通过fread() 来完成,如果找到不匹配的字节则中止,但我宁愿不编写该代码。
【问题讨论】:
-
您是否正在尝试对冲哈希冲突?
-
使用散列是个好主意。正如您所提到的,碰撞的可能性非常低 - 所以您可以确定在一般情况下,它会没事的。如果没有 - 请让我们知道您对这些文件内容的情况:p
-
git 正在使用 sha1,所以我认为您可以安全地使用 sha1 :)
-
我试图避免由于哈希冲突而丢失文件内容。是的,如果我看到碰撞,我会保留这两个文件。我敢打赌,在那种情况下,我会发现我的永久存储已经烂掉了。 (在任何存储设备上出现随机位错误的变化似乎比发现 SHA-1 冲突要高得多;在这种情况下,我仍然想要一个损坏文件的新副本。)
-
@Kakawait: @Kakawait:
git据我所知,在仅仅因为 SHA-1 哈希恰好匹配而相信文件相同之前,也会进行逐字节比较测试。
标签: php performance file-upload file-io