You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

类外部修改私有密钥后openssl_encrypt加密结果未变更的问题

问题根源

你的核心问题在于加密依赖的_encryption_key和_iv是在构造函数中初始化的,而构造函数在new Encryption()时就已经执行完毕——此时$_secret_key还是初始的空字符串,生成的加密密钥和IV都是基于空值计算的。后续调用setSecretkey()虽然修改了$_secret_key,但并没有同步更新实际用于加密的_encryption_key和_iv,所以加密结果自然不会变化。

而直接修改类内$_secret_key的初始值时,构造函数执行时会用新的初始值生成正确的加密密钥,所以加密结果会改变。

解决方案

这里提供两种实用的修复方式:

方式一:修改setSecretkey方法,同步更新加密密钥和IV

在设置$_secret_key后,重新计算_encryption_key和_iv,确保加密使用最新的密钥:

class Encryption
{
  const AES_256_CBC = 'aes-256-cbc';
    
  private $_secret_key = '';
  private $_secret_iv  = '';
  private $_encryption_key;
  private $_iv;
    

  function setSecretkey($_secret_key) {
      $this->_secret_key = $_secret_key;
      // 新增:同步更新加密密钥和IV
      $this->_encryption_key = hash('sha256', $this->_secret_key);
      $this->_iv             = substr(hash('sha256', $this->_secret_iv), 0, 16);
  }

  function getSecretkey() {
      echo 'new key =  ' . $this->_secret_key . '<br>';
  }
    

  public function __construct()
  {
    $this->_encryption_key = hash('sha256', $this->_secret_key);
    $this->_iv             = substr(hash('sha256', $this->_secret_iv), 0, 16);
  }


  public function encryptString($data)
  {
    return base64_encode(openssl_encrypt($data, self::AES_256_CBC, $this->_encryption_key, 0, $this->_iv));
  }

  public function decryptString($data)
  {
    return openssl_decrypt(base64_decode($data), self::AES_256_CBC, $this->_encryption_key, 0, $this->_iv);
  }

  public function setEncryptionKey($key)
  {
    $this->_encryption_key = $key;
  }

  public function setInitVector($iv)
  {
    $this->_iv = $iv;
  }
}

// 测试代码不变
$keyvalue = 'test';
$raw_string = 'Testtext';
$encrypt = new Encryption();
$encrypt->setSecretkey($keyvalue);
$encrypt->getSecretkey();
$encrypted = $encrypt->encryptString($raw_string);
echo 'encrypted text = ' . $encrypted;

方式二:构造函数直接接收密钥参数(更规范的OOP写法)

避免对象处于未正确初始化的状态,直接在创建对象时传入密钥,一次性完成所有初始化:

class Encryption
{
  const AES_256_CBC = 'aes-256-cbc';
    
  private $_secret_key;
  private $_secret_iv;
  private $_encryption_key;
  private $_iv;
    
  // 构造函数接收密钥和IV参数
  public function __construct($secret_key, $secret_iv = '')
  {
    $this->_secret_key = $secret_key;
    $this->_secret_iv = $secret_iv;
    $this->_encryption_key = hash('sha256', $this->_secret_key);
    $this->_iv             = substr(hash('sha256', $this->_secret_iv), 0, 16);
  }

  function getSecretkey() {
      echo 'current key =  ' . $this->_secret_key . '<br>';
  }

  public function encryptString($data)
  {
    return base64_encode(openssl_encrypt($data, self::AES_256_CBC, $this->_encryption_key, 0, $this->_iv));
  }

  public function decryptString($data)
  {
    return openssl_decrypt(base64_decode($data), self::AES_256_CBC, $this->_encryption_key, 0, $this->_iv);
  }

  // 如果需要后续修改密钥,保留set方法并同步更新
  function setSecretkey($_secret_key) {
      $this->_secret_key = $_secret_key;
      $this->_encryption_key = hash('sha256', $this->_secret_key);
  }
}

// 测试代码修改为构造时传参
$keyvalue = 'test';
$raw_string = 'Testtext';
$encrypt = new Encryption($keyvalue);
$encrypt->getSecretkey();
$encrypted = $encrypt->encryptString($raw_string);
echo 'encrypted text = ' . $encrypted;
额外提示
  • AES-256-CBC的IV应该是随机生成的,不建议固定基于密钥生成IV(会降低加密安全性)。每次加密时生成随机IV,把IV和密文一起存储,解密时再提取IV使用。
  • 哈希函数hash('sha256', $key)生成的是64字符的十六进制字符串,而AES-256需要32字节的密钥,其实可以用hash('sha256', $key, true)获取原始二进制哈希值,更高效。

内容的提问来源于stack exchange,提问作者Plakativ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 18:43:26