V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
nowheretoseek
V2EX  ›  问与答

百度网盘有些文件有两个 MD5?

  •  
  •   nowheretoseek · 53 天前 · 1281 次点击
    这是一个创建于 53 天前的主题,其中的信息可能已经有所发展或是发生改变。

    孤陋寡闻,昨天刚知道秒传油猴脚本这个东西,于是结合源码抓包研究了一下。

    其基本原理可以用这篇文章嘿嘿,我发现了百度网盘秒传的秘密 - 51CTO.COM的这段话总结:

    百度网盘上传时,如果是超过 256KB 的文件,将计算整个文件的 MD5 和文件前 256KB 内容的 MD5 ,并对两个 MD5 值加密后请求后端执行秒传。后端通过两个 MD5 和长度信息判断是否存在该文件,如果存在则完成秒传。

    可能文章过时了,我没有发现对两个 MD5 值的加密,但发现了另一个现象,不得要领。描述如下:

    百度页面提供的获取文件列表的 xhr 请求中可以看到每个文件的 MD5 (简称 MD5A ), 秒传请求中使用整个文件的 MD5 (简称 MD5B )和前 256KB 内容的 MD5 (简称 MD5C )。我发现有些文件的 MD5A 跟 MD5B 一致,有些文件的则不一致,并且这跟文件大小没有什么关系。MD5A 就是算出来哪个,而 MD5B 是从文件下载请求的响应 headers 中获取的,在 Content-MD5 字段。

    所以请问,这个 MD5B 是怎么来的,怎么会跟 MD5A 不一致呢?已经有 MD5C 用来规避 MD5 碰撞了,这种设计又是为了什么?

    第 1 条附言  ·  52 天前
    更正:正文有误,MD5B 才是全量文件的真实 MD5 。
    第 2 条附言  ·  50 天前

    看到qjfoidnh/BaiduPCS-Go: iikira/BaiduPCS-Go原版基础上集成了分享链接/秒传链接转存功能有关于MD5的叙述,也许MD5A可能是分片上传导致的:

    • 分片上传之后, 服务器可能会记录到错误的文件md5, 可使用 fixmd5 命令尝试修复文件的MD5值, 修复md5不一定能成功, 但文件的完整性是没问题的.
    • 禁用分片上传可以保证服务器记录到正确的md5.
    • 禁用分片上传时只能使用单线程上传, 指定的单个文件上传最大线程数将会无效.

    使用分片上传文件, 当文件分片数大于1时, 百度网盘服务端最终计算所得的md5值和本地的不一致, 这可能是百度网盘的bug.

    不过把上传的文件下载到本地后,对比md5值是匹配的, 也就是文件在传输中没有发生损坏.

    对于MD5值可能有误的文件, 程序会在获取文件的元信息时, 给出MD5值 "可能不正确" 的提示, 表示此文件可以尝试进行MD5值修复.

    修复文件MD5不一定能成功, 原因可能是服务器未刷新, 可过几天后再尝试.

    修复文件MD5的原理为秒传文件, 即修复文件MD5成功后, 文件的创建日期, 修改日期, fs_id, 版本历史等信息将会被覆盖, 修复的MD5值将覆盖原先的MD5值, 但不影响文件的完整性.

    注意: 无法修复 20GB 以上文件的 md5!

    11 条回复    2021-11-27 01:25:50 +08:00
    kiotech
        1
    kiotech  
       53 天前
    可能是为了优化性能,File Meta 信息生成 MD5 值 A ,文件内容生成 MD5 值 B 。文件内容相同,但修改了文件名称 /日期等 meta ,会导致 MD5 变化。
    JinTianYi456
        2
    JinTianYi456  
       53 天前
    > 最后给大家留一个思考题:后端拿到 MD5 后,怎么判断后端是否有这个 MD5 呢? 这可是大厂经常爱考的一个面试题哦,来开动脑筋想一下!

    怎么搞?有奇淫技巧?
    kera0a
        3
    kera0a  
       53 天前 via iPhone   ❤️ 2
    @JinTianYi456 布隆过滤器
    JinTianYi456
        4
    JinTianYi456  
       53 天前
    @kera0a #3 感觉好像有点不对,比如后端拿到 md5 了,返回一定存在,那就秒传成功;返回 unknown ,那就开始上传,大不了多存一份呗。但如果是布隆过滤器,返回一定不存在,那就开始上传;返回 unknown ,也得上传啊。
    finab
        5
    finab  
       53 天前
    @JinTianYi456
    我没有真的做过类似的东西,我只是简单的考虑哈~

    先走布隆过滤器,返回一定不存在,至少这部分查询就已经确切完成了,不能闪存的文件就可以开始上传了(新文件和个人文件不知道占多少查询比率)查询结束。

    已经上传过的文件,可以再查一个缓存,是返回一定存在或 unknown , 可以缓存热门文件之类的。

    再之后就是查个人缓存或者查库或者直接传都行,这部分 上传过又不是热门的文件 量 相对来说就很少了。
    selfcreditgiving
        6
    selfcreditgiving  
       53 天前   ❤️ 1
    做过分片上传功能的就知道怎么回事了。一个大文件算 MD5 很慢的,在客户浏览器计算 md5 ,如果是 1G 文件等个 10 秒用户才看到上传进度条开始动,这个不太能接受。百度是文件头尾各取一部分内容合并起来生成“伪文件 md5”(一定程度上可以当做是一个文件的唯一 ID )。
    第二个 MD5 是等大文件上传后,在后端再生成的“真文件 MD5”。
    selfcreditgiving
        7
    selfcreditgiving  
       53 天前
    @JinTianYi456 直接用 MD5 命名文件,都存到一个大文件夹,存的了就是没有,报错有同名文件就是有?

    还是直接数据库插这条数据,以 MD5 字符串作为唯一索引,插不进就说明有?
    nowheretoseek
        8
    nowheretoseek  
    OP
       52 天前
    @selfcreditgiving 有道理,我没相关经验就是参不透。所以 MD5B 即 Content-MD5 字段获取的才是完整文件的 MD5 ,MD5A 是最初上传时在客户端生成的吧
    selfcreditgiving
        9
    selfcreditgiving  
       52 天前   ❤️ 1
    @nowheretoseek

    >百度页面提供的获取文件列表的 xhr 请求中可以看到每个文件的 MD5 (简称 MD5A ), 秒传请求中使用整个文件的 >MD5 (简称 MD5B )和前 256KB 内容的 MD5 (简称 MD5C )。

    从这句话分析的话,肯定是秒传请求的是 客户端生成的“快速版的 MD5”。获取文件列表请求的 MD5 是真实的 文件全量 MD5
    nowheretoseek
        10
    nowheretoseek  
    OP
       52 天前
    @selfcreditgiving 我找了个小点的文件验证,发现文件下载时从 headers 中拿到的 MD5B 是全量 MD5 ,文件列表 xhr 请求中给出 MD5A 的不是。Content-MD5 在响应头中,作为真实 MD5 ,供客户端验证下载的文件无误,也是应有之义。

    根据你前面的讲解,有无可能 MD5A 是在初次上传时生成,仅作为标识符使用?总之,它在哪个环节、根据什么规则、为了什么而生成,我还是不太清楚。
    nowheretoseek
        11
    nowheretoseek  
    OP
       52 天前
    @selfcreditgiving 提问时找了几个文件验证,正好 MD5A 与根据文件算出来的 MD5 一致,而 MDB5 要下载抓包才能知道,想当然就认为 MD5A 是全量文件的 MD5 了,已附言更正。抱歉。
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   3216 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 21ms · UTC 10:35 · PVG 18:35 · LAX 02:35 · JFK 05:35
    ♥ Do have faith in what you're doing.