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

如何使用CryptoJS通过AES算法实现文件加密?

将RC4加密迁移到AES的解决方案

AES是块加密算法,和流加密的RC4调用逻辑完全不同,直接替换方法名肯定无法运行。核心差异在于:

  • AES需要初始化向量(IV),解密时必须和加密时使用的IV完全一致
  • AES要求密钥长度符合算法标准(128/192/256位),且需指定加密模式(默认CBC)
  • CryptoJS的AES加密需要明确处理IV的存储与读取,不能像RC4那样直接传入明文和密钥

以下是修改后的完整代码,替换原RC4相关逻辑:

<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js" integrity="sha512-E8QSvWZ0eCLGk4km3hxSsNmGWbLtSCSUcewDQPQWZF6pEU8GlT8a5fF32wOl1i8ftdMhssTrF/OhyGWwonTcXA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

<div>
  <h1>encrypt/decrypt file</h1>
  <ol>
    <li>Set password</li>
    <li>Pick a file</li>
    <li>Download decrypted/encrypted file</li>
  </ol>
  <div>
    <input type="text" id="pass" placeholder="pass">
    <button id="encrypt">encrypt file</button>
    <button id="decrypt">decrypt file</button>
    <button id="test">test</button>
  </div>
</div>

<script>
  // 保留原辅助函数不变
  const download = (data, filename, type) => {
    const file = new Blob([data], {
      type: type
    });
    const a = document.createElement('a');
    const url = URL.createObjectURL(file);

    a.href = url;
    a.download = filename;
    document.body.appendChild(a);

    a.click();

    setTimeout(function() {
      document.body.removeChild(a);
      window.URL.revokeObjectURL(url);
    }, 0);
  };
  const pickAFile = (getText = true) => {
    return new Promise((resolve, reject) => {
      const input = document.createElement('input');
      input.type = 'file';
      input.onchange = (e) => {
        const file = e.target.files[0];
        const reader = new FileReader();
        if (!getText) {
          resolve(file);
        } else {
          reader.onload = (e) => resolve(e.target.result);
          reader.onerror = (e) => reject(e);
          reader.readAsText(file);
        }
      };
      input.click();
    });
  };
  const convertWordArrayToUint8Array = (wordArray) => {
    const arrayOfWords = wordArray.hasOwnProperty('words') ? wordArray.words : [];

    const length = wordArray.hasOwnProperty('sigBytes') ?
      wordArray.sigBytes :
      arrayOfWords.length * 4;

    const uInt8Array = new Uint8Array(length);
    let index = 0;
    let word;
    let i;

    for (i = 0; i < length; i++) {
      word = arrayOfWords[i];
      uInt8Array[index++] = word >> 24;
      uInt8Array[index++] = (word >> 16) & 0xff;
      uInt8Array[index++] = (word >> 8) & 0xff;
      uInt8Array[index++] = word & 0xff;
    }
    return uInt8Array;
  };
  // /辅助函数结束

  function app() {
    const passNode = document.querySelector('input#pass');
    const encryptNode = document.querySelector('#encrypt');
    const decryptNode = document.querySelector('#decrypt');

    encryptNode.addEventListener('click', () => {
      if (!passNode.value) return alert('Password input is empty! Aborting.');
      // 用SHA3生成256位密钥,适配AES-256标准
      const key = CryptoJS.SHA3(passNode.value);
      // 生成16字节随机IV(AES块大小固定为16字节)
      const iv = CryptoJS.lib.WordArray.random(16);
      
      pickAFile(false).then((file) => {
        const reader = new FileReader();

        reader.onload = (e) => {
          const wordArray = CryptoJS.lib.WordArray.create(e.target.result);
          // AES加密:指定密钥、IV,使用默认CBC模式
          const encrypted = CryptoJS.AES.encrypt(wordArray, key, { iv: iv });
          // 将IV与密文拼接为"IV:密文"格式(均为Base64编码),方便解密时拆分
          const encryptedData = `${iv.toString(CryptoJS.enc.Base64)}:${encrypted.ciphertext.toString(CryptoJS.enc.Base64)}`;
          download(encryptedData, `encrypted-${file.name}`, 'text/plain');
        };

        reader.readAsArrayBuffer(file);
      });
    });

    decryptNode.addEventListener('click', () => {
      if (!passNode.value) return alert('Password input is empty! Aborting.');
      const key = CryptoJS.SHA3(passNode.value);
      
      pickAFile(true).then((encryptedText) => {
        try {
          // 拆分IV与密文
          const [ivBase64, ciphertextBase64] = encryptedText.split(':');
          const iv = CryptoJS.enc.Base64.parse(ivBase64);
          const ciphertext = CryptoJS.enc.Base64.parse(ciphertextBase64);
          
          // AES解密:传入密文对象、密钥和IV
          const decrypted = CryptoJS.AES.decrypt(
            { ciphertext: ciphertext },
            key,
            { iv: iv }
          );
          const typedArray = convertWordArrayToUint8Array(decrypted);
          download(typedArray, `decrypted-${file.name}`, file.type);
        } catch (error) {
          console.log('wrong password or invalid encrypted data!');
        }
      });
    });
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', app);
  } else {
    app();
  }
</script>

关键改动说明

  1. IV处理:每次加密生成随机IV,并与密文一起存储,解密时必须使用相同IV才能正确还原数据
  2. 密钥适配:原代码用SHA3生成的32字节(256位)密钥刚好符合AES-256的要求,无需修改密钥生成逻辑
  3. 加密结果存储:将IV和密文用冒号分隔保存为Base64字符串,确保解密时能准确拆分出所需参数
  4. 解密逻辑调整:从加密文件中拆分IV和密文后,再传入AES解密方法完成解密

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 16:16:12