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