|
|
@@ -0,0 +1,103 @@
|
|
|
+<?php
|
|
|
+
|
|
|
+namespace App\Module\Plug\Uraus;
|
|
|
+
|
|
|
+use UCore\Exception\LogicException;
|
|
|
+
|
|
|
+class CryptoService
|
|
|
+{
|
|
|
+
|
|
|
+ private string $key;
|
|
|
+ private int $timeout;
|
|
|
+
|
|
|
+ public function __construct(string $key, int $timeout = 300)
|
|
|
+ {
|
|
|
+ $this->key = $key;
|
|
|
+ $this->timeout = $timeout;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 加密
|
|
|
+ * @param array $data
|
|
|
+ * @return array
|
|
|
+ * @throws LogicException
|
|
|
+ * @throws \Random\RandomException
|
|
|
+ */
|
|
|
+ public function encrypt(array $data): array
|
|
|
+ {
|
|
|
+ $iv = random_bytes(16);
|
|
|
+ $timestamp = time();
|
|
|
+ $json = json_encode($data, JSON_UNESCAPED_UNICODE);
|
|
|
+
|
|
|
+ $encrypted = openssl_encrypt(
|
|
|
+ $json,
|
|
|
+ 'AES-256-CBC',
|
|
|
+ $this->key,
|
|
|
+ OPENSSL_RAW_DATA,
|
|
|
+ $iv
|
|
|
+ );
|
|
|
+
|
|
|
+ if ($encrypted === false) {
|
|
|
+ throw new LogicException('加密失败: ' . openssl_error_string());
|
|
|
+ }
|
|
|
+
|
|
|
+ $dataBase64 = base64_encode($encrypted);
|
|
|
+ $ivBase64 = base64_encode($iv);
|
|
|
+
|
|
|
+ return [
|
|
|
+ 'data' => $dataBase64,
|
|
|
+ 'iv' => $ivBase64,
|
|
|
+ 'timestamp' => $timestamp,
|
|
|
+ 'sign' => hash('sha256', $dataBase64 . $ivBase64 . $timestamp . $this->key)
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 解密
|
|
|
+ *
|
|
|
+ * @param array $encryptedData
|
|
|
+ * @return array
|
|
|
+ * @throws LogicException
|
|
|
+ */
|
|
|
+ public function decrypt(array $encryptedData): array
|
|
|
+ {
|
|
|
+ // 验证时间戳
|
|
|
+ if (abs(time() - $encryptedData['timestamp']) > $this->timeout) {
|
|
|
+ throw new LogicException('请求已过期');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证签名
|
|
|
+ $sign = hash('sha256',
|
|
|
+ $encryptedData['data'] .
|
|
|
+ $encryptedData['iv'] .
|
|
|
+ $encryptedData['timestamp'] .
|
|
|
+ $this->key
|
|
|
+ );
|
|
|
+
|
|
|
+ if (!hash_equals($sign, $encryptedData['sign'])) {
|
|
|
+ throw new LogicException('签名验证失败');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 解密数据
|
|
|
+ $decrypted = openssl_decrypt(
|
|
|
+ base64_decode($encryptedData['data']),
|
|
|
+ 'AES-256-CBC',
|
|
|
+ $this->key,
|
|
|
+ OPENSSL_RAW_DATA,
|
|
|
+ base64_decode($encryptedData['iv'])
|
|
|
+ );
|
|
|
+
|
|
|
+ if ($decrypted === false) {
|
|
|
+ throw new LogicException('解密失败: ' . openssl_error_string());
|
|
|
+ }
|
|
|
+
|
|
|
+ $data = json_decode($decrypted, true);
|
|
|
+ if (json_last_error() !== JSON_ERROR_NONE) {
|
|
|
+ throw new LogicException('JSON解析失败: ' . json_last_error_msg());
|
|
|
+ }
|
|
|
+
|
|
|
+ return $data;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|