我有一个使用crypto-Js AES的应用程序。模拟工作代码为:
var ciphertext = CryptoJS.AES.encrypt('My_message', 'My_secret_key');
console.log(ciphertext.toString());
答案是:
U2FsdGVkX1/Dd3uAr/mdw5lVoBvq0UX5LHnNoX24JAM=
当我尝试在服务器端重现它时,我从未得到相同的答案:
$passphrase='My_secret_key';
$value='My_message';
$salt = openssl_random_pseudo_bytes(8);
$salt ='';
$salted = '';
$dx = '';
while (strlen($salted) < 48) {
$dx = md5($dx.$passphrase.$salt, true);
$salted .= $dx;
}
$key = substr($salted, 0, 32);
$iv = substr($salted, 32,16);
$encrypted_data = openssl_encrypt($value, 'aes-256-cbc', $key, true, $iv);
echo base64_encode($encrypted_data);
服务器端答案:
3jSTl1yR55lfTbz7f0o3Yw==
我必须错过一些事情,但不能指出。本地无法触及。
欢迎所有帮助
参考方案
如果CryptoJS.AES.encrypt
中的第二个参数作为字符串传递,则将其解释为一个密码短语,从该密码短语中导出实际的键和IV,即[1]。这是通过使用OpenSSL函数EVP_BytesToKey
的功能(迭代计数为1
)和MD5-digest([2] [3])来实现的(请注意,CryptoJS不考虑默认摘要的切换是从从OpenSSL版本1.1.0c开始的MD5到SHA256,[4])。
CryptoJS.AES.encrypt
返回一个CipherParams
对象,该对象封装了密文,密钥IV和盐[5]。另外,CipherParams#toString()
以OpenSSL格式返回结果,作为Base64编码的字符串。 OpenSSL格式由一个16字节的标头和随后的密文组成。标头以ASCII编码的字符串Salted__
开头,后跟8字节的盐。每次都会随机生成该盐,并与密码一起使用以导出密钥/ IV。每次创建一个不同的键/ IV。
PHP代码在功能上是相同的:每次使用新生成的盐从口令短语中通过模拟逻辑得出Key和IV(有关证明,请参见下文)。但是,需要进行一些小的更改:
必须删除以下行:$salt ='';
在当前代码中,仅显示Base64编码的密文。对于OpenSSL格式的结果的Base64编码输出,必须改为使用以下代码:
echo base64_encode('Salted__'.$salt.$encrypted_data);
openssl_encrypt
中的第4个参数应从true
更改为OPENSSL_RAW_DATA
。两者在功能上是相同的,但是OPENSSL_RAW_DATA
的使用更加透明。
JavaScript和PHP代码每次都会生成一个新的盐,因此会生成一个不同的密钥和IV,每次都会更改密文。那就是应该的样子。由于盐与密文一起存储,因此可以随时使用密码对密文进行解密。
两种代码使用相同的逻辑来得出密钥和IV的证明:每次生成的新盐/密文都会阻止直接比较两种代码的结果。为了毫不费力地执行此比较,最好也使用PHP代码中JavaScript代码中生成的盐。 JavaScript代码中的salt可通过以下方式确定为十六进制字符串:
console.log(ciphertext.salt.toString(CryptoJS.enc.Hex));
此盐将在PHP代码中使用,而不是随机生成的盐(当然,仅用于此比较):
$salt = hex2bin('<Salt from JavaScript-Code as hexadecimal string>');
现在比较两个输出可证明它们是相等的,表明两个代码在功能上是相同的。
Javascript IF语句 - javascript嗨,我有这段代码可以正常工作,并将两个日历显示为一个日历。我还有一个php变量$login_session,其中包含登录电子邮件地址的用户。关于如何显示[email protected]日历的任何想法(伪代码)IF $login_session == "[email protected]…
提交初始化后删除某些帖子数据 - javascript在初始化提交之后但在将数据发送到处理页面之前,是否可以过滤$ _POST表单数据?我想象过程的方式:提交->收集$ _POST数据->发送数据我想做的事:提交->收集$ _POST数据->删除某些元素->发送数据这样就不必更改处理页面以过滤掉不希望接收的元素了吗? javascript大神给出的解决方案 当然可以,您可以在JS …
获取JavaScript值到C#字符串 - javascript是否可以在C#中执行类似的操作?该值为“ 10/05/2014”string jsValue = javascript("$('#EstimatedStartDate').val()"); 参考方案 您能否更详细地阐明您要做什么。看来您正在尝试从javascript(客户…
如何使用Javascript将字典列表解析为JSON格式? - javascript我正在尝试解析JSON格式的词典列表,以便可以使用它们的数据创建一组列表项,其中使用此数据生成文本和ID。我将以下内容传递到我的网页,并在投放之前将其存储在隐藏的div中: [{'text': 'org1', 'id': 'org1ID'}, {'text':…
AES-加密JS和PHP - javascript我对用cryptojs加密的解密数据有问题。有时它有时不起作用,如果起作用,则返回“消息”,但如果声明,则返回垃圾。 var salt = CryptoJS.lib.WordArray.random(128/8); var key256Bits500Iterations = CryptoJS.PBKDF2("password", salt…