要把同道的人当作朋友,而不必把同利的人当作朋友。 --罗兰
上次曾经分享过一个自己写的微信操作类,虽然有注释,但是看起来还是有些费力。今天同样给大伙带来一篇微信相关的文章,今天主要谈的是微信数据加密类的实现,这次的分享,我会细致的一步步的说明这个类的工作原理。不过值得一提的是,我用的加密类是98%官方源码+2%自定义代码。所以,想要看明白并且成功的用起来,还是需要有一定PHP基础的。
文件名及文件作用
1. ErrorCode.php [ 定义错误码 ]
2. Pkcs7Encoder.php [ 基于PKCS7算法的加解密 ]
3. Prpcrypt.php [ 加解密接口 ]
4. Sha1.php [ 用SHA1算法生成安全签名 ]
5. WxCrypt.php [ 应对各个场景做的函数封装相比于加解密接口更具有针对性 ]
ErrorCode.php
这个文件主要是统一返回码的,对各个错误类型进行了全局的控制,为调试带来便利,这个文件没啥好说的,就是定义了一堆常量而已。
常量名 | 常量值 | 说明 |
---|---|---|
OK | 0 | 没有错误 |
ValidateSignatureError | -40001 | 签名验证错误 |
ParseXmlError | -40002 | xml解析失败 |
ComputeSignatureError | -40003 | sha加密生成签名失败 |
IllegalAesKey | -40004 | encodingAesKey非法 |
ValidateCorpidError | -40005 | corpid 校验错误 |
EncryptAESError | -40006 | aes 加密失败 |
DecryptAESError | -40007 | aes 解密失败 |
IllegalBuffer | -40008 | 解密后得到的buffer非法 |
EncodeBase64Error | -40009 | base64加密失败 |
DecodeBase64Error | -40010 | base64解密失败 |
GenReturnXmlError | -40011 | 生成xml失败 |
我们从错误类型就可以看出,微信为了提高安全性,对数据进行了两层加密,分别是AES和Base64。同时微信加密的身份令牌是用sha这个Hash算法计算出来的。最后就是在微信加解密的类库中,自带了关于XML的操作函数。
Pkcs7Encoder.php
这个类主要是用来实现基于PKCS7算法的加解密,何为PKCS7算法呢?我也不去百度了,直接根据代码,上个demo就可以了。
class Pkcs7Encoder {
public static $block_size = 32; //最终字符串长度必定是这个值得整数倍数
/**
* 对需要加密的明文进行填充补位
* @param $text 需要进行填充补位操作的明文
* @return 补齐明文字符串
*/
public function encode($text){
$block_size = self::$block_size;
//这里计算出现有字符串长度,假设现在字符串为“zxczxczxc” 那么它的长度就是9
$text_length = strlen($text);
//因为我们最终的字符长度一定是$block_size的整数倍,所以我们计算出后面还需要补上的字符个数,我们这里需要补上23个字符
$amount_to_pad = $block_size - ($text_length % $block_size);
//如果很凑巧原始字符串的长度就是$block_size的整数倍,那么我们就在原始字符串后边在接上长度为$block_size的字符串
if ($amount_to_pad == 0) {
$amount_to_pad = $block_size;
}
//根据需要补位的位数获得补位所用的字符,我们这里就是chr(23)
$pad_chr = chr($amount_to_pad);
$tmp = "";
for ($index = 0; $index < $amount_to_pad; $index++) {
$tmp .= $pad_chr;
}
//最终在原始字符串后边补上23个字符chr(23)
return $text . $tmp;
}
/**
* 对解密后的明文进行补位删除
* @param decrypted 解密后的明文
* @return 删除填充补位后的明文
*/
public function decode($text){
//根据补位函数,我们不难看出,字符串在补位后,最后一个字符一定是我们计算出来的特殊字符,也就是上面说的chr(23),这里用ord函数获得整数23 ,这个23就表示了我们最终在字符串后拼接了23个特殊字符
$pad = ord(substr($text, -1));
if ($pad < 1 || $pad > self::$block_size) {
$pad = 0;
}
//用substr函数截取出我们的原始字符串
return substr($text, 0, (strlen($text) - $pad));
}
}
这个类为原始的字符串进行了扰码的添加,更加提高了其安全性能。到这里我虽然还是不明白PKCS7的具体定义,但是可以知道,通过PKCS7可以为字符串加上扰码。
Sha1.php
这个类主要是用来生成计算身份令牌的,用于身份确认的。
//这个类,也就只有这么一个函数
public function getSHA1($token, $timestamp, $nonce, $encrypt_msg){
//排序
try {
//组成一个特定数组
$array = array($encrypt_msg, $token, $timestamp, $nonce);
//这是进行参数排序,其实这一步我个人认为是没有必要的,因为上一步我们已经手工排好了顺序了,这里再次排序就显得有点多余。当然,这里的排序代码不能去掉,因为微信服务端做了排序了,如果你去掉,那么验证肯定没法通过的。
sort($array, SORT_STRING);
$str = implode($array);
return array(ErrorCode::OK, sha1($str));
} catch (\Exception $e) {
print $e . "\n";
return array(ErrorCode::ComputeSignatureError, null);
}
}
基于时间戳,基于随机字符串,基于Token等计算出一个signal,从这里可以看出,微信在确认请求者身份这件事情上,也并没有什么特别的方法,也用了这种常见的认证方法。
最后说两句:今天我将加密系列类中的较为简单的三个类说了下,还有两个较为复杂的,甚至还夹杂了些业务逻辑的类,我打算明天再聊。另外,我希望这套接口验证,及数据加密形式能够给大家带来灵感,让大家的API变的更加安全可靠。
本文由 陌上花开 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: Jul 1, 2016 at 06:15 am