V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
caduke
V2EX  ›  Python

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

  •  
  •   caduke · 2016-02-19 10:01:43 +08:00 · 7329 次点击
    这是一个创建于 2995 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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


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

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

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

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

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

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

    我认为正确的姿势应该是:
    1.保存(或生成)文件时,既对文件进行 hash 值生成(空闲时生成以备后用,避免使用时耗费时间)
    2.先比较文件的外部属性,如 size 等
    3.比较 hash 值
    (其实到这里就应该结束了)
    4.如果还不放心,可以继续比较两文件特定大小、特定位置的 stream (等同于二次比较 hash 值,碰撞几率减半)(是否比较根据你需要的精确度来确定)
    akira
        21
    akira  
       2016-02-19 17:47:46 +08:00
    如果只是对特定的 2 个文件做比较,那随便你怎么弄都行。
    如果是对一大堆文件做比对,那肯定还是先用哈希算法做一次过滤比较好。
    SlipStupig
        22
    SlipStupig  
       2016-02-22 03:55:18 +08:00
    @lhbc md5 极易碰撞,大神很多网络证书的 sign 都是 md5 ,还有很多网站后台认证算法都是裸奔的 MD5 ,劫持入侵数据指日可待啊!
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1027 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 18:06 · PVG 02:06 · LAX 11:06 · JFK 14:06
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.