背景
在开发支付宝小程序时,获取用户手机号,需要AES解密得到手机号明文。
官方并没有提供PHP解密的实例,所以要用PHP实现AES算法的解密过程。
要点
- PHP实现AES解密可以用 mcrypt 类方法,以及 openssl 族的方法。mcrypt 在PHP7.2被弃用,所以推荐使用 openssl 实现。
- 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("