node crypto和crypto-js加解密的兼容性
Compatibility between node crypto and crypto-js encryption and decryption
如何使用加密模块(服务器端)和 crypto-js(客户端,react-native)在 node.js 之间正确地 encrypt/decrypt 数据?
注意:
我在 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
您的"password"(它用作密钥而不是密码)在客户端和服务器端有两种不同的编码。在客户端,您将其解析为十六进制,但在服务器上,您将其作为二进制字符串传递,按原样使用。
您需要在服务器上解析它(现在是 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,以实现语义安全。它不必是秘密的,因此您只需将它与密文一起发送即可。通常将其添加到密文中并在解密之前将其切掉。
最好对您的密文进行身份验证,以便像 CryptoJS 提供的具有强 MAC 的 MAC 方案一样进行攻击。
这是示例节点 js 加密 (https://nodejs.org/api/crypto.html) and related encryption and decryption in 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);
如何使用加密模块(服务器端)和 crypto-js(客户端,react-native)在 node.js 之间正确地 encrypt/decrypt 数据?
注意: 我在 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
您的"password"(它用作密钥而不是密码)在客户端和服务器端有两种不同的编码。在客户端,您将其解析为十六进制,但在服务器上,您将其作为二进制字符串传递,按原样使用。
您需要在服务器上解析它(现在是 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,以实现语义安全。它不必是秘密的,因此您只需将它与密文一起发送即可。通常将其添加到密文中并在解密之前将其切掉。
最好对您的密文进行身份验证,以便像 CryptoJS 提供的具有强 MAC 的 MAC 方案一样进行攻击。
这是示例节点 js 加密 (https://nodejs.org/api/crypto.html) and related encryption and decryption in 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);