在加密中使用动态 IV(初始化向量)是更安全的实践。动态 IV 的生成方式通常是随机生成,并与加密的密文一起存储或传输,这样在解密时可以还原原始数据。
以下是支持动态 IV 的 PHP 和 Python 示例代码。
---
PHP 示例代码
<?php
function aesEncryptWithDynamicIV($data, $key) {
$iv = random_bytes(16); // 动态生成随机IV
$paddedData = pkcs7Pad($data, 16);
$encryptedData = openssl_encrypt($paddedData, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv);
return base64_encode($iv . $encryptedData); // IV 和密文拼接后返回
}
function aesDecryptWithDynamicIV($encryptedData, $key) {
$decodedData = base64_decode($encryptedData);
$iv = substr($decodedData, 0, 16); // 提取前16字节作为IV
$encryptedData = substr($decodedData, 16); // 提取剩余部分作为密文
$decryptedData = openssl_decrypt($encryptedData, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv);
return pkcs7Unpad($decryptedData);
}
function pkcs7Pad($data, $blockSize) {
$padLength = $blockSize - (strlen($data) % $blockSize);
return $data . str_repeat(chr($padLength), $padLength);
}
function pkcs7Unpad($data) {
$padLength = ord(substr($data, -1));
return substr($data, 0, -$padLength);
}
// 示例使用
$key = "1234567890abcdef"; // 16字节密钥
$data = "Hello, AES CBC!";
$encrypted = aesEncryptWithDynamicIV($data, $key);
echo "加密后的数据: " . $encrypted . PHP_EOL;
$decrypted = aesDecryptWithDynamicIV($encrypted, $key);
echo "解密后的数据: " . $decrypted . PHP_EOL;
?>
---
Python 示例代码
from Crypto.Cipher import AES
import base64
import os
def pkcs7_pad(data, block_size):
pad_length = block_size - len(data) % block_size
return data + chr(pad_length).encode() * pad_length
def pkcs7_unpad(data):
pad_length = data[-1]
return data[:-pad_length]
def aes_encrypt_with_dynamic_iv(data, key):
iv = os.urandom(16) # 动态生成随机IV
cipher = AES.new(key, AES.MODE_CBC, iv)
padded_data = pkcs7_pad(data.encode(), AES.block_size)
encrypted_data = cipher.encrypt(padded_data)
return base64.b64encode(iv + encrypted_data).decode() # IV 和密文拼接后返回
def aes_decrypt_with_dynamic_iv(encrypted_data, key):
decoded_data = base64.b64decode(encrypted_data)
iv = decoded_data[:16] # 提取前16字节作为IV
encrypted_data = decoded_data[16:] # 提取剩余部分作为密文
cipher = AES.new(key, AES.MODE_CBC, iv)
decrypted_data = cipher.decrypt(encrypted_data)
return pkcs7_unpad(decrypted_data).decode()
# 示例使用
key = b"1234567890abcdef" # 16字节密钥
data = "Hello, AES CBC!"
encrypted = aes_encrypt_with_dynamic_iv(data, key)
print("加密后的数据:", encrypted)
decrypted = aes_decrypt_with_dynamic_iv(encrypted, key)
print("解密后的数据:", decrypted)
---
动态 IV 的关键点
1. IV 的生成:通过 random_bytes (PHP) 或 os.urandom (Python) 随机生成。
2. IV 的存储或传输:将 IV 拼接在密文前(或通过其他方式存储),以便在解密时使用。
3. 安全性提升:动态 IV 避免了使用固定 IV 时的加密模式分析风险。
输出示例
加密后的数据会随 IV 的变化而变化,但解密后原始数据保持不变。
以下是支持动态 IV 的 PHP 和 Python 示例代码。
---
PHP 示例代码
<?php
function aesEncryptWithDynamicIV($data, $key) {
$iv = random_bytes(16); // 动态生成随机IV
$paddedData = pkcs7Pad($data, 16);
$encryptedData = openssl_encrypt($paddedData, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv);
return base64_encode($iv . $encryptedData); // IV 和密文拼接后返回
}
function aesDecryptWithDynamicIV($encryptedData, $key) {
$decodedData = base64_decode($encryptedData);
$iv = substr($decodedData, 0, 16); // 提取前16字节作为IV
$encryptedData = substr($decodedData, 16); // 提取剩余部分作为密文
$decryptedData = openssl_decrypt($encryptedData, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv);
return pkcs7Unpad($decryptedData);
}
function pkcs7Pad($data, $blockSize) {
$padLength = $blockSize - (strlen($data) % $blockSize);
return $data . str_repeat(chr($padLength), $padLength);
}
function pkcs7Unpad($data) {
$padLength = ord(substr($data, -1));
return substr($data, 0, -$padLength);
}
// 示例使用
$key = "1234567890abcdef"; // 16字节密钥
$data = "Hello, AES CBC!";
$encrypted = aesEncryptWithDynamicIV($data, $key);
echo "加密后的数据: " . $encrypted . PHP_EOL;
$decrypted = aesDecryptWithDynamicIV($encrypted, $key);
echo "解密后的数据: " . $decrypted . PHP_EOL;
?>
---
Python 示例代码
from Crypto.Cipher import AES
import base64
import os
def pkcs7_pad(data, block_size):
pad_length = block_size - len(data) % block_size
return data + chr(pad_length).encode() * pad_length
def pkcs7_unpad(data):
pad_length = data[-1]
return data[:-pad_length]
def aes_encrypt_with_dynamic_iv(data, key):
iv = os.urandom(16) # 动态生成随机IV
cipher = AES.new(key, AES.MODE_CBC, iv)
padded_data = pkcs7_pad(data.encode(), AES.block_size)
encrypted_data = cipher.encrypt(padded_data)
return base64.b64encode(iv + encrypted_data).decode() # IV 和密文拼接后返回
def aes_decrypt_with_dynamic_iv(encrypted_data, key):
decoded_data = base64.b64decode(encrypted_data)
iv = decoded_data[:16] # 提取前16字节作为IV
encrypted_data = decoded_data[16:] # 提取剩余部分作为密文
cipher = AES.new(key, AES.MODE_CBC, iv)
decrypted_data = cipher.decrypt(encrypted_data)
return pkcs7_unpad(decrypted_data).decode()
# 示例使用
key = b"1234567890abcdef" # 16字节密钥
data = "Hello, AES CBC!"
encrypted = aes_encrypt_with_dynamic_iv(data, key)
print("加密后的数据:", encrypted)
decrypted = aes_decrypt_with_dynamic_iv(encrypted, key)
print("解密后的数据:", decrypted)
---
动态 IV 的关键点
1. IV 的生成:通过 random_bytes (PHP) 或 os.urandom (Python) 随机生成。
2. IV 的存储或传输:将 IV 拼接在密文前(或通过其他方式存储),以便在解密时使用。
3. 安全性提升:动态 IV 避免了使用固定 IV 时的加密模式分析风险。
输出示例
加密后的数据会随 IV 的变化而变化,但解密后原始数据保持不变。