Javascript CryptoJS和openssl_解密不会产生相同的结果

Javascript CryptoJS和openssl_解密不会产生相同的结果,javascript,php,encryption,cryptojs,php-openssl,Javascript,Php,Encryption,Cryptojs,Php Openssl,我正在尝试在php和JavaScript上使用字符串实现AES 256位加密。对于jasvascript I和php,我使用openssl_decrypt/enecrypt 下面是JS中用于加密和解密的代码 JavaScript function aes_encrypt(str_to_encrypt){ if(str_to_encrypt==null) return ""; var key = CryptoJS.enc.Hex.parse("012

我正在尝试在php和JavaScript上使用字符串实现AES 256位加密。对于jasvascript I和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\u encrypt()
    返回默认情况下编码的密文Base64,因此密文当前被Base64编码两次。因此,删除显式的
    base64\u encode()
    或使用
    OPENSSL\u RAW\u DATA
    作为第四个参数,以便返回原始数据。类似于
    openssl\u decrypt()
当这些问题得到解决时,两个代码在我的机器上提供相同的密文。请注意,静态IV是不安全的(另请参见注释),但您可能只是出于测试目的才这样做


示例:以下代码使用未修改的CryptoJS代码,即AES-128:

函数aes\u encrypt(str\u to\u encrypt){
if(str_to_encrypt==null)
返回“”;
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();
返回encryptedString;
}
函数aes_decrypt(str_to_decrypt){
if(str_to_decrypt==null)
返回“”;
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);
返回解密字符串;
}
var ciphertext=aes_encrypt(“敏捷的棕色狐狸跳过了懒狗”);
var decrypted=aes_decrypt(密文);
log(ciphertext.replace(/({56})/g,'$1\n');
console.log(解密)

1。不要硬编码IVs,它们应该根据输入动态生成,并与密文一起分发。2.如果没有示例数据,除了猜测之外,任何人都不能做很多事情。感谢您的反馈,现在问题已经解决了。在php和JS上,我将密钥长度扩展为32,因为我必须使用256位密钥。我对iv有一个疑问,若静态iv是不安全的,我是否需要将系统生成的iv传递给解密函数。我的最终目的是以加密(php或JS)格式将数据(字符串)存储在DB中。稍后访问它并解密(从JS)以供进一步使用。通常为每次加密生成一个随机IV。IV不是秘密的,与密文一起未加密发送给收件人。因此,只需发送一个值,两个数据通常在字节级别以IV |密文顺序连接。由于IV的长度是已知的(对应于块大小,即AES为16字节),接收器可以分离IV和密文并执行解密。这意味着
AES_encrypt()
将返回IV+密文,我可以将其存储在DB中,而解密时我只需要从DB传递加密数据,不单独传递IV。这意味着aes_encrypt()将返回IV+密文,我可以将其存储在DB中:是,解密时我必须只从DB传递加密数据,而不是单独传递IV:否,用于解密,例如,使用
aes_decrypt()
,IV+密文从DB传递到
aes_decrypt()
,其中IV和密文被分离,然后进行解密。