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==
*/
我在 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==
*/