PHP 和 Python 实现 AES/CBC/PKCS7 加密解密(支持 Base64 和 Hex 编码)
1. Python 版本
import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
class AESUtilCBC:
def __init__(self, key, iv):
self.key = key.encode('utf-8')
self.iv = iv.encode('utf-8')
self.pad_length = AES.block_size
def encrypt(self, data):
try:
data = data.encode('utf-8')
cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
padded_data = pad(data, self.pad_length, style='pkcs7')
encrypted_data = cipher.encrypt(padded_data)
encoded_data = base64.b64encode(encrypted_data).decode('utf-8')
return encoded_data
except Exception as e:
raise Exception(f"Encryption failed: {str(e)}")
def decrypt(self, encrypted_data):
try:
encrypted_bytes = base64.b64decode(encrypted_data)
cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
decrypted_data = cipher.decrypt(encrypted_bytes)
unpadded_data = unpad(decrypted_data, self.pad_length, style='pkcs7')
return unpadded_data.decode('utf-8')
except Exception as e:
raise Exception(f"Decryption failed: {str(e)}")
# 示例使用 AESUtilCBC 类进行加密和解密
key = 'Nhic0EAJqsIdMBfs' # 16字节的密钥
iv = 'Nhic0EAJqsIdMBfs' # 16字节的 IV
aes_util = AESUtilCBC(key, iv)
data = '123456'
encrypted_data = aes_util.encrypt(data)
print(f"加密后的数据: {encrypted_data}")
decrypted_data = aes_util.decrypt(encrypted_data)
print(f"解密后的数据: {decrypted_data}")
运行结果:
加密后的数据: Qun8LbhlewyVvRQDzrNCIQ==
解密后的数据: 123456
2. PHP 版本
<?php
class AESUtilCBC
{
private $key = 'Nhic0EAJqsIdMBfs';
private $iv = 'Nhic0EAJqsIdMBfs';
private $algo = 'AES-128-CBC';
private $options = OPENSSL_RAW_DATA;
public function __construct($key = null, $iv = null, $algo = null, $options = null)
{
if ($key) $this->key = $key;
if ($iv) $this->iv = $iv;
if ($algo) $this->algo = $algo;
if ($options) $this->options = $options;
}
public function encrypt($data)
{
try {
$encryptedData = openssl_encrypt($data, $this->algo, $this->key, $this->options, $this->iv);
return base64_encode($encryptedData);
} catch (Exception $e) {
return false;
}
}
public function decrypt($encryptedData)
{
try {
$decodedData = base64_decode($encryptedData);
return openssl_decrypt($decodedData, $this->algo, $this->key, $this->options, $this->iv);
} catch (Exception $e) {
return false;
}
}
public function encryptHexData($hexData)
{
try {
$encrypted = openssl_encrypt($hexData, $this->algo, $this->key, OPENSSL_RAW_DATA, $this->iv);
return bin2hex($encrypted);
} catch (Exception $e) {
return false;
}
}
public function decryptHexData($hexData)
{
try {
$hexData = pack("H*", $hexData);
return openssl_decrypt($hexData, $this->algo, $this->key, OPENSSL_RAW_DATA, $this->iv);
} catch (Exception $e) {
return false;
}
}
}
$util = new AESUtilCBC();
$encrypted = $util->encrypt('123456');
print("\u52A0\u5BC6\u540E\u7684\u6570\u636E: {$encrypted}<br>");
$decrypted = $util->decrypt($encrypted);
print("\u89E3\u5BC6\u540E\u7684\u6570\u636E: {$decrypted}<br>");
$hexEncrypted = $util->encryptHexData('123456');
print("hex\u52A0\u5BC6\u540E\u7684\u6570\u636E: {$hexEncrypted}<br>");
$hexDecrypted = $util->decryptHexData($hexEncrypted);
print("hex\u89E3\u5BC6\u540E\u7684\u6570\u636E: {$hexDecrypted}");
运行结果:
加密后的数据: Qun8LbhlewyVvRQDzrNCIQ==
解密后的数据: 123456
hex加密后的数据: 42e9fc2db8657b0c95bd1403ceb34221
hex解密后的数据: 123456
3. 其他
1. 在线测试
可以通过下面的网站测试加密结果是否一致:
- https://www.ssleye.com/ssltool/aes_cipher.html
2. 修改加密长度
- PHP 中可通过
$algo
设置 AES-128-CBC 或 AES-256-CBC - Python 根据 key 长度决定,16 字节是 128-bit,32 字节是 256-bit
3. IV 长度
- IV 必须是 16 字节
- key 和 iv 允许一致
4. 加密不一致问题
- key 长度不足 16/32 时,在 PHP/
Python 里需要补全,且补全方式不同也会导致结果不一致
5. PHP 修改模式
- CBC 模式可以改为 ECB:如 AES-128-ECB
6. PHP Hex 解密说明
- 加密:
bin2hex
- 解密:
pack("H*", $hexData)
将 16 进制字符串 转为二进制 - 在在线测试时,选择 “hex” 编码方式即可