在浏览器中在Node和CryptoJS之间使用AES加密时出现问题 [英] Problems when using AES crypto between Node and CryptoJS in browser

查看:3362
本文介绍了在浏览器中在Node和CryptoJS之间使用AES加密时出现问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要使用Node加密字串,并使用CryptoJS在浏览器中解密字串。



加密:

  var crypto = require('crypto'); 

function encrypt(txt,cryptkey){
var cipher = crypto.createCipher('aes-256-cbc',cryptkey);
var crypted = cipher.update(txt,'utf8','hex');
crypted + = cipher.final('hex');
return crypted;
}

encrypt('1','key'); // 83684beb6c8cf063caf45cb7fad04a50

包含:

 < script src =http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js>< / script> 

解密:

 code> var decryptpted = CryptoJS.AES.decrypt('83684beb6c8cf063caf45cb7fad04a50','key'); 
console.log(decryptpted.toString(CryptoJS.enc.Utf8)); //空字符串

实际结果是空字符串。



从节点解密数据的正确方法是什么?

解决方案

CryptoJS支持相同的基于密码的加密模式node.js中的crypto模块支持将其实现为等同于EVP_BytesToKey。 CryptoJS默认生成一个随机盐,但node.js不使用空盐。空的盐是坏的,不应该使用。此外,使用此方法从密码派生密钥也不安全。需要使用PBKDF2(由CryptoJS和node.js支持)或类似的,有很多迭代和随机盐。



  var ctHex = '83684beb6c8cf063caf45cb7fad04a50'; var ct = CryptoJS.enc.Hex.parse(ctHex); var salt = CryptoJS.lib.WordArray.create(0); // empty arrayvar decryptpted = CryptoJS.AES.decrypt({ciphertext:ct,salt:salt},'key'); document.querySelector(#dec)。innerHTML = decryptpted.toString(CryptoJS.enc.Utf8);  

 < script src =https:// raw。 githubusercontent.com/CryptoStore/crypto-js/3.1.2/build/rollups/aes.js\"> ;</script>预期:1< br /> Got:< span id =dec >< / span> 






您说这将通过HTTP完成。



如果您想在没有用户干预的情况下使用传输安全,那么这是完全不安全的,因为密钥需要沿着使其最好使混淆的密文传送。



如果用户和服务器在通信之前都知道密码,那么这仍然不够,因为CryptoJS和节点.js提供不足,并且必须使用像PBKDF2。 MD5很容易暴力攻击。



您需要使用非对称加密技术来保护这种通信免受被动攻击者的攻击(一种不能将任意数据包注入服务器和客户)。我建议您生成一个RSA密钥对,并将公钥发送到客户端,以便客户端可以加密到服务器的消息。您可以使用伪造






加密将如下所示:



  var salt = CryptoJS.lib.WordArray .create(0); // empty arrayvar params = CryptoJS.kdf.OpenSSL.execute('key',256/32,128/32,salt); var pt ='1'; var encrypted = CryptoJS.AES.encrypt(pt,params.key ,{iv:params.iv}); document.querySelector(#enc)。innerHTML = encrypted.ciphertext.toString();   < script src =https://raw.githubusercontent.com/CryptoStore/crypto-js/3.1.2/build/rollups/aes。 js>< / script>预期:83684beb6c8cf063caf45cb7fad04a50< br /> Got:< span id =enc>< / span> 


I want encrypt a string with Node, and decrypt the string with CryptoJS in browser.

Encrypt:

var crypto = require('crypto');

function encrypt(txt, cryptkey) {
    var cipher = crypto.createCipher('aes-256-cbc', cryptkey);
    var crypted = cipher.update(txt, 'utf8', 'hex');
    crypted += cipher.final('hex');
    return crypted;
}

encrypt('1', 'key'); // 83684beb6c8cf063caf45cb7fad04a50

Include:

<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js"></script>

Decrypt:

var decrypted = CryptoJS.AES.decrypt('83684beb6c8cf063caf45cb7fad04a50', 'key');
console.log(decrypted.toString(CryptoJS.enc.Utf8)); // empty string

The actual result is empty string.

What is the right way to decrypt data from node?

解决方案

CryptoJS supports the same password-based encryption mode that the crypto module in node.js supports which is implemented as the equivalent to EVP_BytesToKey. CryptoJS generates a random salt by default, but node.js doesn't and uses an empty salt. An empty salt is bad and should not be used. Also, it's not secure to derive a key from a password with this method. One needs to use PBKDF2 (supported by CryptoJS and node.js) or similar with a lot of iterations and a random salt.

var ctHex = '83684beb6c8cf063caf45cb7fad04a50';
var ct = CryptoJS.enc.Hex.parse(ctHex);
var salt = CryptoJS.lib.WordArray.create(0); // empty array
var decrypted = CryptoJS.AES.decrypt({ciphertext: ct, salt: salt}, 'key');

document.querySelector("#dec").innerHTML = decrypted.toString(CryptoJS.enc.Utf8);

<script src="https://raw.githubusercontent.com/CryptoStore/crypto-js/3.1.2/build/rollups/aes.js"></script>
Expected: "1"<br/>Got: "<span id="dec"></span>"


You said that this will be done over HTTP.

If you want to use transport security without user intervention, then this is completely insecure, because the key needs to be transmitted alongside of the ciphertext which makes this at best obfuscation.

If the user and the server both know the password before communication, then this is still insufficient, because the key derivation that both CryptoJS and node.js provide is insufficient and something like PBKDF2 must be used. MD5 is easily brute-forceable.

You would need to use asymmetric cryptography to protect this communication against a passive attacker (one that cannot inject arbitrary packets into the stream between server and client). I suggest that you generate an RSA key pair and sent the public key to the client so that the client can encrypt a message to the server. You can use forge for that.


Encryption would look like this:

var salt = CryptoJS.lib.WordArray.create(0); // empty array
var params = CryptoJS.kdf.OpenSSL.execute('key', 256/32, 128/32, salt);
var pt = '1';
var encrypted = CryptoJS.AES.encrypt(pt, params.key, {iv: params.iv});

document.querySelector("#enc").innerHTML = encrypted.ciphertext.toString();

<script src="https://raw.githubusercontent.com/CryptoStore/crypto-js/3.1.2/build/rollups/aes.js"></script>
Expected: "83684beb6c8cf063caf45cb7fad04a50"<br/>Got: "<span id="enc"></span>"

这篇关于在浏览器中在Node和CryptoJS之间使用AES加密时出现问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆