当前位置: 首页 > 科技观察

哎,我发现了百度网盘即时传输的秘密

时间:2023-03-22 14:23:00 科技观察

微信上有读者问我:百度网盘的即时传输功能是如何实现的?这个问题我其实也想过,我猜大概是前端计算一个文件的hash值(比如MD5)发给后端,网盘服务器判断这个文件是否存在。如果存在,则直接在后台完成文件的“转储”,并直接告诉前台上传成功。但这是我自己的猜测,是否正确,我从来没有验证过。我告诉他我的猜测,他问:如果发生哈希冲突怎么办?。我想了想说:那就再加几个哈希吧!但是百度网盘是怎么做到的呢?既然这位读者问了,我就趁机花几分钟研究了一下,算是解答了这个疑惑。增加了知识。MD5冲突首先,只使用一个散列值。事实证明,冲突会发生,而不仅仅是理论上。比如我在知乎上找了一个例子。下面两条不同的数据只相差两个字节:分别计算md5,结果是一样的:所以,如果只用一个hash值来判断是同一个文件,那么就更容易出现这种情况张冠李戴。甚至,有人据此提出了hash碰撞攻击:如果我知道一个文件的md5值却无法获取到该文件,我通过数学计算构造了一个md5相同的文件,那岂不是可以直接删除那个文件?文件?给我转的?如果是私人文件怎么办?那么什么都不会发生!百度网盘是做什么的?百度网盘是怎么做到的?先上传一个稍微大一点的文件(小文件有hash计算,功夫已经上传了),用浏览器F12大法,看它的网络请求:可以看到百度网盘是分块传输文件的,这也是一个目前业内流行的做法。block,如果网络不好掉线了,下次只需要传输剩余的block,就可以从断点继续传输了。但是注意,在上面的block中间,插入了一个叫rapidupload接口的request。从名字也可以猜到。这个接口肯定和它的“二次传输”功能有关。我们看一下请求的参数,是一个Form有几个字段:content-length:文件长度content-md5:文件slice的MD5-md5:文件slice的MD5,这里你猜对了,一定是由这三个参数共同判断,同时满足条件的就是同一个文件!看服务器回复了什么:二传成功!那么如果上传了一个后台肯定不存在的文件,会返回什么?我构建了一个测试:看,404!说明后台没有这个文件,老老实实传下去吧!接下来我想看看这个md5切片,百度网盘是怎么切的。通过网络通信中的Initiator函数,可以定位到JS代码在请求的地方:通过调用栈,看到调用rapidUpload的函数,再跟进,找到计算分片MD5的地方:其实就是对于文件的前262144字节,即256KB,进行计算。如果文件小于此,则无需秒传。但是奇怪的是,我扣除了文件的前256字节,计算出来的md5和它界面上传的参数不一致!这让我想了好几分钟,是不是这么简单?我再次中断点击计算位置,发现它的计算和我的一样,只是通过网络发送后变了。果然是薛定谔的MD5,好奇怪!不过程序不是量子力学,不会说谎,很快我就发现了问题:百度网盘可能是担心它的路径号被发现,它把文件的MD5和切片的MD5都加密了!这就是加密函数:一些简单的字符串处理。好了,现在可以回答之前读者的问题了:上传到百度网盘时,如果文件超过256KB,会计算整个文件的MD5和文件前256KB的MD5,并对这两个MD5值进行加密并请求后端执行即时传输。后端通过两个MD5和长度信息判断文件是否存在,存在则完成二次传输。这样做,虽然理论上不能保证不会发生哈希冲突,但是这样一来,至少概率降低了很多。最后给大家留一个思考题:后端拿到MD5后,如何判断后端是否有MD5?这是大厂经常爱考的面试题。让我们考虑一下!本文转载自微信公众号“编程技术宇宙”,可通过以下二维码关注。转载本文请联系编程技术宇宙公众号。