You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Electron+React的桌面应用文件加解密实现咨询(Node.js Crypto流)

基于Electron + React的多格式文件流加密/解密实现

看起来你已经选对了方向——用Node.js的crypto和fs流处理文件,比一次性把文件读进内存高效太多,尤其适合桌面应用里的txt、pdf、jpg、png这类不同格式的文件(流处理只认二进制数据,完全不挑文件类型)。不过你的现有代码还有几个小问题要修正,比如file_path没作为参数传入、createCipher已经被官方标记为弃用(安全性也不足),我来帮你完善整个加解密流程:

加密函数(安全优化版)

我把弃用的createCipher换成了更安全的createCipheriv(createCipher的密钥派生方式存在安全隐患),同时补全了参数传递、流的安全处理和错误捕获:

const crypto = require('crypto');
const fs = require('fs');
const { pipeline } = require('stream/promises'); // 用Promise版管道,适配async/await语法

export async function encryptFile(filePath, passphrase, outputPath) {
  // 从用户密码生成符合AES-192要求的密钥和随机IV(密钥24字节,IV16字节)
  const salt = crypto.randomBytes(16);
  const key = crypto.scryptSync(passphrase, salt, 24);
  const iv = crypto.randomBytes(16);

  const cipher = crypto.createCipheriv('aes-192-cbc', key, iv);

  try {
    // 用pipeline自动处理流的拼接、错误和关闭,避免内存泄漏
    await pipeline(
      fs.createReadStream(filePath),
      cipher,
      fs.createWriteStream(outputPath, { flags: 'w' })
    );

    // 把salt和IV写入加密文件的开头,解密时必须用到这两个值
    const outputFile = fs.openSync(outputPath, 'r+');
    fs.writeSync(outputFile, salt, 0, salt.length, 0);
    fs.writeSync(outputFile, iv, 0, iv.length, salt.length);
    fs.closeSync(outputFile);

    return true; // 加密成功返回标记
  } catch (err) {
    console.error('加密过程出错:', err);
    // 这里可以结合Electron的dialog组件给用户弹出错误提示
    return false;
  }
}

对应的解密函数

解密时需要读取加密文件开头的salt和IV,再用相同的密码生成密钥:

export async function decryptFile(encryptedFilePath, passphrase, outputPath) {
  // 先读取文件开头的salt和IV
  const fileBuffer = fs.readFileSync(encryptedFilePath, { encoding: null });
  const salt = fileBuffer.slice(0, 16);
  const iv = fileBuffer.slice(16, 32);

  // 用相同的密码和salt生成密钥
  const key = crypto.scryptSync(passphrase, salt, 24);
  const decipher = crypto.createDecipheriv('aes-192-cbc', key, iv);

  try {
    // 从第32字节开始读取加密数据(跳过前面的salt和IV)
    const inputStream = fs.createReadStream(encryptedFilePath, { start: 32 });
    await pipeline(
      inputStream,
      decipher,
      fs.createWriteStream(outputPath, { flags: 'w' })
    );

    return true; // 解密成功返回标记
  } catch (err) {
    console.error('解密过程出错:', err);
    return false;
  }
}

在Electron + React中使用的关键细节

  • 获取文件路径:
    如果是通过前端File API拿到的文件,在Electron渲染进程开启nodeIntegration的情况下,可以直接通过file.path获取本地路径;也可以用Electron的弹窗让用户选择文件:
    // 渲染进程中(需开启remote模块或通过IPC调用主进程)
    const { dialog } = require('electron').remote;
    
    async function handleEncrypt() {
      const selectResult = await dialog.showOpenDialog({
        filters: [{ name: '支持的文件', extensions: ['txt', 'pdf', 'jpg', 'png'] }]
      });
      if (!selectResult.canceled && selectResult.filePaths.length > 0) {
        const inputPath = selectResult.filePaths[0];
        const outputPath = `${inputPath}.encrypted`; // 给加密文件加后缀区分
        const userPassphrase = '这里替换为用户输入的密码'; // 建议用React表单收集用户密码
        const success = await encryptFile(inputPath, userPassphrase, outputPath);
        if (success) dialog.showMessageBox({ message: '加密完成!' });
      }
    }
    
  • 权限与打包:打包Electron应用时,确保不要限制文件系统的读写权限,否则会无法操作文件。
  • 密码安全:绝对不要硬编码密码,一定要让用户输入;如果需要记住密码,可以用Electron的safeStorage模块加密存储。

内容的提问来源于stack exchange,提问作者Manish

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 03:25:59