国内流行的内容管理系统(CMS)多端全媒体解决方案 https://www.dedebiz.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

164 lines
4.9KB

  1. <?php
  2. if (!defined('DEDEINC')) exit('dedebiz');
  3. /**
  4. * PKCS7算法 - 加解密
  5. * Class PKCS7Encoder
  6. */
  7. class PKCS7Encoder
  8. {
  9. public static $blockSize = 32;
  10. /**
  11. * 对需要加密的明文进行填充补位
  12. * @param string $text 需要进行填充补位操作的明文
  13. * @return string 补齐明文字符串
  14. */
  15. function encode($text)
  16. {
  17. $amount_to_pad = PKCS7Encoder::$blockSize - (strlen($text) % PKCS7Encoder::$blockSize);
  18. if ($amount_to_pad == 0) {
  19. $amount_to_pad = PKCS7Encoder::$blockSize;
  20. }
  21. list($pad_chr, $tmp) = [chr($amount_to_pad), ''];
  22. for ($index = 0; $index < $amount_to_pad; $index++) {
  23. $tmp .= $pad_chr;
  24. }
  25. return $text.$tmp;
  26. }
  27. /**
  28. * 对解密后的明文进行补位删除
  29. * @param string $text 解密后的明文
  30. * @return string 删除填充补位后的明文
  31. */
  32. function decode($text)
  33. {
  34. $pad = ord(substr($text, -1));
  35. if ($pad < 1 || $pad > PKCS7Encoder::$blockSize) {
  36. $pad = 0;
  37. }
  38. return substr($text, 0, strlen($text) - $pad);
  39. }
  40. }
  41. /**
  42. * 公众号消息 - 加解密
  43. * Class Prpcrypt
  44. */
  45. class Prpcrypt
  46. {
  47. public $key;
  48. /**
  49. * Prpcrypt constructor.
  50. * @param $key
  51. */
  52. function __construct($key)
  53. {
  54. $this->key = base64_decode("{$key}=");
  55. }
  56. /**
  57. * 对明文进行加密
  58. * @param string $text 需要加密的明文
  59. * @param string $appid 公众号APPID
  60. * @return array
  61. */
  62. public function encrypt($text, $appid)
  63. {
  64. try {
  65. $random = $this->getRandomStr();
  66. $iv = substr($this->key, 0, 16);
  67. $pkcEncoder = new PKCS7Encoder();
  68. $text = $pkcEncoder->encode($random.pack("N", strlen($text)).$text.$appid);
  69. $encrypted = openssl_encrypt($text, 'AES-256-CBC', substr($this->key, 0, 32), OPENSSL_ZERO_PADDING, $iv);
  70. return [ErrorCode::$OK, $encrypted];
  71. } catch (Exception $e) {
  72. return [ErrorCode::$EncryptAESError, null];
  73. }
  74. }
  75. /**
  76. * 对密文进行解密
  77. * @param string $encrypted 需要解密的密文
  78. * @return array
  79. */
  80. public function decrypt($encrypted)
  81. {
  82. try {
  83. $iv = substr($this->key, 0, 16);
  84. $decrypted = openssl_decrypt($encrypted, 'AES-256-CBC', substr($this->key, 0, 32), OPENSSL_ZERO_PADDING, $iv);
  85. } catch (Exception $e) {
  86. return [ErrorCode::$DecryptAESError, null];
  87. }
  88. try {
  89. $pkcEncoder = new PKCS7Encoder();
  90. $result = $pkcEncoder->decode($decrypted);
  91. if (strlen($result) < 16) {
  92. return [ErrorCode::$DecryptAESError, null];
  93. }
  94. $content = substr($result, 16, strlen($result));
  95. $len_list = unpack("N", substr($content, 0, 4));
  96. $xml_len = $len_list[1];
  97. return [0, substr($content, 4, $xml_len), substr($content, $xml_len + 4)];
  98. } catch (Exception $e) {
  99. return [ErrorCode::$IllegalBuffer, null];
  100. }
  101. }
  102. /**
  103. * 随机生成16位字符串
  104. * @param string $str
  105. * @return string 生成的字符串
  106. */
  107. function getRandomStr($str = "")
  108. {
  109. $str_pol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
  110. $max = strlen($str_pol) - 1;
  111. for ($i = 0; $i < 16; $i++) {
  112. $str .= $str_pol[mt_rand(0, $max)];
  113. }
  114. return $str;
  115. }
  116. }
  117. /**
  118. * 仅用作类内部使用
  119. * 不用于官方API接口的errCode码
  120. * Class ErrorCode
  121. */
  122. class ErrorCode
  123. {
  124. public static $OK = 0;
  125. public static $ParseXmlError = 40002;
  126. public static $IllegalAesKey = 40004;
  127. public static $IllegalBuffer = 40008;
  128. public static $EncryptAESError = 40006;
  129. public static $DecryptAESError = 40007;
  130. public static $EncodeBase64Error = 40009;
  131. public static $DecodeBase64Error = 40010;
  132. public static $GenReturnXmlError = 40011;
  133. public static $ValidateAppidError = 40005;
  134. public static $ComputeSignatureError = 40003;
  135. public static $ValidateSignatureError = 40001;
  136. public static $errCode = [
  137. '0' => '处理成功',
  138. '40001' => '校验签名失败',
  139. '40002' => '解析xml失败',
  140. '40003' => '计算签名失败',
  141. '40004' => '不合法的AESKey',
  142. '40005' => '校验AppID失败',
  143. '40006' => 'AES加密失败',
  144. '40007' => 'AES解密失败',
  145. '40008' => '公众平台发送的xml不合法',
  146. '40009' => 'Base64编码失败',
  147. '40010' => 'Base64解码失败',
  148. '40011' => '公众帐号生成回包xml失败',
  149. ];
  150. /**
  151. * 获取错误消息内容
  152. * @param string $code 错误代码
  153. * @return bool
  154. */
  155. public static function getErrText($code)
  156. {
  157. if (isset(self::$errCode[$code])) {
  158. return self::$errCode[$code];
  159. }
  160. return false;
  161. }
  162. }
  163. ?>