【问题标题】:Node.js encrypts large file using AESNode.js 使用 AES 加密大文件
【发布时间】:2015-02-05 09:23:07
【问题描述】:

我尝试使用以下代码加密 1 GB 的文件。但是 Node.js 因“致命错误:JS 分配失败 - 进程内存不足”而中止。我该如何处理?

var fs = require('fs');
var crypto = require('crypto');
var key = "14189dc35ae35e75ff31d7502e245cd9bc7803838fbfd5c773cdcd79b8a28bbd";
var cipher = crypto.createCipher('aes-256-cbc', key);
var file_cipher = "";
var f = fs.ReadStream("test.txt");
f.on('data', function(d) {
    file_cipher = file_cipher + cipher.update(d, 'utf8', 'hex');
});
f.on('end', function() {  
    file_cipher = file_cipher + cipher.final('hex');
});   

【问题讨论】:

    标签: javascript node.js encryption


    【解决方案1】:

    您可以将加密文件写回磁盘,而不是将整个文件缓存在内存中:

    var fs = require('fs');
    var crypto = require('crypto');
    
    var key = '14189dc35ae35e75ff31d7502e245cd9bc7803838fbfd5c773cdcd79b8a28bbd';
    var cipher = crypto.createCipher('aes-256-cbc', key);
    var input = fs.createReadStream('test.txt');
    var output = fs.createWriteStream('test.txt.enc');
    
    input.pipe(cipher).pipe(output);
    
    output.on('finish', function() {
      console.log('Encrypted file written to disk!');
    });
    

    【讨论】:

    • 谢谢!顺便说一句,我怎么知道加密何时完成?
    • 你可以在output上监听finish事件。
    • 同一个文件如何解密?
    • 您可以使用crypto.createDecipher 而不是crypto.createCipher 以完全相同的方式解密。
    【解决方案2】:

    不推荐使用没有初始化向量的crypto.createCipher(),因为NodeJS v10.0.0 改用crypto.createCipheriv()

    您还可以使用stream.pipeline() 而不是pipe 方法对流进行管道传输,然后对其进行promisify(这样代码将很容易适应promise-like 和async/await 流)。

    const {createReadStream, createWriteStream} = require('fs');
    const {pipeline} = require('stream');
    const {randomBytes, createCipheriv} = require('crypto');
    const {promisify} = require('util');
    
    const key = randomBytes(32); // ... replace with your key
    const iv = randomBytes(16); // ... replace with your initialization vector
    
    promisify(pipeline)(
            createReadStream('./text.txt'),
            createCipheriv('aes-256-cbc', key, iv),
            createWriteStream('./text.txt.enc')
    )
    .then(() => {/* ... */})
    .catch(err => {/* ... */});
    

    使用 NodeJS 15+ 您可以简化它(跳过 promisify 部分)

    const {createReadStream, createWriteStream} = require('fs');
    const {pipeline} = require('stream/promises');
    const {randomBytes, createCipheriv} = require('crypto');
    
    const key = randomBytes(32); // ... replace with your key
    const iv = randomBytes(16); // ... replace with your initialization vector
    
    pipeline(
      createReadStream('./text.txt'),
      createCipheriv('aes-256-cbc', key, iv),
      createWriteStream('./text.txt.enc')
    )
    .then(() => {/* ... */})
    .catch(err => {/* ... */});
    

    【讨论】:

    • 解密文件Error: Unsupported state or unable to authenticate data时出现此错误@
    • @PrathameshMore 如果没有看到文件解密的代码,很难说问题出在哪里。请注意,您应该将密钥和初始化向量存储在某个地方(例如文件),randomBytes 仅用于演示目的。
    • Stream Promises API 从 Node 版本 15 (docu) 开始可用
    【解决方案3】:

    我会简单地使用 Fileger 来完成它。它是一个基于 Promise 的包,是 NodeJS 文件系统的干净替代品。

    const fileger = require("fileger")
    const file = new fileger.File("./your-file-path.txt");
    
    file.encrypt("your-password") // this will encrypt the file
       .then(() => {
          file.decrypt("your-password") // this will decrypt the file
       })
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-08-03
      • 2016-03-30
      • 2015-02-23
      • 2021-05-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多