类外部修改私有密钥后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
相关产品推荐
相关产品推荐

