python 在比较 2 个文件一致性时是否该使用 MD5

2016-02-19 10:01:43 +08:00
 caduke

如题,由于 md5 校验也需要读取文件,所以使用 open 的'br'模式读取部分内容会不会更直接呢?
如果 md5 更好,好在什么地方呢?

7535 次点击
所在节点    Python
22 条回复
zzn
2016-02-19 10:33:18 +08:00
如果有两个文件,应该是直接读取会直接一点,但哪种更快?要实际比较一下
Septembers
2016-02-19 10:35:13 +08:00
要验证完整性的话 建议使用 Hash 算法
jimzhong
2016-02-19 10:37:12 +08:00
如果只要比较两个文件,且都在本地,则直接比较更好。
rock_cloud
2016-02-19 10:40:29 +08:00
如果两个文件的 MD5 不相同,则文件内容一定不相同,如果两个文件的 MD5 相同,则文件内容可能相同。
所以如果是比较一个文件和许多其他文件是否相同,并且提前知道其他文件的 MD5 值,则先比较 MD5 值可以大大提高文件比较的速度。
lhbc
2016-02-19 10:45:42 +08:00
要确保 100%正确就必须校验全文
而且不能使用 MD5 这种极易碰撞的算法,起码 SHA1 ,最好 SHA256
congeec
2016-02-19 10:49:38 +08:00
文件大小,文件多不多,要比较几次都影响算法
Frapples
2016-02-19 11:07:26 +08:00
比较两个文件一致性有两种方案:
1. 直接逐字节比较文件内容
2. 使用 md5 等 hash 算法比较


论程序执行效率来说,方案 1 需要把两个文件的内容都扫一遍, hash 算法肯定比单单扫一遍文件内容要慢。不过考虑到 python 中 hash 算法是优化过的 C 实现的,扫文件内容则是单纯的 python 代码, hash 应该没想象的慢。。。
然而值得注意的是,假如这两个文件是跨主机的呢?需要用网络传递信息呢?这种情况下,考虑到网络传输慢很多,方案一需要传递长长的文件内容,但是方案二只需要传递短短的 hash 就 ok 了。

论程序可靠性来说, hash 算法有碰撞的可能,尤其是 md5 这种已经过时的 hash 算法,人为碰撞的可能性更大。但是直接比文件内容就没这个问题了, 100%靠谱。

从程序容易写这方面看,无论方案一还是二几句代码就能搞定吧 。。。

所以的话,本地程序还是逐字节比较好,但是跨主机的用 hash 较好。要注意的是不要用 md5 这种过时 hash ,应该采用类似 sha512 这种霸气点的。
caduke
2016-02-19 11:14:11 +08:00
感谢大家的回答,原本只是想到如果多加一层 hash 校验性能会更差,但是了解了 hash 是 C 实现的,所以不那么认为了!
aec4d
2016-02-19 11:23:19 +08:00
怕个毛碰撞-_- MD5+CRC32
otakustay
2016-02-19 11:23:48 +08:00
如果这 2 个文件没有事先就存在的 MD5 码,那么你生成 MD5 也是需要全部读取一遍的,不如就地读取判等,省了 MD5 的 CPU 开销
如果原来就有 MD5 码,且文本本身是存在意义的(如小说等可读文字、论坛用户提交的贴子,不是一堆随便构造的乱码),那么 MD5 可以认为是可信的,在有意义的前提下构造 MD5 冲撞概率太小
如果这类比较会在今后频繁发生,那么使用 MD5 并存下来是个不错的选择
wbsdty331
2016-02-19 11:24:09 +08:00
md5 有可能碰撞
试试 crc32 或者 sha1
fy
2016-02-19 11:46:06 +08:00
为什么总想着碰撞所以要全文比较呢?

1. 如果两个文件都是本地文件,全文比较也无不可
2. 如果其中一个是网络文件:提取文件的大小、前 XXX 字节、哈希作为特征值,碰撞概率基本可以忽略不记了。
wy315700
2016-02-19 11:46:25 +08:00
hmac
Anteiku
2016-02-19 12:09:59 +08:00
billlee
2016-02-19 13:28:05 +08:00
@wbsdty331 crc32 更可能碰撞
otakustay
2016-02-19 13:43:23 +08:00
@wbsdty331 没有不会碰撞的摘要算法,不过 md5 有相对成熟的创造碰撞的方法就是了
realpg
2016-02-19 14:09:28 +08:00
计算任何 hash 时候,都要把文件内容完整读一遍,而且运算过程本身也是执行开销。总内存消耗量应该是把两个文件分别执行 md5 的过程总内存开销中的大者。
直接读取进来比较的话,总内存消耗量就是俩文件大小之和,近似的。
本地文件,不是巨大文件,语言有比较方便的大文件数据读入比较,倾向于直接比较。

如果 hash 比较,建议使用 md5+crc 之类双轻计算 hash ,能同时碰撞两个 hash 的冲突,很难构造,对于一般安全级别足够了
raptor
2016-02-19 14:37:53 +08:00
MD5 都碰撞了,还 CRC32 …… CRC32 的碰撞率比 MD5 高得多得多得多……而且构造一个 CRC32 碰撞也比构造一个 MD5 碰撞容易得多得多得多……
VYSE
2016-02-19 16:36:37 +08:00
HASH 比较仅仅好在多个文件比较
两个文件比较,请用 filecmp.cmp
WhoMercy
2016-02-19 16:49:43 +08:00
如果文件大小不确定,直接比较文件的内容是效率极低的方法。

我认为正确的姿势应该是:
1.保存(或生成)文件时,既对文件进行 hash 值生成(空闲时生成以备后用,避免使用时耗费时间)
2.先比较文件的外部属性,如 size 等
3.比较 hash 值
(其实到这里就应该结束了)
4.如果还不放心,可以继续比较两文件特定大小、特定位置的 stream (等同于二次比较 hash 值,碰撞几率减半)(是否比较根据你需要的精确度来确定)

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/257552

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX