Files

38 lines
1.8 KiB
JavaScript
Raw Permalink Normal View History

'use strict';
// MD5 is required by Baidu's upload protocol; it is not used for authentication.
const ZhaoFileHash=(()=>{
const shifts=[7,12,17,22,5,9,14,20,4,11,16,23,6,10,15,21];
const constants=Array.from({length:64},(_,i)=>Math.floor(Math.abs(Math.sin(i+1))*4294967296)|0);
function md5(input){
const bytes=new Uint8Array(input),length=bytes.length,padded=new Uint8Array(Math.ceil((length+9)/64)*64);
padded.set(bytes);padded[length]=128;const view=new DataView(padded.buffer);
view.setUint32(padded.length-8,(length*8)>>>0,true);view.setUint32(padded.length-4,Math.floor(length/536870912),true);
let h=[0x67452301,0xefcdab89|0,0x98badcfe|0,0x10325476];
for(let offset=0;offset<padded.length;offset+=64){
let [a,b,c,d]=h;
for(let i=0;i<64;i++){
let f,g;
if(i<16){f=(b&c)|(~b&d);g=i;}
else if(i<32){f=(d&b)|(~d&c);g=(5*i+1)%16;}
else if(i<48){f=b^c^d;g=(3*i+5)%16;}
else{f=c^(b|~d);g=(7*i)%16;}
const shift=shifts[Math.floor(i/16)*4+i%4],sum=(a+f+constants[i]+view.getInt32(offset+g*4,true))|0;
const next=(b+((sum<<shift)|(sum>>>(32-shift))))|0;a=d;d=c;c=b;b=next;
}
h=[(h[0]+a)|0,(h[1]+b)|0,(h[2]+c)|0,(h[3]+d)|0];
}
return h.map(n=>[0,8,16,24].map(s=>((n>>>s)&255).toString(16).padStart(2,'0')).join('')).join('');
}
async function blocks(file,progress=()=>{},valid=()=>true){
const result=[];
for(let offset=0;offset<file.size;offset+=4194304){
if(!valid())throw Object.assign(Error('操作已取消'),{stale:true});
result.push(md5(await file.slice(offset,offset+4194304).arrayBuffer()));progress(Math.min(file.size,offset+4194304),file.size);
await new Promise(resolve=>setTimeout(resolve,0));
}
return result;
}
return {md5,blocks};
})();
if(typeof module!=='undefined')module.exports=ZhaoFileHash;