【原】微信企业号加密类库详解(上)
in 备忘 with 0 comment

【原】微信企业号加密类库详解(上)

in 备忘 with 0 comment

要把同道的人当作朋友,而不必把同利的人当作朋友。 --罗兰


上次曾经分享过一个自己写的微信操作类,虽然有注释,但是看起来还是有些费力。今天同样给大伙带来一篇微信相关的文章,今天主要谈的是微信数据加密类的实现,这次的分享,我会细致的一步步的说明这个类的工作原理。不过值得一提的是,我用的加密类是98%官方源码+2%自定义代码。所以,想要看明白并且成功的用起来,还是需要有一定PHP基础的。

文件名及文件作用

 1. ErrorCode.php [ 定义错误码 ]
 2. Pkcs7Encoder.php [ 基于PKCS7算法的加解密 ]
 3. Prpcrypt.php [ 加解密接口 ]
 4. Sha1.php [ 用SHA1算法生成安全签名 ]
 5. WxCrypt.php [ 应对各个场景做的函数封装相比于加解密接口更具有针对性 ]

ErrorCode.php

这个文件主要是统一返回码的,对各个错误类型进行了全局的控制,为调试带来便利,这个文件没啥好说的,就是定义了一堆常量而已。

常量名常量值说明
OK0没有错误
ValidateSignatureError-40001签名验证错误
ParseXmlError-40002xml解析失败
ComputeSignatureError-40003sha加密生成签名失败
IllegalAesKey-40004encodingAesKey非法
ValidateCorpidError-40005corpid 校验错误
EncryptAESError-40006aes 加密失败
DecryptAESError-40007aes 解密失败
IllegalBuffer-40008解密后得到的buffer非法
EncodeBase64Error-40009base64加密失败
DecodeBase64Error-40010base64解密失败
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变的更加安全可靠。

Comments are closed.