从Node.js加密库得到奇怪的结果

时间:2014-02-06 06:16:44

标签: javascript node.js cryptography

我正在尝试编写一个函数来递归获取目录中所有文件的md5sum,但是每次运行时都会得到不同的结果而没有修改任何文件。

代码我从以下方面得到了这些结果:

var crypto = require('crypto');
var fs = require('fs');
var path = require('path');

function _deepMD5(dir, md5){
    var files = fs.readdirSync(dir);
    for(var i = 0; i < files.length; i++){
        var fp = dir+path.sep+files[i];
        if(fs.lstatSync(fp).isDirectory()){
            _deepMD5(fp, md5);
        }
        else{
            var fh = fs.openSync(fp, 'r');
            var chunkSize=1024;
            var buffer=new Buffer(chunkSize, 'binary');
            while(fs.readSync(fh, buffer, 0, chunkSize, null) != 0){
                md5.update(buffer);
            }
        }
    }
}

function deepMD5(dir){
    var md5sum = crypto.createHash('md5');
    _deepMD5(dir, md5sum);
    return md5sum.digest('hex');
}

console.log(deepMD5("."));

2 个答案:

答案 0 :(得分:2)

创建新缓冲区时,不会清除它。所以你从随机填充的缓冲区开始 - 这是运行之间的变化来自。

接下来,您读取1024个字节并使用它更新哈希值。但是,该读取实际上读取最多 1024字节。它返回实际读取的字节数。你会想要意识到这一点。否则,每次你通过一个不能被1024字节整除的文件时,你会在最后用额外的东西更新哈希值(如果是第一次读取,则是随机的,或者是先前读取的剩余内容。

因此,每当读取少于chunkSize个字节时,您希望切掉实际来自最近读取的字节并将该缓冲区传递给update

var length;
while((length = fs.readSync(fh, buffer, 0, chunkSize, null)) != 0){
    if(length == chunkSize)
        md5.update(buffer);
    else
        md5.update(buffer.slice(0, length));
}

为了效率,我在没有必要时避免切片。当然,如果您更喜欢较短的代码并且不担心性能,您可以随时进行切片。

答案 1 :(得分:1)

您的代码需要进行非常小的更改才能使其按预期工作:您需要在创建后使用buffer.fill(0)重置新缓冲区。

new Buffer()表达式分配内存但不清理,因此您必须手动执行此操作。如果您的所有文件都超过1024字节大小,您可能不会注意到该问题。但是,如果至少有一个文件的大小小于1024字节,则很可能会出现问题。

更正_deepMD5功能:

function _deepMD5(dir, md5){
    var files = fs.readdirSync(dir);
    console.info("running with files: ", files)
    for(var i = 0; i < files.length; i++){
        var fp = dir+path.sep+files[i];
        if(fs.lstatSync(fp).isDirectory()){
            _deepMD5(fp, md5);
        }
        else{
            var fh = fs.openSync(fp, 'r');
            var chunkSize=1024;
            var buffer=new Buffer(chunkSize, 'binary');
            buffer.fill(0) // that will fix the issue.
            while(fs.readSync(fh, buffer, 0, chunkSize, null) != 0){
                md5.update(buffer);
            }
        }
    }
}

我希望这会有所帮助。