簡體   English   中英

節點crypto與crypto-js加解密的兼容性

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

如何使用crypto模塊(服務器端)和crypto-js(客戶端,react-native)正確加密/解密node.js之間的數據?

注意:我在 react-native 項目中使用了 cryptojs,因此我不能在客戶端上使用加密。 更換加密服務器端對我來說不是一個選擇。

服務端代碼:

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

您的“密碼”(它用作密鑰而不是密碼)在客戶端和服務器端有兩種不同的編碼。 在客戶端,您將其解析為十六進制,但在服務器上,您將其作為二進制字符串傳遞,按原樣使用。

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

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

或者更改客戶端上的編碼(從 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 "";
    }
  }

您仍然有安全問題:

  • 必須為相同密鑰下的每個加密隨機選擇 IV,以實現語義安全。 它不必是秘密的,因此您可以簡單地將其與密文一起發送。 通常將其添加到密文並在解密之前將其切片。

  • 最好驗證您的密文,以便像填充預言機攻擊這樣的攻擊是不可能的。 這可以通過像 GCM 或 EAX 這樣的認證模式來完成,或者使用具有強 MAC 的加密然后 MAC方案,如 CryptoJS 提供的 HMAC-SHA256。

下面是示例 node js crypto ( 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);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM