这是我的PHP代码:
$cipher = 'aes-256-cbc';
// 128-bit key
$key = md5('super secret', true);
// 128-bit IV
$iv = openssl_random_pseudo_bytes(16);
$ciphertext = openssl_encrypt($message, $cipher, $key, OPENSSL_RAW_DATA, $iv);
error_log(__FILE__ . __LINE__ . ' key: ' . bin2hex($key));
error_log(__FILE__ . __LINE__ . ' iv: ' . bin2hex($iv));
error_log(__FILE__ . __LINE__ . ' ciphertext: ' . bin2hex($ciphertext));
file_put_contents($courseOutlineFile, bin2hex($iv) . bin2hex($ciphertext));
还有我的Javascript代码,其中res是来自ajax响应的文本,用于读取PHP生成的文件:
var k = CryptoJS.MD5('super secret');
var iv = CryptoJS.enc.Hex.parse(res.substring(0, 32));
var data = CryptoJS.enc.Hex.parse(res.substring(32));
console.log("key: ", CryptoJS.enc.Hex.stringify(k))
console.log("iv: ", CryptoJS.enc.Hex.stringify(iv))
console.log("ciphertext: ", CryptoJS.enc.Hex.stringify(data))
var cipher = CryptoJS.lib.CipherParams.create({
ciphertext: data
});
var dec = CryptoJS.AES.decrypt(cipher, k, {
iv: iv,
mode: CryptoJS.mode.CBC
});
console.log("decrypted:", dec.toString(CryptoJS.enc.Hex));
var json = dec.toString(CryptoJS.enc.Utf8);
console.log("json:", json)
我已经使用比较工具验证了密钥,IV和数据的十六进制值在PHP中是相同的,并且打印到浏览器控制台的内容也相同。它确实可以成功解密(某些东西),但是最后一个console.log语句生成错误:错误:“格式错误的UTF-8数据”。如果我尝试使用Latin1,则会导致一堆不可打印的字符。
我正在加密的$ message变量是数组上json_encode的输出。
有人知道我想念什么吗?
这些是解密结果的前80个十六进制数字,整个东西还不到28k十六进制数字。
20a290156abf2855f2c3344a2d9cf7dc84c5c02b1a48a03f18aa8a5054f650dd5517b25b6582c72d
这是一个完整的例子:
<?php
ini_set('display_errors', 1);
$jsonObj = [
'el1' => 'val1',
'ar1' => [
'el2' => 'val2',
'el3' => 'val3',
],
];
$message = json_encode($jsonObj);
echo $message . '<br>';
$cipher = 'aes-256-cbc';
// 128-bit key
$key = md5('super secret', true);
// 128-bit IV
$iv = openssl_random_pseudo_bytes(16);
$ciphertext = openssl_encrypt($message, $cipher, $key, OPENSSL_RAW_DATA, $iv);
echo ' key: ' . bin2hex($key) . '<br>';
echo ' iv: ' . bin2hex($iv) . '<br>';
echo ' ciphertext: ' . bin2hex($ciphertext) . '<br>';
echo bin2hex($iv) . bin2hex($ciphertext);
输出:
{"el1":"val1","ar1":{"el2":"val2","el3":"val3"}}
key: 5f1903f5f2cb32acb4c1dcae9e30d374
iv: bfdb765d1ca4734c5748ffb9883dd15c
ciphertext:
02717027440040375f7e0dbea69e77783949d3c160529eef0b9d59a751a2a312fa137a5034f6f4c9f89a348ef3f96fce40c8afe0c8a20a2f7a2535417cca2dd2
bfdb765d1ca4734c5748ffb9883dd15c02717027440040375f7e0dbea69e77783949d3c160529eef0b9d59a751a2a312fa137a5034f6f4c9f89a348ef3f96fce40c8afe0c8a20a2f7a2535417cca2dd2
和Javascript:
res = 'bfdb765d1ca4734c5748ffb9883dd15c02717027440040375f7e0dbea69e77783949d3c160529eef0b9d59a751a2a312fa137a5034f6f4c9f89a348ef3f96fce40c8afe0c8a20a2f7a2535417cca2dd2';
var k = CryptoJS.MD5('super secret');
var iv = CryptoJS.enc.Hex.parse(res.substring(0, 32));
var data = CryptoJS.enc.Hex.parse(res.substring(32));
console.log("key: ", CryptoJS.enc.Hex.stringify(k))
console.log("iv: ", CryptoJS.enc.Hex.stringify(iv))
console.log("ciphertext: ", CryptoJS.enc.Hex.stringify(data))
var cipher = CryptoJS.lib.CipherParams.create({
ciphertext: data
});
var dec = CryptoJS.AES.decrypt(cipher, k, {
iv: iv,
mode: CryptoJS.mode.CBC
});
console.log("dec:", dec.toString());
console.log("decrypted:", dec.toString(CryptoJS.enc.Hex));
var json = dec.toString(CryptoJS.enc.Utf8);
console.log("json:", json)
// parse the JSON string to get the object
var obj = JSON.parse(json);
控制台输出:
key: 5f1903f5f2cb32acb4c1dcae9e30d374
iv: bfdb765d1ca4734c5748ffb9883dd15c
ciphertext: 02717027440040375f7e0dbea69e77783949d3c160529eef0b9d59a751a2a312fa137a5034f6f4c9f89a348ef3f96fce40c8afe0c8a20a2f7a2535417cca2dd2
dec: 50d411522f2d08b34d68f847fb78e0cfabf1144f933d83839431732a473079d9b3ed843e120d9ad6a239
decrypted: 50d411522f2d08b34d68f847fb78e0cfabf1144f933d83839431732a473079d9b3ed843e120d9ad6a239
Error during decryption: Error: "Malformed UTF-8 data"