CryptoJS AES 解密在 PHP openssl_encrypt 中加密的消息
CryptoJS AES decrypting a message encrypted in PHP openssl_encrypt
我有以下 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
用零值填充键,直到达到指定的键长度,即键 TasKagitMakas
扩展为 TasKagitMakas[=15=][=15=][=15=]
.
$options = 0
表示密文隐式Base64编码。由于密文之后又显式进行了Base64编码,所以总共进行了两次的Base64编码。这是不必要的,应该更改,例如 $options = OPENSSL_RAW_DATA
.
- 对于像 CTR 这样的流密码模式
openssl_encrypt
会自动禁用默认的 PKCS7 填充。
JavaScript代码:
- 由于在PHP代码中进行了两次Base64编码,因此需要在JavaScript代码中进行两次Base64解码。这一步当然只对不变的 PHP 代码是必要的。
- 密钥和 IV 必须使用 Utf8 编码器解析为
WordArray
。必须使用扩展密钥。
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[=10=][=10=][=10=]"); // 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 student@ug.bilkent.edu.tr Team1 6
我有以下 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
用零值填充键,直到达到指定的键长度,即键TasKagitMakas
扩展为TasKagitMakas[=15=][=15=][=15=]
.$options = 0
表示密文隐式Base64编码。由于密文之后又显式进行了Base64编码,所以总共进行了两次的Base64编码。这是不必要的,应该更改,例如$options = OPENSSL_RAW_DATA
.- 对于像 CTR 这样的流密码模式
openssl_encrypt
会自动禁用默认的 PKCS7 填充。
JavaScript代码:
- 由于在PHP代码中进行了两次Base64编码,因此需要在JavaScript代码中进行两次Base64解码。这一步当然只对不变的 PHP 代码是必要的。
- 密钥和 IV 必须使用 Utf8 编码器解析为
WordArray
。必须使用扩展密钥。 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[=10=][=10=][=10=]"); // 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 student@ug.bilkent.edu.tr Team1 6