【问题标题】:CryptoJS AES decrypting a message encrypted in PHP openssl_encryptCryptoJS AES 解密用 PHP openssl_encrypt 加密的消息
【发布时间】:2020-07-04 19:38:02
【问题描述】:

我有以下使用openssl_encrypt() 函数加密消息的PHP 代码。代码如下:

$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));

这段代码给了我一个空白输出,什么也没有。我在这里做错了什么?如何更正我的实现?

【问题讨论】:

    标签: javascript encryption openssl aes cryptojs


    【解决方案1】:

    PHP 代码:

    • openssl_encrypt 用零值填充键,直到达到指定的键长度,即键 TasKagitMakas 扩展为 TasKagitMakas\0\0\0
    • $options = 0 表示密文是隐式 Base64 编码的。由于密文之后又显式进行了Base64编码,所以一共是Base64编码两次。这是不必要的,应该更改,例如使用$options = OPENSSL_RAW_DATA
    • 对于 CTR openssl_encrypt 等流密码模式,会自动禁用默认的 PKCS7 填充。

    JavaScript 代码:

    • 由于在 PHP 代码中进行了两次 Base64 编码,因此需要在 JavaScript 代码中进行两次 Base64 解码。这一步当然只对未更改的 PHP 代码是必要的。
    • 必须使用 Utf8 编码器将密钥和 IV 解析为 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\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 student@ug.bilkent.edu.tr   Team1   6 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-08-17
      • 2021-12-20
      • 2012-08-01
      • 2019-08-13
      • 1970-01-01
      • 1970-01-01
      • 2014-12-16
      • 1970-01-01
      相关资源
      最近更新 更多