Prpcrypt.php 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. <?php
  2. namespace wx\offiaccount\event;
  3. use wx\offiaccount\Event\PKCS7Encoder;
  4. use Exception;
  5. /**
  6. * Prpcrypt class
  7. *
  8. * 提供接收和推送给公众平台消息的加解密接口.
  9. */
  10. class Prpcrypt
  11. {
  12. public $key;
  13. function __construct($k)
  14. {
  15. $this->key = base64_decode($k . "=");
  16. }
  17. /**
  18. * 对明文进行加密
  19. * @param string $text 需要加密的明文
  20. * @return string 加密后的密文
  21. */
  22. public function encrypt($text, $appid)
  23. {
  24. try {
  25. $random = $this->getRandomStr();//"aaaabbbbccccdddd";
  26. $text = $random . pack("N", strlen($text)) . $text . $appid;
  27. $iv = substr($this->key, 0, 16);
  28. $pkc_encoder = new PKCS7Encoder();
  29. $text = $pkc_encoder->encode($text);
  30. $encrypted = openssl_encrypt($text,'AES-256-CBC',substr($this->key, 0, 32),OPENSSL_ZERO_PADDING,$iv);
  31. return array(ErrorCode::$OK, $encrypted);
  32. } catch (Exception $e) {
  33. //print $e;
  34. return array(ErrorCode::$EncryptAESError, null);
  35. }
  36. }
  37. /**
  38. * 对密文进行解密
  39. * @param string $encrypted 需要解密的密文
  40. * @return string 解密得到的明文
  41. */
  42. public function decrypt($encrypted, $appid)
  43. {
  44. try {
  45. $iv = substr($this->key, 0, 16);
  46. $decrypted = openssl_decrypt($encrypted,'AES-256-CBC',substr($this->key, 0, 32),OPENSSL_ZERO_PADDING,$iv);
  47. } catch (Exception $e) {
  48. return array(ErrorCode::$DecryptAESError, null);
  49. }
  50. try {
  51. //去除补位字符
  52. $pkc_encoder = new PKCS7Encoder();
  53. $result = $pkc_encoder->decode($decrypted);
  54. //去除16位随机字符串,网络字节序和AppId
  55. if (strlen($result) < 16)
  56. return "";
  57. $content = substr($result, 16, strlen($result));
  58. $len_list = unpack("N", substr($content, 0, 4));
  59. $xml_len = $len_list[1];
  60. $xml_content = substr($content, 4, $xml_len);
  61. $from_appid = substr($content, $xml_len + 4);
  62. if (!$appid)
  63. $appid = $from_appid;
  64. //如果传入的appid是空的,则认为是订阅号,使用数据中提取出来的appid
  65. } catch (Exception $e) {
  66. //print $e;
  67. return array(ErrorCode::$IllegalBuffer, null);
  68. }
  69. if ($from_appid != $appid)
  70. return array(ErrorCode::$ValidateAppidError, null);
  71. //不注释上边两行,避免传入appid是错误的情况
  72. return array(0, $xml_content, $from_appid);
  73. //增加appid,为了解决后面加密回复消息的时候没有appid的订阅号会无法回复
  74. }
  75. /**
  76. * 随机生成16位字符串
  77. * @return string 生成的字符串
  78. */
  79. function getRandomStr()
  80. {
  81. $str = "";
  82. $str_pol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
  83. $max = strlen($str_pol) - 1;
  84. for ($i = 0; $i < 16; $i++) {
  85. $str .= $str_pol[mt_rand(0, $max)];
  86. }
  87. return $str;
  88. }
  89. }