javascript - CryptoJS AES 解密 PHP openssl_encrypt 中加密的消息

标签 javascript encryption openssl aes cryptojs

我有以下 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 长度,即 key TasKagitMakas 扩展为 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/

相关文章:

encryption - RSA公钥将ASCII值加密为0,如何解密?

Java:如何创建一个通过交换字符对来加密行的程序?

java - 制作加密程序,我收到语法错误,但我不知道为什么

c - Openssl中的大数模一个小整数

ssl - 使用特殊规则签署证书请求

javascript - 如何将此 .js 文件转换为 jsp 文件?

javascript - 在这个父 div 中添加新的父 div 和下一个 div

javascript - 没有 jQuery 的 .prependTo() 和 .insertAfter()

javascript - 何时将 JS 变量用引号引起来

php - 64 位 Linux/Ubuntu 和 openssl 问题(无法读取符号 : Bad value)