CryptoJS 和 openssl_decrypt 不会产生相同的结果
CryptoJS and openssl_decrypt not produce same result
我正在尝试使用 php 和 JavaScript 上的字符串实施 AES 256 位加密。对于 jasvascript,我使用了 CryptoJS 和 php,我使用 openssl_decrypt/enecrypt.
下面是JS中的加解密代码。
JavaScript
function aes_encrypt(str_to_encrypt){
if(str_to_encrypt==null)
return "";
var key = CryptoJS.enc.Hex.parse("0123456789abcdef0123456789abcdef");
var iv = CryptoJS.enc.Hex.parse("abcdef9876543210abcdef9876543210");
var encrypted = CryptoJS.AES.encrypt(str_to_encrypt,key, {'mode': CryptoJS.mode.CBC, iv: iv});
var encryptedString = encrypted.toString();
return encryptedString;
}
function aes_decrypt(str_to_decrypt){
if(str_to_decrypt==null)
return "";
var key = CryptoJS.enc.Hex.parse("0123456789abcdef0123456789abcdef");
var iv = CryptoJS.enc.Hex.parse("abcdef9876543210abcdef9876543210");
var decrypted = CryptoJS.AES.decrypt(str_to_decrypt,key, {'mode': CryptoJS.mode.CBC, iv: iv });
var decryptedString = decrypted.toString(CryptoJS.enc.Utf8);
return decryptedString;
}
而在 php 中的代码是
PHP
class Crypto_AES256
{
public $key = "0123456789abcdef0123456789abcdef";
public $iv = "abcdef9876543210abcdef9876543210";
public $encrypt_method = 'AES-256-CBC';
function __construct ()
{
$this->key = hex2bin($this->key);
$this->iv = hex2bin($this->iv);
}
public function encrypt ( $string )
{
if ( $encrypted = base64_encode( openssl_encrypt ( $string, $this->encrypt_method, $this->key, 0, $this->iv ) ) )
{
return $encrypted;
}
else
{
return false;
}
}
public function decrypt ($string)
{
if ( $decrypted = openssl_decrypt ( base64_decode ( $string ), $this->encrypt_method, $this->key, 0, $this->iv ) )
{
return $decrypted;
}
else
{
return false;
}
}
}
但是JavaScript端的加密结果和php不一样,我需要在JavaScript和php端产生相同的加密和加密结果。可能是什么问题。
两种代码在两个方面有所不同:
- PHP 代码应用 AES-256,但由于只使用了 16 字节的密钥(因为十六进制解码),PHP 自动用 0 值填充它,使其长度为 32字节。在 CryptoJS 代码中,密钥长度决定了模式,因此应用了 AES-128。为了使两个代码产生相同的结果,必须在 CryptoJS 代码中扩展密钥,类似于 PHP 代码,或者必须在 PHP 代码中使用 AES-128。
- 在PHP代码中,
openssl_encrypt()
returns密文默认Base64编码,所以密文目前是Base64编码两次。因此,删除显式 base64_encode()
或使用 OPENSSL_RAW_DATA
作为第 4 个参数,以便返回原始数据。 openssl_decrypt()
. 同样
修复这些问题后,两个代码在我的机器上提供相同的密文。请注意,静态 IV 是不安全的(另请参阅评论),但您可能只是出于测试目的才这样做。
示例:以下代码使用您未修改的 CryptoJS 代码,即 AES-128:
function aes_encrypt(str_to_encrypt){
if(str_to_encrypt==null)
return "";
var key = CryptoJS.enc.Hex.parse("0123456789abcdef0123456789abcdef");
var iv = CryptoJS.enc.Hex.parse("abcdef9876543210abcdef9876543210");
var encrypted = CryptoJS.AES.encrypt(str_to_encrypt,key, {'mode': CryptoJS.mode.CBC, iv: iv});
var encryptedString = encrypted.toString();
return encryptedString;
}
function aes_decrypt(str_to_decrypt){
if(str_to_decrypt==null)
return "";
var key = CryptoJS.enc.Hex.parse("0123456789abcdef0123456789abcdef");
var iv = CryptoJS.enc.Hex.parse("abcdef9876543210abcdef9876543210");
var decrypted = CryptoJS.AES.decrypt(str_to_decrypt,key, {'mode': CryptoJS.mode.CBC, iv: iv });
var decryptedString = decrypted.toString(CryptoJS.enc.Utf8);
return decryptedString;
}
var ciphertext = aes_encrypt('The quick brown fox jumps over the lazy dog');
var decrypted = aes_decrypt(ciphertext);
console.log(ciphertext.replace(/(.{56})/g,'\n'));
console.log(decrypted);
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>
如果应用 AES-128-CBC 并且 OPENSSL_RAW_DATA
标志设置为 openssl_encrypt()
中的第 4 个参数,PHP 代码 returns 相同的密文openssl_decrypt()
.
我正在尝试使用 php 和 JavaScript 上的字符串实施 AES 256 位加密。对于 jasvascript,我使用了 CryptoJS 和 php,我使用 openssl_decrypt/enecrypt.
下面是JS中的加解密代码。
JavaScript
function aes_encrypt(str_to_encrypt){
if(str_to_encrypt==null)
return "";
var key = CryptoJS.enc.Hex.parse("0123456789abcdef0123456789abcdef");
var iv = CryptoJS.enc.Hex.parse("abcdef9876543210abcdef9876543210");
var encrypted = CryptoJS.AES.encrypt(str_to_encrypt,key, {'mode': CryptoJS.mode.CBC, iv: iv});
var encryptedString = encrypted.toString();
return encryptedString;
}
function aes_decrypt(str_to_decrypt){
if(str_to_decrypt==null)
return "";
var key = CryptoJS.enc.Hex.parse("0123456789abcdef0123456789abcdef");
var iv = CryptoJS.enc.Hex.parse("abcdef9876543210abcdef9876543210");
var decrypted = CryptoJS.AES.decrypt(str_to_decrypt,key, {'mode': CryptoJS.mode.CBC, iv: iv });
var decryptedString = decrypted.toString(CryptoJS.enc.Utf8);
return decryptedString;
}
而在 php 中的代码是
PHP
class Crypto_AES256
{
public $key = "0123456789abcdef0123456789abcdef";
public $iv = "abcdef9876543210abcdef9876543210";
public $encrypt_method = 'AES-256-CBC';
function __construct ()
{
$this->key = hex2bin($this->key);
$this->iv = hex2bin($this->iv);
}
public function encrypt ( $string )
{
if ( $encrypted = base64_encode( openssl_encrypt ( $string, $this->encrypt_method, $this->key, 0, $this->iv ) ) )
{
return $encrypted;
}
else
{
return false;
}
}
public function decrypt ($string)
{
if ( $decrypted = openssl_decrypt ( base64_decode ( $string ), $this->encrypt_method, $this->key, 0, $this->iv ) )
{
return $decrypted;
}
else
{
return false;
}
}
}
但是JavaScript端的加密结果和php不一样,我需要在JavaScript和php端产生相同的加密和加密结果。可能是什么问题。
两种代码在两个方面有所不同:
- PHP 代码应用 AES-256,但由于只使用了 16 字节的密钥(因为十六进制解码),PHP 自动用 0 值填充它,使其长度为 32字节。在 CryptoJS 代码中,密钥长度决定了模式,因此应用了 AES-128。为了使两个代码产生相同的结果,必须在 CryptoJS 代码中扩展密钥,类似于 PHP 代码,或者必须在 PHP 代码中使用 AES-128。
- 在PHP代码中,
openssl_encrypt()
returns密文默认Base64编码,所以密文目前是Base64编码两次。因此,删除显式base64_encode()
或使用OPENSSL_RAW_DATA
作为第 4 个参数,以便返回原始数据。openssl_decrypt()
. 同样
修复这些问题后,两个代码在我的机器上提供相同的密文。请注意,静态 IV 是不安全的(另请参阅评论),但您可能只是出于测试目的才这样做。
示例:以下代码使用您未修改的 CryptoJS 代码,即 AES-128:
function aes_encrypt(str_to_encrypt){
if(str_to_encrypt==null)
return "";
var key = CryptoJS.enc.Hex.parse("0123456789abcdef0123456789abcdef");
var iv = CryptoJS.enc.Hex.parse("abcdef9876543210abcdef9876543210");
var encrypted = CryptoJS.AES.encrypt(str_to_encrypt,key, {'mode': CryptoJS.mode.CBC, iv: iv});
var encryptedString = encrypted.toString();
return encryptedString;
}
function aes_decrypt(str_to_decrypt){
if(str_to_decrypt==null)
return "";
var key = CryptoJS.enc.Hex.parse("0123456789abcdef0123456789abcdef");
var iv = CryptoJS.enc.Hex.parse("abcdef9876543210abcdef9876543210");
var decrypted = CryptoJS.AES.decrypt(str_to_decrypt,key, {'mode': CryptoJS.mode.CBC, iv: iv });
var decryptedString = decrypted.toString(CryptoJS.enc.Utf8);
return decryptedString;
}
var ciphertext = aes_encrypt('The quick brown fox jumps over the lazy dog');
var decrypted = aes_decrypt(ciphertext);
console.log(ciphertext.replace(/(.{56})/g,'\n'));
console.log(decrypted);
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>
如果应用 AES-128-CBC 并且 OPENSSL_RAW_DATA
标志设置为 openssl_encrypt()
中的第 4 个参数,PHP 代码 returns 相同的密文openssl_decrypt()
.