无法正确加密文件上传流

问题描述 投票:0回答:1

我正在尝试加密和解密上传到运行

express
的 Node.JS 服务器的文件。文件从 HTML 表单上传并发送到加密传入文件流的函数,将其保存到服务器上的文件中。要下载文件,将从服务器检索加密文件并解密,然后将其发送回客户端。

我能够在服务器上正确地将文件保存为纯文本,无需加密,并通过直接将响应管道传输到

readStream
writeStream
(参见代码)来下载它,而不会出现任何损坏。然而,当我传入我的加密函数时,它输出的文件部分损坏。

损坏的示例:

========= input.txt ============
Testing Document!

This is just a testing document!
=================================

========= decrypted.txt =========
@h±²k5øcZxÁ·õ7ÌwBox!

5øcis is just a testing document!
=================================

NodeJS 路线:

app.post('/upload', (req, res) => {
        const busboyInstance = busboy({ headers: req.headers });
      
        // Create a write stream to save the uploaded file
        let fileName;
        let writeStream;
      
        busboyInstance.on('file', (fieldname, file, filename) => {
          fileName = 'encrypted_file.txt'; // Modify the filename as needed
          const filePath = __dirname + '/' + fileName;
          writeStream = fs.createWriteStream(filePath);
      
          // Perform file encryption asynchronously. THIS PARTIALLY CORRUPTS THE FILE
          /*
          aesEncryptFileStream(file, writeStream, 'TESTESTESTESTESTESTESTESTESTESTE')
            .then(() => {
              file.resume(); // Consume the remaining stream
            })
            .catch((error) => {
              console.error('Encryption error:', error);
              res.status(500).send('Encryption error');
            });*/

            //For debugging purposes we will just copy the file. THIS WORKS FINE
            file.pipe(writeStream);

        });
      
        busboyInstance.on('finish', () => {
          res.end('Upload complete');
          console.log('File upload complete');
        });
      
        req.pipe(busboyInstance);
      });
      
      // Set up a route for handling file decryption and download
      app.get('/download', async (req, res) => {
        try {
          // Create a read stream from the encrypted file
          const fileName = 'encrypted_file.txt'; // Modify the filename as needed
          const filePath = __dirname + '/' + fileName;
          const readStream = fs.createReadStream(filePath);
      
          // Perform file decryption asynchronously. THIS PARTIALLY CORRUPTS THE FILE
          //await aesDecryptFile(readStream, res, "TESTESTESTESTESTESTESTESTESTESTE");
      
          //For debugging purposes we will just copy the file. THIS WORKS FINE
            readStream.pipe(res);
            
          console.log('File download complete');
        } catch (error) {
          console.error('Error:', error);
          res.status(500).send('Server error');
        }
      });

密码学功能:

async function aesEncryptFileStream(inputStream, outputStream, secret) {
    const algorithm = 'aes-256-cbc';
    const iv = crypto.randomBytes(16); // Initialization vector.

    const cipher = crypto.createCipheriv(algorithm, secret, iv);

    return new Promise((resolve, reject) => {
        inputStream.pipe(cipher).pipe(outputStream);

        inputStream.on('end', () => {
            resolve();
        });

        inputStream.on('error', (err) => {
            reject(err);
        });
    });
}

async function aesDecryptFile(inputStream, outputStream, secret) {
    const algorithm = 'aes-256-cbc';
    const iv = crypto.randomBytes(16); // Initialization vector.

    const decipher = crypto.createDecipheriv(algorithm, Buffer.from(secret), iv);

    return new Promise((resolve, reject) => {
        inputStream.pipe(decipher).pipe(outputStream);

        inputStream.on('end', () => {
            resolve();
        });

        inputStream.on('error', (err) => {
            reject(err);
        });
    });
}

我最初认为这是一个标头问题,但经过进一步调查并尝试不同的标头组合,我仍然看到使用

/download
下载文件时返回部分损坏的数据。尝试删除加密功能并直接管道传输文件工作正常,所以我认为这是加密/解密功能的一些问题。

有谁知道如何解决这个问题吗?

node.js encryption aes
1个回答
0
投票

加密和解密特定消息时,IV 需要相同。您需要将 IV 与加密数据一起存储,然后在再次解密时使用它。

© www.soinside.com 2019 - 2024. All rights reserved.