CryptoService.php 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. <?php
  2. namespace ThirdParty\Urs\Util;
  3. use UCore\Exception\LogicException;
  4. class CryptoService
  5. {
  6. private string $key;
  7. private int $timeout;
  8. public function __construct(string $key, int $timeout = 300)
  9. {
  10. $this->key = $key;
  11. $this->timeout = $timeout;
  12. }
  13. /**
  14. * 加密
  15. * @param array $data
  16. * @return array
  17. * @throws LogicException
  18. * @throws \Random\RandomException
  19. */
  20. public function encrypt(array $data): array
  21. {
  22. $iv = random_bytes(16);
  23. $timestamp = time();
  24. $json = json_encode($data, JSON_UNESCAPED_UNICODE);
  25. $encrypted = openssl_encrypt(
  26. $json,
  27. 'AES-256-CBC',
  28. $this->key,
  29. OPENSSL_RAW_DATA,
  30. $iv
  31. );
  32. if ($encrypted === false) {
  33. throw new LogicException('加密失败: ' . openssl_error_string());
  34. }
  35. $dataBase64 = base64_encode($encrypted);
  36. $ivBase64 = base64_encode($iv);
  37. return [
  38. 'data' => $dataBase64,
  39. 'iv' => $ivBase64,
  40. 'timestamp' => $timestamp,
  41. 'sign' => hash('sha256', $dataBase64 . $ivBase64 . $timestamp . $this->key)
  42. ];
  43. }
  44. /**
  45. * 解密
  46. *
  47. * @param array $encryptedData
  48. * @return array
  49. * @throws LogicException
  50. */
  51. public function decrypt(array $encryptedData): array
  52. {
  53. // 验证时间戳
  54. if (abs(time() - $encryptedData['timestamp']) > $this->timeout) {
  55. throw new LogicException('请求已过期');
  56. }
  57. // 验证签名
  58. $sign = hash('sha256',
  59. $encryptedData['data'] .
  60. $encryptedData['iv'] .
  61. $encryptedData['timestamp'] .
  62. $this->key
  63. );
  64. if (!hash_equals($sign, $encryptedData['sign'])) {
  65. throw new LogicException('签名验证失败');
  66. }
  67. // 解密数据
  68. $decrypted = openssl_decrypt(
  69. base64_decode($encryptedData['data']),
  70. 'AES-256-CBC',
  71. $this->key,
  72. OPENSSL_RAW_DATA,
  73. base64_decode($encryptedData['iv'])
  74. );
  75. if ($decrypted === false) {
  76. throw new LogicException('解密失败: ' . openssl_error_string());
  77. }
  78. $data = json_decode($decrypted, true);
  79. if (json_last_error() !== JSON_ERROR_NONE) {
  80. throw new LogicException('JSON解析失败: ' . json_last_error_msg());
  81. }
  82. return $data;
  83. }
  84. }