RsaEncryptionService.php 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. <?php
  2. namespace App\Service;
  3. class RsaEncryptionService extends Service
  4. {
  5. // public function encrypt($data)
  6. // {
  7. // //公钥文件位于 storage/app/public/rsa/public.pem
  8. // $publicKeyPath = storage_path('app/public/rsa/public.pem');
  9. // $publicKey = openssl_pkey_get_public(file_get_contents($publicKeyPath));
  10. //
  11. // openssl_public_encrypt($data, $encrypted, $publicKey);
  12. // return base64_encode($encrypted);
  13. // }
  14. public function encrypt($data){
  15. $data = json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); // 重新序列化,确保所有key按字典序排序
  16. // 公钥文件位于 storage/app/public/rsa/public.pem
  17. $publicKeyPath = storage_path('app/public/rsa/public.pem');
  18. // 确保文件存在
  19. if (!file_exists($publicKeyPath)) return [false , '公钥不存在'];
  20. // 读取公钥文件的内容
  21. $publicKeyContent = file_get_contents($publicKeyPath);
  22. if ($publicKeyContent === false) return [false , '公钥文件读取失败'];
  23. // 获取公钥资源
  24. $publicKey = openssl_pkey_get_public($publicKeyContent);
  25. if (! $publicKey) {
  26. $error = openssl_error_string();
  27. if ($error !== false) {
  28. return [false , '公钥文件加载失败:' . $error];
  29. } else {
  30. return [false , '公钥文件加载失败'];
  31. }
  32. }
  33. // 假设 $publicKey 是你已经获取的公钥资源
  34. // $keyDetails = openssl_pkey_get_details($publicKey);
  35. // $keyBits = $keyDetails['bits'];
  36. // PKCS#1 v1.5 填充的最大数据长度
  37. // $maxDataLengthPkcs1 = floor($keyBits / 8) - 11;
  38. // OAEP 填充的最大数据长度
  39. // $maxDataLengthOaep = floor($keyBits / 8) - 42;
  40. // echo "For PKCS#1 v1.5 padding, the maximum data length is: {$maxDataLengthPkcs1} bytes.\n";
  41. // echo "For OAEP padding, the maximum data length is: {$maxDataLengthOaep} bytes.\n";
  42. if (! openssl_public_encrypt($data, $encrypted, $publicKey)) {
  43. $error = openssl_error_string();
  44. if ($error !== false) {
  45. return [false , '加密失败:' . $error];
  46. } else {
  47. return [false , '加密失败'];
  48. }
  49. }
  50. // 返回base64编码的加密数据
  51. return [true, base64_encode($encrypted)];
  52. }
  53. function encrypt2($data) {
  54. // 公钥文件
  55. $publicKeyString = storage_path('app/public/rsa/public.pem');
  56. // 读取公钥文件内容
  57. $publicKeyString = file_get_contents($publicKeyString);
  58. //加密的数据
  59. $plainText = json_encode($data);
  60. // 生成随机AES密钥以进行对称加密
  61. $aesKey = openssl_random_pseudo_bytes(16); // AES-128
  62. // 使用AES加密明文
  63. $ivlen = openssl_cipher_iv_length('aes-128-cbc');
  64. $iv = openssl_random_pseudo_bytes($ivlen);
  65. $encryptedBytes = openssl_encrypt($plainText, 'aes-128-cbc', $aesKey, OPENSSL_RAW_DATA, $iv);
  66. // 使用RSA加密AES密钥
  67. $resource = openssl_pkey_get_public($publicKeyString);
  68. openssl_public_encrypt($aesKey, $encryptedAESKey, $resource);
  69. // 组合AES密钥和加密的消息
  70. $encryptedAESKeyStr = base64_encode($encryptedAESKey);
  71. $encryptedMessageStr = base64_encode($iv . $encryptedBytes);
  72. //AES的密钥 : 传递的参数
  73. return $encryptedAESKeyStr . ":" . $encryptedMessageStr;
  74. }
  75. function decrypt2($encryptedText) {
  76. // 密钥文件
  77. $privateKeyString = storage_path('app/public/rsa/private.pem');
  78. // 读取密钥文件内容
  79. $privateKeyString = file_get_contents($privateKeyString);
  80. // 将输入分成加密的AES密钥和加密的消息两部分
  81. list($encryptedAESKeyStr, $encryptedMessageStr) = explode(":", $encryptedText, 2);
  82. if (!isset($encryptedAESKeyStr) || !isset($encryptedMessageStr)) {
  83. throw new \Exception("无效的输入格式");
  84. }
  85. // 使用RSA私钥解密AES密钥
  86. $resource = openssl_pkey_get_private($privateKeyString);
  87. $encryptedAESKey = base64_decode($encryptedAESKeyStr);
  88. openssl_private_decrypt($encryptedAESKey, $decryptedAESKey, $resource);
  89. // 使用AES解密消息
  90. $ivlen = openssl_cipher_iv_length('aes-128-cbc');
  91. $encryptedMessage = base64_decode($encryptedMessageStr);
  92. $iv = substr($encryptedMessage, 0, $ivlen);
  93. $ciphertext = substr($encryptedMessage, $ivlen);
  94. $plaintext = openssl_decrypt($ciphertext, 'aes-128-cbc', $decryptedAESKey, OPENSSL_RAW_DATA, $iv);
  95. return $plaintext;
  96. }
  97. // 加密函数
  98. function aesEncrypt($data) {
  99. $data = json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); // 重新序列化,确保所有key按字典序排序
  100. // 密钥文件
  101. $key = storage_path('app/public/rsa/public.pem');
  102. // 读取密钥文件内容
  103. $key = file_get_contents($key);
  104. // 生成一个随机的初始化向量(IV)
  105. $ivSize = openssl_cipher_iv_length('aes-256-cbc');
  106. $iv = openssl_random_pseudo_bytes($ivSize);
  107. // 加密数据
  108. $encrypted = openssl_encrypt($data, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
  109. if ($encrypted === false) return [false, '加密失败'];
  110. // 将 IV 和加密后的数据一起返回,以便解密时使用
  111. return [true, base64_encode($iv) . ":" . base64_encode($encrypted)];
  112. }
  113. // 解密函数
  114. function aesDecrypt($data) {
  115. // 公钥文件位于 storage/app/public/rsa/public.pem
  116. $key = storage_path('app/public/rsa/public.pem');
  117. // 读取密钥文件内容
  118. $key = file_get_contents($key);
  119. // 分割字符串,去除冒号
  120. list($ivPart, $encryptedPart) = explode(':', $data, 2);
  121. $ivPart = base64_decode($ivPart);
  122. $encryptedPart = base64_decode($encryptedPart);
  123. // 获取 IV 和加密后的数据
  124. $ivSize = openssl_cipher_iv_length('aes-256-cbc');
  125. $iv = substr($ivPart, 0, $ivSize);
  126. $encrypted = $encryptedPart;
  127. // 解密数据
  128. $decrypted = openssl_decrypt($encrypted, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
  129. if ($decrypted === false) {
  130. throw new \Exception('Decryption failed.');
  131. }
  132. return $decrypted;
  133. }
  134. }