在 PHP 中实现与 OpenSSL 兼容的 ‌AES 加密（含 Salted__ 头）‌，需手动处理盐值生成和密钥派生。以下是完整实现代码及分步说明：一、加密实现代码<?php /** * AES 加密（兼容 OpenSSL 的 "Salted__" 格式） * @param string $data 明文数据 * @param string $password 加密密码 * @param string $method 加密算法，如 'AES-256-CBC' * @return string Base64 编码的加密数据（含 Salted__ 头） */ function opensslEncryptWithSalt($data, $password, $method = 'AES-256-CBC') { // 生成 8 字节随机盐 $salt = openssl_random_pseudo_bytes(8); // 通过盐和密码派生密钥与 IV $keyIv = deriveKeyAndIV($password, $salt, $method); $key = $keyIv['key']; $iv = $keyIv['iv']; // 加密数据 $encrypted = openssl_encrypt($data, $method, $key, OPENSSL_RAW_DATA, $iv); // 拼接 Salted__ 头 + 盐 + 密文 $result = "Salted__" . $salt . $encrypted; // Base64 编码便于传输 return base64_encode($result); } /** * 派生密钥和 IV（模拟 OpenSSL 的 EVP_BytesToKey） */ function deriveKeyAndIV($password, $salt, $method) { $digest = 'md5'; // OpenSSL 默认使用 MD5 $keySize = 32; // AES-256 需要 32 字节密钥 $ivSize = 16; // CBC 模式需要 16 字节 IV $derived = ''; $data = ''; $length = 0; while ($length < $keySize + $ivSize) { $data = $data . $password . $salt; $md5 = hash($digest, $data, true); $data = $md5; $derived .= $md5; $length += strlen($md5); } return [ 'key' => substr($derived, 0, $keySize), 'iv' => substr($derived, $keySize, $ivSize) ]; } 二、解密实现代码<?php /** * AES 解密（兼容 OpenSSL 的 "Salted__" 格式） * @param string $encryptedData Base64 编码的加密数据 * @param string $password 解密密码 * @param string $method 加密算法，如 'AES-256-CBC' * @return string 解密后的明文 */ function opensslDecryptWithSalt($encryptedData, $password, $method = 'AES-256-CBC') { // 解码 Base64 $data = base64_decode($encryptedData); // 提取盐（前 8 字节，跳过 "Salted__" 头） $salt = substr($data, 8, 8); // 提取密文（去除头部的 16 字节：Salted__ + 盐） $encrypted = substr($data, 16); // 派生密钥和 IV $keyIv = deriveKeyAndIV($password, $salt, $method); $key = $keyIv['key']; $iv = $keyIv['iv']; // 解密数据 return openssl_decrypt($encrypted, $method, $key, OPENSSL_RAW_DATA, $iv); } 三、使用示例<?php // 加密示例 $plaintext = "Hello, World!"; $password = "mySecretPassword"; $encrypted = opensslEncryptWithSalt($plaintext, $password); echo "加密结果: " . $encrypted . "\n"; // 解密示例 $decrypted = opensslDecryptWithSalt($encrypted, $password); echo "解密结果: " . $decrypted . "\n"; 四、核心逻辑说明‌1. 盐值生成‌使用 openssl_random_pseudo_bytes(8) 生成 8 字节随机盐，确保每次加密结果不同。2‌. 密钥派生‌通过 ‌EVP_BytesToKey‌ 算法（模拟 OpenSSL 默认行为）派生密钥和 IV：使用 MD5 哈希（出于兼容性考虑，尽管不够安全）多次迭代拼接 $password + $salt 生成足够长度的密钥和 IV‌3. 数据格式‌加密结果格式为：Base64编码( "Salted__" + 8字节盐 + 密文 )‌算法兼容性‌支持 AES-128-CBC、AES-256-CBC 等常见算法与 OpenSSL 命令行加密结果互解：# 加密 openssl enc -aes-256-cbc -pass pass:mySecretPassword -S $(echo -n "SALT_HEX" | xxd -r -p) -a -p 五、注意事项1‌. 安全性建议‌优先使用更安全的密钥派生方式（如 PBKDF2），但需放弃与 OpenSSL 的兼容性避免使用弱密码或固定盐值‌2. 错误处理‌添加异常捕获：<?php try { $encrypted = openssl_encrypt(...); if ($encrypted === false) { throw new Exception('加密失败: ' . openssl_error_string()); } } catch (Exception $e) { die("错误: " . $e->getMessage()); } 3‌. 编码格式‌明文数据需为二进制格式（若含中文需统一编码，如 UTF-8）密文通过 Base64 编码避免传输乱码通过上述代码，可实现与 OpenSSL Salted__ 格式完全兼容的 AES 加密/解密，确保跨平台数据交换的可靠性。