小蒋同学 - 2025年3月
type: channel
link: https://www.eybk.cn/2025/03/
description: 小蒋同学
items: CryptoJS aes加密的数据包含Salted__ 如何使用php实现

CryptoJS aes加密的数据包含Salted__ 如何使用php实现
type: item
date: 2025-03-25T01:39:00+08:00
description: 在 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 = open…