3

如何存储crypto.createHash('sha1')(填充后hash.update(buffer))的当前状态以在另一个http request可能发生在 node.js 的不同进程中使用它?

我想象做这样的事情:

var crypto = require('crypto'),
    hash   = someDatabase.read('hashstate')    // continue with filled hash
             || crypto.createHash('sha1');     // start a new hash

// update the hash
someObj.on('data', function(buffer){
    hash.update(buffer);
});
someObj.on('end', function(){
    // store the current state of hash to retrieve it later (this won't work:)
    someDatabase.write('hashstate', hash);

    if(theEndOfAllRequests){
        // create the result of multiple http requests
        hash.digest('hex');
    }
});
4

3 回答 3

3

我可以提出几个选择,并进行不同的权衡。需要注意的重要一点是它crypto不会暴露其哈希函数的部分状态,因此无法直接实现将状态保存到数据库的计划。

选项 1 涉及深入研究哈希函数,这可能很棘手。幸运的是,已经有一个用 javascript 编写的。同样,它不会暴露状态,但我不认为这将是一个非常困难的代码转换。我相信整个状态都存储在create- h0-4, block, offset, shift, 和totalLength. 然后,您可以按照计划将状态保存在数据库中。

选项 2 涉及使用crypto和传递要在进程之间散列的数据。我认为这更容易使用,但速度也慢得多。在一些快速测试中,看起来消息将以大约 2.5-3MB/秒的速度传递,因此每个 3MB 块大约需要 1.5 秒(您只能传递字符串,所以我希望您需要 Base64 转换这需要额外的 33%)。为此,您将使用process.send与标识 ID 一起发送数据。主进程将worker.on在每个工作人员上使用来获取消息,并保留 id 到散列对象的映射。最后,您可能希望在消息中有一个标志,告诉主服务器它正在接收最后一条消息,并且它会worker.send生成哈希(在工作人员中收到process.on)。

我很乐意详细说明其中最合适的声音。

于 2014-01-10T07:44:47.743 回答
2

基本上,您需要做的就是为每个“相关请求组”创建一个新的散列,将其直接存储在代码中的一个对象中,并独立于正在进行的任何其他不相关请求而不断更新该散列。

所需要的只是您能够以某种方式命名一组相关请求,以便您知道它们属于一起,并确保您的长期哈希的范围包含处理功能。

类似于以下内容(假设在任何给定时刻仅发生一组请求,并且不担心命名请求组以确保您不会交叉):

var crypto = require('crypto'),
    // don't create it here, but set the scope so it will live between requests
    hash = null;

someObj.on('data', function(chunk) {
    // we have to have some data in chunk that allows us
    // to relate this request to its fellow requests, or assume
    // that no unrelated requests are occurring at this time
    // var name = chunk.this_is_my_name;
    if (hash === null) hash = crypto.createHash('sha1');
    hash.update(chunk);
});

someObj.on('end', function(){
    if(theEndOfAllRequests){
        // create the result of multiple http requests
        var digest = hash.digest('hex');

        /* use the digest */

        hash = null; // so it can be created fresh for the next set of requests
    }
});
于 2014-01-08T15:24:03.420 回答
1

您可以hash.update在数据进入时多次调用。

在不知道如何获取块的情况下很难准确地说出应该做什么,但这里有一个 v1 Streams 的简单示例:

var hash = crypto.createHash('sha1');
var data = // incoming file data

data.on('data', function(chunk){
  hash.update(chunk);
});
data.on('end', function(){
  var sha = hash.digest('hex');

  // Do something with it
})
于 2013-05-26T03:24:08.137 回答