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