|
|
|
|
<?php
|
|
|
|
|
// +----------------------------------------------------------------------
|
|
|
|
|
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
|
|
|
|
|
// +----------------------------------------------------------------------
|
|
|
|
|
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
|
|
|
|
|
// +----------------------------------------------------------------------
|
|
|
|
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
|
|
|
|
// +----------------------------------------------------------------------
|
|
|
|
|
// | Author: 麦当苗儿 <zuojiazi.cn@gmail.com> <http://www.zjzit.cn>
|
|
|
|
|
// +----------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
namespace Com;
|
|
|
|
|
|
|
|
|
|
class WechatCrypt{
|
|
|
|
|
/**
|
|
|
|
|
* 加密KEY
|
|
|
|
|
* @var string
|
|
|
|
|
*/
|
|
|
|
|
private $cyptKey = '';
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 公众平台APPID
|
|
|
|
|
* @var string
|
|
|
|
|
*/
|
|
|
|
|
private $appId = '';
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 构造方法,初始化加密KEY
|
|
|
|
|
* @param string $key 加密KEY
|
|
|
|
|
* @param string $appid 微信APP_KEY
|
|
|
|
|
*/
|
|
|
|
|
public function __construct($key, $appid){
|
|
|
|
|
if($key && $appid){
|
|
|
|
|
$this->appId = $appid;
|
|
|
|
|
$this->cyptKey = base64_decode($key . '=');
|
|
|
|
|
} else {
|
|
|
|
|
throw new \Exception('缺少参数 APP_ID 和加密KEY!');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 对明文进行加密
|
|
|
|
|
* @param string $text 需要加密的字符串
|
|
|
|
|
* @return string 密文字符串
|
|
|
|
|
*/
|
|
|
|
|
public function encrypt($text){
|
|
|
|
|
//填充到明文之前的随机字符
|
|
|
|
|
$random = self::getRandomStr(16);
|
|
|
|
|
|
|
|
|
|
//网络字节序
|
|
|
|
|
$size = pack("N", strlen($text));
|
|
|
|
|
|
|
|
|
|
//生成被加密字符串
|
|
|
|
|
$text = $random . $size . $text . $this->appId;
|
|
|
|
|
|
|
|
|
|
//打开加密算法模块
|
|
|
|
|
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
|
|
|
|
|
|
|
|
|
|
//使用PKCS7对明文进行补位
|
|
|
|
|
$text = self::PKCS7Encode($text, mcrypt_enc_get_key_size($td));
|
|
|
|
|
|
|
|
|
|
//初始化加密算法模块
|
|
|
|
|
mcrypt_generic_init($td, $this->cyptKey, substr($this->cyptKey, 0, 16));
|
|
|
|
|
|
|
|
|
|
//执行加密
|
|
|
|
|
$encrypt = mcrypt_generic($td, $text);
|
|
|
|
|
|
|
|
|
|
//关闭加密算法模块
|
|
|
|
|
mcrypt_generic_deinit($td);
|
|
|
|
|
mcrypt_module_close($td);
|
|
|
|
|
|
|
|
|
|
//输出密文
|
|
|
|
|
return base64_encode($encrypt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 对密文进行解密
|
|
|
|
|
* @param string $encrypt 密文
|
|
|
|
|
* @return string 明文
|
|
|
|
|
*/
|
|
|
|
|
public function decrypt($encrypt){
|
|
|
|
|
//BASE64解码
|
|
|
|
|
$encrypt = base64_decode($encrypt);
|
|
|
|
|
|
|
|
|
|
//打开加密算法模块
|
|
|
|
|
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
|
|
|
|
|
|
|
|
|
|
//初始化加密算法模块
|
|
|
|
|
mcrypt_generic_init($td, $this->cyptKey, substr($this->cyptKey, 0, 16));
|
|
|
|
|
|
|
|
|
|
//执行解密
|
|
|
|
|
$decrypt = mdecrypt_generic($td, $encrypt);
|
|
|
|
|
|
|
|
|
|
//去除PKCS7补位
|
|
|
|
|
$decrypt = self::PKCS7Decode($decrypt, mcrypt_enc_get_key_size($td));
|
|
|
|
|
|
|
|
|
|
//关闭加密算法模块
|
|
|
|
|
mcrypt_generic_deinit($td);
|
|
|
|
|
mcrypt_module_close($td);
|
|
|
|
|
|
|
|
|
|
if(strlen($decrypt) < 16){
|
|
|
|
|
throw new \Exception("非法密文字符串!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//去除随机字符串
|
|
|
|
|
$decrypt = substr($decrypt, 16);
|
|
|
|
|
|
|
|
|
|
//获取网络字节序
|
|
|
|
|
$size = unpack("N", substr($decrypt, 0, 4));
|
|
|
|
|
$size = $size[1];
|
|
|
|
|
|
|
|
|
|
//APP_ID
|
|
|
|
|
$appid = substr($decrypt, $size + 4);
|
|
|
|
|
|
|
|
|
|
//验证APP_ID
|
|
|
|
|
if($appid !== $this->appId){
|
|
|
|
|
throw new \Exception("非法APP_ID!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//明文内容
|
|
|
|
|
$text = substr($decrypt, 4, $size);
|
|
|
|
|
|
|
|
|
|
return $text;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* PKCS7填充字符
|
|
|
|
|
* @param string $text 被填充字符
|
|
|
|
|
* @param integer $size Block长度
|
|
|
|
|
*/
|
|
|
|
|
private static function PKCS7Encode($text, $size){
|
|
|
|
|
//字符串长度
|
|
|
|
|
$str_size = strlen($text);
|
|
|
|
|
|
|
|
|
|
//填充长度
|
|
|
|
|
$pad_size = $size - ($str_size % $size);
|
|
|
|
|
$pad_size = $pad_size ? : $size;
|
|
|
|
|
|
|
|
|
|
//填充的字符
|
|
|
|
|
$pad_chr = chr($pad_size);
|
|
|
|
|
|
|
|
|
|
//执行填充
|
|
|
|
|
$text = str_pad($text, $str_size + $pad_size, $pad_chr, STR_PAD_RIGHT);
|
|
|
|
|
|
|
|
|
|
return $text;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 删除PKCS7填充的字符
|
|
|
|
|
* @param string $text 已填充的字符
|
|
|
|
|
* @param integer $size Block长度
|
|
|
|
|
*/
|
|
|
|
|
private static function PKCS7Decode($text, $size){
|
|
|
|
|
//获取补位字符
|
|
|
|
|
$pad_str = ord(substr($text, -1));
|
|
|
|
|
|
|
|
|
|
if ($pad_str < 1 || $pad_str > $size) {
|
|
|
|
|
return '';
|
|
|
|
|
} else {
|
|
|
|
|
return substr($text, 0, strlen($text) - $pad_str);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 生成指定长度的字符串
|
|
|
|
|
* @param integer $len 字符串长度
|
|
|
|
|
* @return string 生成的字符串
|
|
|
|
|
*/
|
|
|
|
|
private static function getRandomStr($len){
|
|
|
|
|
static $pol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
|
|
|
|
|
|
|
|
|
|
$str = '';
|
|
|
|
|
$max = strlen($pol) - 1;
|
|
|
|
|
for ($i = 0; $i < $len; $i++) {
|
|
|
|
|
$str .= $pol[mt_rand(0, $max)];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $str;
|
|
|
|
|
}
|
|
|
|
|
}
|