PHP实现AES对称加密

背景

在开发支付宝小程序时,获取用户手机号,需要AES解密得到手机号明文。
官方并没有提供PHP解密的实例,所以要用PHP实现AES算法的解密过程。

要点

  1. PHP实现AES解密可以用 mcrypt 类方法,以及 openssl 族的方法。mcrypt 在PHP7.2被弃用,所以推荐使用 openssl 实现。
  2. screct_key 即 aes_key 是从支付宝小程序管理中心后台获取的。

实现过程

openssl 实现方式

/**
     * openssl 解密
     * @param unknown $encryptedData
     * @return string
     */
    protected static function decryptOpenssl($encryptedData, $screct_key) {
        $aesKey = base64_decode($screct_key);
        $aesIV = null;
        $aesCipher = base64_decode($encryptedData);
        $result = openssl_decrypt($aesCipher, "AES-128-CBC", $aesKey, 1, $aesIV); //1=OPENSSL_RAW_DATA 模式
//      $result = openssl_decrypt($aesCipher, "AES-128-CBC", $aesKey, 2, $aesIV);
        return $result;
    }

options 参数即为重要,它是兼容 mcrpty 算法的关键:

options = 0: 默认模式,自动对明文进行 pkcs7 padding,且数据做 base64 编码处理。
options = 1: OPENSSL_RAW_DATA,自动对明文进行 pkcs7 padding, 且数据未经 base64 编码处理。这里的理解很重要
options = 2: OPENSSL_ZERO_PADDING,要求待加密的数据长度已按 "0" 填充与加密算法数据块长度对齐,即同 mcrpty 默认填充的方式一致,且对数据做 base64 编码处理。注意,此模式下 openssl 要求待加密数据已按 "0" 填充好,其并不会自动帮你填充数据,如果未填充对齐,则会报错。

mcrypt 实现方式,可以参考alipay sdk 的aop/AopEnctypt.php 的 decrypt

class AliBizDataCrypt {
     * 解密方法
     *
     * @param string $encryptedData : 需要解密的报文
     * @return string
     */
    protected static function decrypt($encryptedData, $screct_key) {
        // AES, 128 模式加密数据 CBC
        $encryptedDataBase64Decoded = base64_decode($encryptedData);
        $screct_key = base64_decode($screct_key);
        // 设置全0的IV
        $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
        $iv = str_repeat("\0", $iv_size);
        $decrypt_str = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $screct_key, $encryptedDataBase64Decoded, MCRYPT_MODE_CBC, $iv);
        $decrypt_str = self::stripPKSC7Padding($decrypt_str);
        return $decrypt_str;
    }
    
    /**
     * 移去填充算法
     *
     * @param string $source
     * @return string
     */
    protected static function stripPKSC7Padding($source) {
        $char = substr($source, - 1);
        $num = ord($char);
        if( $num == 62 )
            return $source;
        $source = substr($source, 0, - $num);
        return $source;
    }
}   

猜你喜欢

转载自www.cnblogs.com/aworkstory/p/php-aes-symmetrical-encryption.html
今日推荐