代码之家  ›  专栏  ›  技术社区  ›  Jacob Marshall

在Forge.js中解密CryptoJS AES数据(使用密码)

  •  1
  • Jacob Marshall  · 技术社区  · 9 年前

    所以我有一段代码,用密码对字符串进行加密。它使用CryptoJS AES加密功能( CryptoJS.AES.encrypt )看起来像这样。。。

    CryptoJS.AES.encrypt(data, password).toString();
    

    展望未来,我不想使用CryptoJS,因为它已被正式弃用/未被维护,我反而想使用Forge.js。我试着通读《锻造》。js文档在GitHub上寻找解决方案,但还没有找到任何使用密码而不是手动创建密钥&四、

    我看了一下CryptoJS档案 https://code.google.com/archive/p/crypto-js/ 似乎如果 encrypt 函数被传递一个字符串作为第二个参数(key),它被用作派生密钥和IV的密码短语。

    似乎base64解码结果得到的字符串以 Salted__ 然后是逗号,然后是二进制文本的加密块,我甚至不确定如何将“salt”传递给Forge。

    我该如何使用Forge解密这一数据块呢。仅js?

    1 回复  |  直到 9 年前
        1
  •  5
  •   Artjom B.    7 年前

    CryptoJS支持OpenSSL的EVP_BytesToKey函数,该函数使用一轮MD5从新生成的salt和密码中派生密钥和IV forge documentation page :

    在节点中使用forge。js来匹配openssl的“enc”命令行工具 ( 注: OpenSSL“enc”使用带有自定义密钥的非标准文件格式 派生函数和固定迭代计数1 考虑不如OpenPGP/GnuPG等替代方案安全):

    var forge = require('node-forge');
    var fs = require('fs');
    
    // openssl enc -des3 -in input.txt -out input.enc
    function encrypt(password) {
      var input = fs.readFileSync('input.txt', {encoding: 'binary'});
    
      // 3DES key and IV sizes
      var keySize = 24;
      var ivSize = 8;
    
      // get derived bytes
      // Notes:
      // 1. If using an alternative hash (eg: "-md sha1") pass
      //   "forge.md.sha1.create()" as the final parameter.
      // 2. If using "-nosalt", set salt to null.
      var salt = forge.random.getBytesSync(8);
      // var md = forge.md.sha1.create(); // "-md sha1"
      var derivedBytes = forge.pbe.opensslDeriveBytes(
        password, salt, keySize + ivSize/*, md*/);
      var buffer = forge.util.createBuffer(derivedBytes);
      var key = buffer.getBytes(keySize);
      var iv = buffer.getBytes(ivSize);
    
      var cipher = forge.cipher.createCipher('3DES-CBC', key);
      cipher.start({iv: iv});
      cipher.update(forge.util.createBuffer(input, 'binary'));
      cipher.finish();
    
      var output = forge.util.createBuffer();
    
      // if using a salt, prepend this to the output:
      if(salt !== null) {
        output.putBytes('Salted__'); // (add to match openssl tool output)
        output.putBytes(salt);
      }
      output.putBuffer(cipher.output);
    
      fs.writeFileSync('input.enc', output.getBytes(), {encoding: 'binary'});
    }
    
    // openssl enc -d -des3 -in input.enc -out input.dec.txt
    function decrypt(password) {
      var input = fs.readFileSync('input.enc', {encoding: 'binary'});
    
      // parse salt from input
      input = forge.util.createBuffer(input, 'binary');
      // skip "Salted__" (if known to be present)
      input.getBytes('Salted__'.length);
      // read 8-byte salt
      var salt = input.getBytes(8);
    
      // Note: if using "-nosalt", skip above parsing and use
      // var salt = null;
    
      // 3DES key and IV sizes
      var keySize = 24;
      var ivSize = 8;
    
      var derivedBytes = forge.pbe.opensslDeriveBytes(
        password, salt, keySize + ivSize);
      var buffer = forge.util.createBuffer(derivedBytes);
      var key = buffer.getBytes(keySize);
      var iv = buffer.getBytes(ivSize);
    
      var decipher = forge.cipher.createDecipher('3DES-CBC', key);
      decipher.start({iv: iv});
      decipher.update(input);
      var result = decipher.finish(); // check 'result' for true/false
    
      fs.writeFileSync(
        'input.dec.txt', decipher.output.getBytes(), {encoding: 'binary'});
    }
    

    此示例针对三重DES显示,但它对AES的工作方式相同。你只需要改变 ivSize 至16。