【问题标题】:nodejs crypto module, does hash.update() store all input in memorynodejs 加密模块,hash.update() 是否将所有输入存储在内存中
【发布时间】:2019-05-10 05:03:39
【问题描述】:

我有一个 API 路由代理文件从浏览器/客户端上传到 AWS S3。

此 API 路由会在文件上传时尝试对文件进行流式传输,以避免在服务器内存中缓冲文件的全部内容。

但是,该路由还尝试计算文件正文的 MD5 校验和。当文件的每个部分都被分块时,hash.update() 方法会被调用。

http://nodejs.org/api/crypto.html#crypto_hash_update_data_input_encoding

var crypto = require('crypto');
var hash = crypto.createHash('md5');
function write (chunk) {
  // invoked many times as file is uploaded
  hash.update(chunk);
}
function done() {
  // will hash buffer all chunks in memory at this point?
  hash.digest('hex');
}

Hash 实例是否会缓冲文件的所有内容以执行哈希计算(从而破坏避免在内存中缓冲整个文件内容的目标)?或者可以增量计算 MD5 哈希,而无需整个输入可用于执行计算?

【问题讨论】:

    标签: node.js hash stream cryptography md5


    【解决方案1】:

    MD5 和其他一些哈希函数基于Merkle–Damgård construction。它支持数据的增量/渐进/流式散列。在将数据转换为内部状态(具有固​​定大小)之后,执行最后一个最终确定步骤,通过填充和处理最后一个块来生成最终哈希,然后简单地返回最终状态。

    这可能也是为什么许多散列库函数被设计成带有更新和完成步骤的原因。

    回答您的问题:不,文件内容不保存在缓冲区中,而是转换为固定大小的内部状态。

    【讨论】:

      【解决方案2】:

      所有现代加密哈希函数的创建方式都可以增量更新。

      为了允许增量更新,消息的输入数据首先以块的形式排列。这些块按顺序处理。为此,实现通常会在内部缓冲输入,直到它有一个完整的块,然后使用所谓的 压缩函数。初始状态通常简单地由预先确定的常数值组成。在调用digest 期间,最后一个块被填充——通常是位填充和处理字节数量的编码——并计算最终状态;这可能需要一个没有任何消息数据的附加块。可能会执行最终操作并最终返回结果哈希值。

      对于MD5,使用Merkle–Damgård construction。这种通用结构也用于 SHA-1 和 SHA-2。 SHA-2 是基于 SHA-256 (SHA-224) 和 SHA-512 (SHA-384、SHA-512/224 和 SHA-512/256) 算法的哈希家族。特别是 MD5 使用 512 位的块大小和 128 位的内部状态。最后一个块的内部状态(包括填充)直接输出,无需对 MD5、SHA-1、SHA-256 和 SHA-512 进行任何后处理。

      Keccak 已被选为 SHA-3。它是基于海绵的结构,具有特定的压缩功能。它不是 Merkle–Damgård 哈希 - 这是 为什么 它被选为 SHA-3 的一个重要原因。它仍然具有 Merkle–Damgård 哈希的所有更新属性,并且已设计 与 SHA-2 兼容。它像前面提到的哈希一样拆分和缓冲块,但它具有更大的内部状态并对输出执行最终操作,因此可以说更安全。

      因此,当您使用现代散列结构(例如 MD5)时,您会在不知不觉中执行额外的缓冲。幸运的是,512 位 + 128 位的状态大小的单个块的缓冲不太可能使您耗尽内存。在计算最终的哈希值之前,哈希实现当然不需要缓冲整个消息。


      注意事项:

      • MD5 和 SHA-1 被认为是不安全的 w.r.t.抗碰撞性,最好不要再使用它们,尤其是在验证内容时;
      • “压缩函数”是一种特定的加密概念;它不是 LSZIP 或类似的东西;
      • 可能有专门的、理论上的散列以不同的方式执行计算值 - 从理论上讲,不需要将输入消息分成块并按顺序对块进行操作。不用担心,这些不太可能在您正在使用的库中;
      • 同样,实现可能会决定一次缓冲更多块,但幸运的是,这种情况也极为罕见。通常只使用一个块作为缓冲区 - 在某些情况下,缓冲几个块可能会更高效;
      • 出于效率原因,一些低级实现可能需要您自己提供块。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-06-22
        • 2015-06-15
        • 1970-01-01
        • 2022-10-19
        • 2014-06-06
        • 2021-04-15
        • 1970-01-01
        相关资源
        最近更新 更多