up. 双向数据加密
This commit is contained in:
parent
7a072e4bec
commit
bae500bd2c
@ -160,45 +160,48 @@ class ContextMiddleware extends middleware
|
||||
* @throws ValidateException 解密失败时抛出异常
|
||||
*/
|
||||
private function decryptCryptoJSData(string $encryptedData): array
|
||||
{// 1. Base64 解码加密数据
|
||||
$encrypted = base64_decode($encryptedData);
|
||||
{
|
||||
// Base64解码
|
||||
$data = base64_decode($encryptedData);
|
||||
|
||||
// 2. 提取初始化向量 (IV) - 前16字节
|
||||
if (strlen($encrypted) < 16) {
|
||||
throw new ValidateException('加密数据太短,无法提取IV');
|
||||
// 检查Salted__头
|
||||
if (!str_starts_with($data, "Salted__")) {
|
||||
throw new ValidateException('Invalid format: missing "Salted__" header');
|
||||
}
|
||||
|
||||
$iv = substr($encrypted, 0, 16);
|
||||
$ciphertext = substr($encrypted, 16);
|
||||
// 提取Salt (8字节)
|
||||
$salt = substr($data, 8, 8);
|
||||
$ct = substr($data, 16);
|
||||
|
||||
// 3. 准备解密密钥
|
||||
// CryptoJS 使用密钥派生函数,这里使用简单的 SHA256 哈希
|
||||
$key = substr(hash('sha256', self::DATA_SECRET_KEY, true), 0, 32);
|
||||
// 通过EVP_BytesToKey派生密钥和IV
|
||||
$keyIv = $this->evpBytesToKey($salt);
|
||||
$key = $keyIv['key'];
|
||||
$iv = $keyIv['iv'];
|
||||
|
||||
// 4. 使用 AES-256-CBC 解密
|
||||
// AES-256-CBC解密
|
||||
$decrypted = openssl_decrypt(
|
||||
$ciphertext,
|
||||
'AES-256-CBC',
|
||||
$ct,
|
||||
'aes-256-cbc',
|
||||
$key,
|
||||
OPENSSL_RAW_DATA,
|
||||
$iv
|
||||
);
|
||||
|
||||
if ($decrypted === false) {
|
||||
throw new ValidateException('解密失败: ' . openssl_error_string());
|
||||
return json_decode($decrypted, true);
|
||||
}
|
||||
|
||||
// 5. 移除 PKCS#7 填充
|
||||
$padding = ord($decrypted[strlen($decrypted) - 1]);
|
||||
$decrypted = substr($decrypted, 0, -$padding);
|
||||
|
||||
// 6. 解析为 JSON
|
||||
$data = json_decode($decrypted, true);
|
||||
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
throw new ValidateException('JSON 解析失败: ' . json_last_error_msg());
|
||||
private function evpBytesToKey($salt): array
|
||||
{
|
||||
$password = self::DATA_SECRET_KEY;
|
||||
$bytes = '';
|
||||
$last = '';
|
||||
// 生成48字节:32字节key + 16字节IV
|
||||
while(strlen($bytes) < 48) {
|
||||
$last = md5($last . $password . $salt, true);
|
||||
$bytes .= $last;
|
||||
}
|
||||
|
||||
return $data;
|
||||
return [
|
||||
'key' => substr($bytes, 0, 32),
|
||||
'iv' => substr($bytes, 32, 16)
|
||||
];
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user