【问题标题】:Compatibility between node crypto and crypto-js encryption and decryption节点crypto与crypto-js加解密的兼容性
【发布时间】:2016-02-21 05:28:15
【问题描述】:

如何正确加密/解密 node.js 与 crypto 模块(服务器端)和 crypto-js(客户端,react-native)之间的数据?

注意: 我在 react-native 项目中使用 cryptojs,因此我不能在客户端上使用 crypto。 替换加密服务器端不是我的选择。

服务器端代码:

var Crypto = require("crypto");

var Cipher = {
  pass: "0123456789abcdef0123456789abcdef",
  iv: "0123456789abcdef",
  encript: function (msg) {
    try {
      var cipher = Crypto.createCipheriv("aes-256-cbc", this.pass, this.iv);
      var hash = cipher.update(msg, 'utf8', "hex");
      var hex = hash + cipher.final("hex");
      return hex;
    } catch (err) {
      console.error(err);
      return "";
    }
  },
  decript: function (hex){
    try {
      var decipher = Crypto.createDecipheriv("aes-256-cbc", this.pass, this.iv);
      var dec = decipher.update(hex, "hex", 'utf8');
      return dec + decipher.final('utf8');
    } catch (err) {
      console.error(err);
      return "";
    }
  }
}
Cipher.encript("i have an apple"); // 577267026f88f82ea286baf6bf089acb
Cipher.decript("577267026f88f82ea286baf6bf089acb"); // i have an apple

客户端代码

var CryptoJS = require("crypto-js");
var Cipher = {
  pass: CryptoJS.enc.Hex.parse("0123456789abcdef0123456789abcdef"),
  iv: CryptoJS.enc.Hex.parse("0123456789abcdef"),
  encript: function (msg) {
    try {
      var options = { mode: CryptoJS.mode.CBC, iv: this.iv};
      var json = CryptoJS.AES.encrypt(msg, this.pass, options);
      return json.ciphertext.toString(CryptoJS.enc.Hex);
    } catch (err) {
      console.error(err);
      return "";
    }
  },
  decript: function (hex){
    try {
      // ???????????????????????????????????
      // ???????????????????????????????????

    } catch (err) {
      console.error(err);
      return "";
    }
  }
}

Cipher.encript("i have an apple"); // 405552d9a77ea9e29442057d27cd7aee
Cipher.decript(?????);  // I have no Idea

【问题讨论】:

    标签: javascript node.js encryption cryptojs node-crypto


    【解决方案1】:

    您的“密码”(它用作密钥而不是密码)在客户端和服务器端有两种不同的编码。在客户端,您将其解析为十六进制,但在服务器上,您将其作为二进制字符串传递,按原样使用。

    您要么需要在服务器上解析它(现在它是 AES-128 而不是 AES-256):

    pass: new Buffer("0123456789abcdef0123456789abcdef", "hex"),
    

    或者更改客户端上的编码(从 AES-128 到 AES-256):

    pass: CryptoJS.enc.<b>Utf8</b>.parse("0123456789abcdef0123456789abcdef"),

      encript: function (msg) {
        try {
          var options = { mode: CryptoJS.mode.CBC, iv: this.iv};
          var json = CryptoJS.AES.encrypt(msg, this.pass, options);
          return json.ciphertext.toString(CryptoJS.enc.Hex);
        } catch (err) {
          console.error(err);
          return "";
        }
      },
      decript: function (hex){
        try {
          var options = { mode: CryptoJS.mode.CBC, iv: this.iv};
          var json = CryptoJS.AES.decrypt({
            ciphertext: CryptoJS.enc.Hex.parse(hex)
          }, this.pass, options);
          return json.toString(CryptoJS.enc.Utf8);
        } catch (err) {
          console.error(err);
          return "";
        }
      }
    

    您仍有安全问题:

    • 必须为相同密钥下的每个加密随机选择 IV 以实现语义安全。它不必是秘密的,因此您可以简单地将其与密文一起发送。通常将其添加到密文之前并在解密之前将其切掉。

    • 最好对您的密文进行身份验证,这样就不会发生像padding oracle attack 这样的攻击。这可以通过 GCM 或 EAX 等经过身份验证的模式来完成,或者通过 CryptoJS 提供的具有强 MAC(如 HMAC-SHA256)的encrypt-then-MAC 方案来完成。

    【讨论】:

    • 谢谢!!,那行得通!... 生病发送带有密文的 iv。
    【解决方案2】:

    这里是示例节点 js 加密(https://nodejs.org/api/crypto.html)以及 crypto.js(https://github.com/brix/crypto-js)中的相关加密和解密。

    要点 - https://gist.github.com/yoavniran/c78a0991e0152b306c25

    //CryptoJS example
    var key = "H98zM6i/55yNJfkFsbu0HrzlFo17FtR9";
    var iv = key.slice(0, 16);
    //Create Key
    key = CryptoJS.enc.Utf8.parse(key);
    //Get Iv
    iv = CryptoJS.enc.Utf8.parse(iv);
    var encrypted = CryptoJS.AES.encrypt("testtest", key,{ iv: iv});
    //Encrypt string
    var encrypted_data = encrypted.toString();
    console.log(encrypted_data)
    var decrypted = CryptoJS.AES.decrypt(encrypted_data, key,{ iv: iv});
    var decrypted_data = decrypted.toString(CryptoJS.enc.Utf8)
    console.log(decrypted_data)
    
    
    ////Node JS example
      var key = "H98zM6i/55yNJfkFsbu0HrzlFo17FtR9";
      var iv = key.slice(0, 16);
      function encryptText(cipher_alg, key, iv, text, encoding) {
          var cipher = crypto.createCipheriv(cipher_alg, key, iv);
          encoding = encoding || "binary";
          var result = cipher.update(text,'utf8',  encoding);
          result += cipher.final(encoding);
          return result;
      }
      function decryptText(cipher_alg, key, iv, text, encoding) {
          var decipher = crypto.createDecipheriv(cipher_alg, key, iv);
          encoding = encoding || "binary";
          var result = decipher.update(text, encoding);
          result += decipher.final();
          return result;
      }
    var encText = encryptText('aes256', key, iv, "testtest1", "base64");
    console.log("encrypted text = " + encText);
    var decText = decryptText('aes256', key, iv, encText, "base64");
    console.log("decrypted text = " + decText);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-12
      • 1970-01-01
      • 1970-01-01
      • 2023-03-17
      • 2017-08-06
      • 2023-03-17
      相关资源
      最近更新 更多