CryptoJS AES-128-ECB 和 PHP openssl_encrypt 不匹配

CryptoJS AES-128-ECB and PHP openssl_encrypt don't match

我在 PHP 上有一些代码,无法编辑,并且数据库中充满了这种方式的加密消息。

$key = '297796CCB81D2553B07B379D78D87618'
return $encrypted = openssl_encrypt($data, 'AES-128-ECB', $key);

我必须编写一些 JS 代码来加密和解密这些消息。为此,我正在使用 CryptoJS。

const key = '297796CCB81D2553B07B379D78D87618'
let k = CryptoJS.enc.Base64.parse(key)
let cypher = CryptoJS.AES.encrypt(this.text, k, {mode: CryptoJS.mode.ECB})
this.cypher = CryptoJS.enc.Base64.stringify(cypher.ciphertext)

我无法让这些代码产生相同的结果。对于 'test' 字符串,我得到以下结果:JS: H1AG6j/i/iSqifSNCG5JKw==PHP: Nqrur4UMEicEMwJC39qq0A==

我尝试了 3 天来解决这个问题,但我找不到问题所在。 我唯一可以编辑的代码是 JS。

我明白是什么问题了。 openssl_encrypt in PHP 将密钥作为 UTF-8 字符串。在获得足够长的长度后,它会忽略下一个字符,因此我们的密钥:'297796CCB81D2553B07B379D78D87618' 修剪为 '297796CCB81D2553'。 此代码有效:

// JS 
const key = '297796CCB81D2553'
let k = CryptoJS.enc.Utf8.parse(key)
let cypher = CryptoJS.AES.encrypt(this.text, k, {mode: CryptoJS.mode.ECB})
this.cypher = CryptoJS.enc.Base64.stringify(cypher.ciphertext) 

如果您在 PHP 部分将方法更改为 AES-256-ECB,它将使用相同的密钥(长度)。是因为CryptoJS.AES,自己根据key的长度选择方法

https://cryptojs.gitbook.io/docs/#the-cipher-algorithms

AES-256-CBC 示例

/*
    CryptoJS (JS) chooses the AES method by size of the key,
    for AES-256 you need 256 bit key (32 1-byte chars).
    For AES-128 you have to change substr() from "32" to "16" in this script below (in both PHP and JS part) and change $method in PHP part to "AES-128-CBC".
    Default CryptoJS mode is CBC.

    Openssl (PHP) AES-CBC cipher expects 128 bit iv (16 1-byte chars).
*/


/* JS */


// Substances
var data = "Data",
    salt = CryptoJS.SHA256( "Salt" ),
    iv   = CryptoJS.SHA1( "Vector" ),
    key  = CryptoJS.SHA256( "Key" );

// Prepare substances
salt = salt.toString( CryptoJS.enc.Base64 );
iv   = iv.toString( CryptoJS.enc.Base64 ).substr( 0, 16 );
iv   = CryptoJS.enc.Utf8.parse( iv );
key  = key.toString( CryptoJS.enc.Base64 ).substr( 0, 32 );
key  = CryptoJS.enc.Utf8.parse( key );

// Cipher
var encrypted = CryptoJS.AES.encrypt( salt + data, key, { iv: iv });

// Results
console.log( "SALT\n"       + salt );
console.log( "IV\n"         + encrypted.iv.toString( CryptoJS.enc.Utf8 ));
console.log( "KEY\n"        + encrypted.key.toString( CryptoJS.enc.Utf8 ));
console.log( "ENCRYPTED\n"  + encrypted.toString());


/* PHP */


// Substances
$data   = "Data";
$salt   = openssl_digest( "Salt",   "SHA256" );
$iv     = openssl_digest( "Vector", "SHA1" );
$key    = openssl_digest( "Key",    "SHA256" );

// Method
$method = "AES-256-CBC";

// Prepare substances
$salt   = base64_encode( hex2bin( $salt ));
$iv     = substr( base64_encode( hex2bin( $iv )),  0, 16 );
$key    = substr( base64_encode( hex2bin( $key )), 0, 32 );

// Cipher
$encrypted = openssl_encrypt( $salt .$data, $method, $key, 0, $iv );

// Results
var_dump([  "SALT"      => $salt,
            "IV"        => $iv,
            "KEY"       => $key,
            "ENCRYPTED" => $encrypted ]);

/*
    Results CryptoJS (JS):

    SALT: yDtwME1gxORm3S1FKrWukVtQJ2/EYSTt3j49voeKTf4=
    IV:   pX4G9FSRBn8DEoT7
    KEY:  S4VjDgGFIBNzA2jl8Ta6/iiIWJgtTgWF
    ENCRYPTED
    5y8MvyMiCUjTQJUxtRNZzuYSWwSoY9edMO0o6aQoSX0t4NZWnnViPotU8vkMtgfBuZ6F1FfE/ZJZvafdtGVHJQ==

    Results openssl_encrypt (PHP):

    SALT: yDtwME1gxORm3S1FKrWukVtQJ2/EYSTt3j49voeKTf4=
    IV:   pX4G9FSRBn8DEoT7
    KEY:  S4VjDgGFIBNzA2jl8Ta6/iiIWJgtTgWF
    ENCRYPTED
    5y8MvyMiCUjTQJUxtRNZzuYSWwSoY9edMO0o6aQoSX0t4NZWnnViPotU8vkMtgfBuZ6F1FfE/ZJZvafdtGVHJQ==
*/