简体   繁体   English

节点crypto与crypto-js加解密的兼容性

[英]Compatibility between node crypto and crypto-js encryption and decryption

How do I properly encrypt/decrypt data between node.js with the crypto module (server side) and crypto-js (client side, react-native)?如何使用crypto模块(服务器端)和crypto-js(客户端,react-native)正确加密/解密node.js之间的数据?

NOTE: I'm using cryptojs in a react-native project, thus I can't use crypto on client.注意:我在 react-native 项目中使用了 cryptojs,因此我不能在客户端上使用加密。 replacing crypto server side is not an option for me.更换加密服务器端对我来说不是一个选择。

Server-side code:服务端代码:

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

Client-side code客户端代码

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

Your "password" (it is used as a key instead of a password) has two different encodings on client-side and server-side.您的“密码”(它用作密钥而不是密码)在客户端和服务器端有两种不同的编码。 On the client, you're parsing it as Hex, but on the server, you're passing it as a binary string, which is used as-is.在客户端,您将其解析为十六进制,但在服务器上,您将其作为二进制字符串传递,按原样使用。

You either need parse it on the server (now it is AES-128 and not AES-256):您要么需要在服务器上解析它(现在它是 AES-128 而不是 AES-256):

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

Or change the encoding on the client (from AES-128 to AES-256):或者更改客户端上的编码(从 AES-128 到 AES-256):

pass: CryptoJS.enc.Utf8.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 "";
    }
  }

You still have security problems:您仍然有安全问题:

  • The IV has to be randomly chosen for every encryption under the same key to achieve semantic security.必须为相同密钥下的每个加密随机选择 IV,以实现语义安全。 It doesn't have to be secret, so you can simply send it along with the ciphertext.它不必是秘密的,因此您可以简单地将其与密文一起发送。 It's common to prepend it to the ciphertext and slice it off before decryption.通常将其添加到密文并在解密之前将其切片。

  • It is better to authenticate your ciphertexts so that attacks like a padding oracle attack are not possible.最好验证您的密文,以便像填充预言机攻击这样的攻击是不可能的。 This can be done with authenticated modes like GCM or EAX, or with an encrypt-then-MAC scheme with a strong MAC like HMAC-SHA256, which CryptoJS provides.这可以通过像 GCM 或 EAX 这样的认证模式来完成,或者使用具有强 MAC 的加密然后 MAC方案,如 CryptoJS 提供的 HMAC-SHA256。

Here is the example node js crypto ( https://nodejs.org/api/crypto.html ) and related encryption and decryption in crypto.js ( https://github.com/brix/crypto-js ).下面是示例 node js crypto ( https://nodejs.org/api/crypto.html ) 和 crypto.js ( https://github.com/brix/crypto-js ) 中的相关加密和解密。

Gist - https://gist.github.com/yoavniran/c78a0991e0152b306c25要点 - 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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM