我有以下 PHP 代码,它使用 openssl_encrypt()
函数来加密消息。这是代码:
$ciphering = "AES-128-CTR";
$options = 0;
$encryption_iv = '5192001995060634';
$encryption_key = "TasKagitMakas";
function encrypt ($string) {
global $ciphering, $options, $encryption_iv, $encryption_key;
$encryption = openssl_encrypt($string, $ciphering,
$encryption_key, $options, $encryption_iv);
$encryption = strtr(base64_encode($encryption), '+/=', '-_,');
return $encryption;
}
我试图反转上面的过程并使用 CryptoJS 获得 Javascript 实现。这是我想到的:
var str = "bzB5UVNBclRHbWhlQUs4aHJoMHVxR1BJNEF1Sk9BRkpvbEpBRDFnVmg0MEx4RGtqWllvdUIrSW0vZGY3eG1KMVd2b2JxRFlOTnJ6N2FnPT0,";
str = str.split("-").join("+");
str = str.split("_").join("/");
str = str.split(",").join("=");
var encrypted = CryptoJS.enc.Base64.parse(str);
var encryptedStr = encrypted.toString(CryptoJS.enc.Utf8);
var key = "TasKagitMakas";
var iv = "5192001995060634";
var decrypted = CryptoJS.AES.decrypt(encryptedStr, key, {iv: iv, mode: CryptoJS.mode.CTR});
console.log(decrypted.toString(CryptoJS.enc.Utf8));
这段代码给了我一个空白的输出,什么也没有。我在这里做错了什么?如何纠正我的实现?
最佳答案
PHP 代码:
openssl_encrypt
用零值填充 key ,直到达到指定的 key 长度,即 keyTasKagitMakas
扩展为TasKagitMakas\0\0\0
。$options = 0
表示密文是隐式 Base64 编码的。由于密文之后再次被显式进行 Base64 编码,因此总共被 Base64 编码两次。这是不必要的,应该进行更改,例如使用$options = OPENSSL_RAW_DATA
。- 对于 CTR 等流密码模式,
openssl_encrypt
会自动禁用默认的 PKCS7 填充。
JavaScript 代码:
- 由于在 PHP 代码中进行了两次 Base64 编码,因此需要在 JavaScript 代码中进行两次 Base64 解码。当然,只有未更改的 PHP 代码才需要执行此步骤。
- Key 和 IV 必须使用 Utf8 编码器解析为
WordArray
。必须使用扩展 key 。 CryptoJS.AES.decrypt
期望密文为CipherParams
对象。- 与 PHP 不同,CryptoJS 不会自动禁用流密码模式的默认 PKCS7 填充,即必须显式禁用它。
以下 JavaScript 代码解密密文:
var str = "bzB5UVNBclRHbWhlQUs4aHJoMHVxR1BJNEF1Sk9BRkpvbEpBRDFnVmg0MEx4RGtqWllvdUIrSW0vZGY3eG1KMVd2b2JxRFlOTnJ6N2FnPT0,";
str = str.split("-").join("+");
str = str.split("_").join("/");
str = str.split(",").join("=");
var encrypted = CryptoJS.enc.Base64.parse(str); // Base64 decode twice (as long as this happens in the PHP code)
var encrypted = encrypted.toString(CryptoJS.enc.Utf8);
var encrypted = CryptoJS.enc.Base64.parse(encrypted);
var key = CryptoJS.enc.Utf8.parse("TasKagitMakas\0\0\0"); // Expand the key and use the Utf8 encoder
var iv = CryptoJS.enc.Utf8.parse("5192001995060634"); // Use the Utf8 encoder
var decrypted = CryptoJS.AES.decrypt(
{
ciphertext: encrypted // Pass teh ciphertext as CipherParams object
},
key,
{
iv: iv,
mode: CryptoJS.mode.CTR,
padding: CryptoJS.pad.NoPadding // Disable the PKCS7 padding
});
console.log(decrypted.toString(CryptoJS.enc.Utf8));
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>
输出:
399002 Örnek2 Öğrenci <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="ff8c8b8a9b9a918bbf8a98d19d9693949a918bd19a9b8ad18b8d" rel="noreferrer noopener nofollow">[email protected]</a> Team1 6
关于javascript - CryptoJS AES 解密 PHP openssl_encrypt 中加密的消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62733639/