You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

181 lines
5.0 KiB
PHP

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?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;
}
}