Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/469.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 用'编码;加密js';并用'解码;加密';(节点)_Javascript_Encryption_Aes_Cryptojs_Node Crypto - Fatal编程技术网

Javascript 用'编码;加密js';并用'解码;加密';(节点)

Javascript 用'编码;加密js';并用'解码;加密';(节点),javascript,encryption,aes,cryptojs,node-crypto,Javascript,Encryption,Aes,Cryptojs,Node Crypto,我正在使用浏览器中的“cypto js”使用高级加密标准(AES)对字符串进行加密,需要在服务器上使用节点“crypto”对其进行解密 我可以单独使用“crypto js”进行加密/解密,但是当我尝试使用“crypto.createDecipher”使用“crypto”(节点)进行解密时,根据我的尝试,会收到“解密错误”或“块大小错误”的错误消息 例:只使用“crypto js”就可以了 crypto-js const cypherParams = CryptoJS.AES.encrypt('

我正在使用浏览器中的“cypto js”使用高级加密标准(AES)对字符串进行加密,需要在服务器上使用节点“crypto”对其进行解密

我可以单独使用“crypto js”进行加密/解密,但是当我尝试使用“crypto.createDecipher”使用“crypto”(节点)进行解密时,根据我的尝试,会收到“解密错误”或“块大小错误”的错误消息

例:只使用“crypto js”就可以了

crypto-js

const cypherParams = CryptoJS.AES.encrypt('my message', 'passphrase')
const decrypted = CryptoJS.AES.decrypt(cypherParams, 'passphrase')
console.log(decrypted.toString(CryptoJS.enc.Utf8)) // 'my message' - works!
例如:使用“crypto js”编码使用“crypto”解码-导致错误

[client]
const cypherParams = CryptoJS.AES.encrypt('my message', 'passphrase')

[server]
const decipher = crypto.createDecipher('aes-256-cbc', 'passphrase');
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
decrypted += decipher.final('utf8'); 
// results in 'bad decrypt' or 'block size' error in console


console.log(decrypted); // this never executes
我试过:

  • 将decrypt中的加密算法更改为192或其他(但'crypto js'文档称默认值为'256'是使用的密码短语)
  • 客户端上的base64编码。也尝试了十六进制编码
例:

  • 我使用的是'crypto.createDecipher'而不是'crypto.createDecipheriv',因为在这个项目中我一直在使用节点v8.12.0

我想就是这样了…我感谢任何帮助或提示!

如果密钥是以字符串形式传递的,
CryptoJS.AES.encrypt()
使用OpenSSL密钥派生函数(KDF)派生32字节的密钥(和16字节的IV),即AES-256确实应用于加密(和)。在此过程中,将生成随机的8字节salt,以确保每次生成不同的密钥/IV对。
NodeJS方法使用相同的KDF,但不应用salt,因此始终生成相同的密钥/IV对。因此也不考虑salt。
总之,这意味着使用
CryptoJS.AES.encrypt()
加密时生成的密钥对与使用
crypto.createDecipher()
解密时生成的密钥对不同,解密失败

据我所知,这两种方法都无法控制是否使用盐,因此无法消除不相容性

因此,一种解决方案是省略内置KDF(这被认为是很弱的,这就是为什么
crypto.createCipher()
/
crypto.createDecipher()
被弃用的原因),而是使用可靠的KDF,例如PBKDF2,并使用从中派生的密钥/IV对。
在CryptoJS端,您必须将密钥和IV作为
WordArray
传递,在NodeJS端,您必须使用。
加密和解密之间的连接是在密钥派生过程中随机生成的salt。salt不是秘密的,通常与密文连接并以这种方式传递给接收方

您提到您使用的版本是Node v8.12.0,因此无法应用
crypto.createDecipheriv()
。但是
crypto.createDecipheriv()
从v0.1.94开始就可用,因此它应该在您的环境中可用


客户端加密的示例实现(CryptoJS):

//生成随机盐
var salt16=CryptoJS.lib.WordArray.random(16);//随机16字节salt
//通过PBKDF2导出密钥和IV
var keyIV=CryptoJS.PBKDF2(“我的密码”,salt16{
keySize:(32+16)/4,//12个字a 4个字节=48个字节
迭代次数:1000,//选择足够高的迭代次数
hasher:CryptoJS.algo.SHA256//默认摘要是SHA-1
}); 
var key32=CryptoJS.lib.WordArray.create(keyIV.words.slice(0,32/4));//8个单词a 4个字节=32个字节
var iv16=CryptoJS.lib.WordArray.create(keyIV.words.slice(32/4,(32+16)/4));//4个单词和4个字节=16个字节
//加密
var message=‘敏捷的棕色狐狸跳过了懒狗’;
var cipherParams=CryptoJS.AES.encrypt(消息,key32,{iv:iv16});
var ciphertext=cipherParams.ciphertext;
//连接salt和密文
var saltCiphertext=salt16.clone().concat(密文);
var saltCiphertextB64=saltCiphertext.toString(CryptoJS.enc.Base64);//这将传递给收件人
//输出
log(“Salt:\n”,salt16.toString(CryptoJS.enc.Base64).replace(/({56})/g,'$1\n');
log(“Ciphertext:\n”,Ciphertext.toString(CryptoJS.enc.Base64).replace(/({56})/g,'$1\n');
log(“Salt | Ciphertext:\n”,saltCiphertextB64.replace(/({56})/g,$1\n');

@jspru-我已经用客户端和服务器端的示例实现说明了我的答案。非常感谢您提供的详细答案。我已经阅读了多次(以及crypto js和crypto docs)并且一直在开发一个实现,但仍有一点困难。我将与您的示例代码进行比较,并尽快返回给您。再次感谢!这对我来说很有效!问题是我没有在服务器端正确导出密钥/iv,导致不匹配。我将继续研究您的实现,以真正理解方法更好。这是复杂的东西,但真的很有趣。谢谢你难以置信的回答和帮助。
const cypherParams = CryptoJS.AES.encrypt('my message', 'passphrase')
const base64Encoded = cipherParams.toString(CryptoJS.enc.Base64)

and

const cypherParams = CryptoJS.AES.encrypt('my message', 'passphrase')
const cypherParams.ciphertext = cipherParams.toString(CryptoJS.enc.Base64)