Node.js使用AES加密大文件

ymzxtsji  于 2023-03-29  发布在  Node.js
关注(0)|答案(3)|浏览(192)

我尝试使用以下代码加密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');
});
xzv2uavs

xzv2uavs1#

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

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!');
});
u3r8eeie

u3r8eeie2#

不推荐使用没有初始化向量的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 => {/* ... */});
lskq00tm

lskq00tm3#

我会简单地使用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
   })

相关问题