首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在线/流MD5算法?

在线/流MD5算法?
EN

Stack Overflow用户
提问于 2013-09-19 03:17:26
回答 2查看 1.2K关注 0票数 2
  1. 随着HTML5的到来,是否可以使用FileReader API和onprogress事件访问数据?
  2. 如果是这样的话,是否有“在线”版本的MD5或其他快速散列算法,以便我可以在文件被完全读取之前开始计算哈希?

我想计算哈希客户端,并只发送哈希到服务器之前,发送一个完整的文件,以检查重复,然后开始文件上传。

我现在不关心对旧浏览器的支持。

编辑:我认识到哈希冲突不能保证文件重复,唯一的方法是逐字节检查文件,这意味着无论如何我都要上传文件。这种可能性很低,以至于我愿意承担这个风险;最坏的情况是,我会提示用户并说:“这个文件似乎已经在服务器上了;您确定要上传吗?”

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-09-19 03:44:13

是否有一个“在线”版本的MD5或其他快速散列算法,以便我可以开始计算哈希之前,文件是完全读取?

是的,如果您想使用SHA,可以使用sjcl。sjcl不支持MD5,所以您必须自己编写它(虽然我确信已经有人这样做了)。CryptoJS支持本地MD5,但速度要慢得多。

我认识到哈希冲突不能保证文件重复.这个概率很低,我愿意冒这个险;

相对于自然发生碰撞,流星撞击地球并终结人类生命的可能性(因此完全消除了对哈希的需要)是相当低的。当然,除非用户故意创建一个碰撞,因为MD5的碰撞阻力被破坏了。

这里是一个live 演示,我认为您正在尝试完成这个任务,减去“访问数据随它而来”部分。我不确定这是否可能。我很久以前就写过这篇文章了,它使用了CryptoJS,所以性能不是很好,但是它完成了工作。重要的部分是:

代码语言:javascript
复制
function handleFileSelect(evt) 
{
    evt.stopPropagation();
    evt.preventDefault();

    var files = evt.target.files || evt.dataTransfer.files; // FileList object.

    for (var i=0, file; file = files[i]; ++i)
    {
        // this creates the FileReader and reads stuff as text
        var fr = new FileReader();

        fr.onload = (function(theFile) {
            return function (e) {
                var hashes = parsePseudoBuffer(e.target.result);

                document.getElementById('output').innerHTML += '<br />' + theFile.name + '<br />' 
                + 'MD5: ' + hashes.md5 + '<br />' + 'SHA1: ' + hashes.sha1 + '<br />' ;

            };
        }) (file);

        fr.readAsArrayBuffer(file); // ArrayBuffer
    }

}

function parsePseudoBuffer(result)
{

    var buffs = new Uint8Array(result); // buffer thingie       
    var md5 = CryptoJS.algo.MD5.create();
    var sha1 = CryptoJS.algo.SHA1.create();     
    var bufsize = 8 * 1024; // 8K buffer

    for (var bstart=0, bend=bufsize; bstart < buffs.length; bstart+=bufsize, bend+= bufsize)
    {
        var data = CryptoJS.lib.WordArray.create(buffs.subarray(bstart, bend)); 
        md5.update(data);
        sha1.update(data);          
    }

    md5 = md5.finalize(); 
    sha1 = sha1.finalize();         

    return {'md5': md5, 'sha1': sha1} ;

}
票数 2
EN

Stack Overflow用户

发布于 2013-09-19 06:45:45

我做了一些实验。看起来,我们可以通过使用读取器对象上的不完整的onprogress来获取在result事件中读取的最后一个块。只有当我们使用reader.readAsArrayBuffer (只有Chrome?)时,才能访问它。或reader.readAsBinaryString.字符串的问题是,如果您想要获取其中的一部分,就必须将其切片,从而生成一个副本(非常慢)。

ArrayBuffers有一个.subarray方法,它在没有复制任何数据的情况下将视图创建到缓冲区中。这正是我们想要的。但是,它似乎在基类上是不可用的;从文档中还不清楚当我们使用这个缓冲区构造派生类(例如Uint8Array)时会发生什么,但是考虑到原始缓冲区可以通过只读属性访问,我假设它没有复制。

sjcl和CryptoJS都很方便地使用了.update方法,这些方法将接受这个ArrayBufferView,这样您就可以动态地更新哈希了。因此,我提出了以下解决方案(使用jQuery、下划线和sjcl):

代码语言:javascript
复制
$(document).on('drop', function(dropEvent) {
    dropEvent.preventDefault();

    _.each(dropEvent.originalEvent.dataTransfer.files, function(file) {
        var reader = new FileReader();
        var pos = 0;

        var hash = new sjcl.hash.sha256();

        reader.onprogress = function(progress) {
            var chunk = new Uint8Array(reader.result, pos, progress.loaded - pos);
            pos = progress.loaded;
            hash.update(chunk);
            if(progress.lengthComputable) {
                console.log((progress.loaded/progress.total*100).toFixed(1)+'%');
            }
        };

        reader.onload = function() {
            var chunk = new Uint8Array(reader.result, pos);
            if(chunk.length > 0) hash.update(chunk);
            console.log(sjcl.codec.hex.fromBits(hash.finalize()));
        };

        reader.readAsArrayBuffer(file);
    });
});

请注意,该解决方案目前只在Chrome中工作,而且速度相当慢。我认为sjcl不仅仅是散列文件,而是关键--增强它,这确实不是我想要的。稍后会进一步调查。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18885655

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档