PHP 对称加密AES算法
PHP 支持多种加密解密算法,包含对称加密(可逆)和非对称加密(不可逆)
不可逆加密算法,包含md5、sha1等,可参加米扑博客:php 加密算法md5, sha1
更多加密算法,请见米扑博客:AES、DES、RSA三种典型加密算法(强烈推荐)
本文主要介绍AES对称加密,用到了 mcrypt 模块
AES 算法简介
AES(Advanced Encryption Standard,高级加密标准),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。
这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。经过五年的甄选流程,高级加密标准由美国国家标准与技术研究院(NIST)于2001年11月26日发布于FIPS PUB 197,并在2002年5月26日成为有效的标准。2006年,高级加密标准已然成为对称密钥加密中最流行的算法之一。
AES对称加密算法的加密和解密的密钥(密钥K)是相同的,米扑科技的项目、微信小程序加密传输等就是用这个加密算法的,具体的加密流程如下图:
AES是基于数据块的加密方式,每次处理的数据是一块16字节,当数据不是16字节的倍数时填充,这就是所谓的分组密码(区别于基于比特位的流密码),16字节是分组长度。
分组加密有几种方式分别是:
ECB:是一种基础的加密方式,密文被分割成分组长度相等的块(不足补齐),然后单独一个个加密,一个个输出组成密文。
CBC:是一种循环模式,前一个分组的密文和当前分组的明文异或操作后再加密,这样做的目的是增强破解难度。
CFB/OFB实际上是一种反馈模式,目的也是增强破解的难度。
ECB和CBC的加密结果是不一样的,两者的模式不同,而且CBC会在第一个密码块运算时加入一个初始化向量。
安装 mcrypt 库包
1. 下载 mcrypt
官方介绍:http://mcrypt.sourceforge.net
下载 libmcrypt 和 mcrypt:https://sourceforge.net/projects/mcrypt/files/
直接下载最新安装包:libmcrypt-2.5.8.tar.gz 和 mcrypt-2.6.8.tar.gz
2. 安装 libmcrypt 和 mcrypt
1)安装 libmcrypt
tar zxvf libmcrypt-2.5.8.tar.gz cd libmcrypt-2.5.8 ./configure make make install
2)安装 mcrypt
tar zxvf mcrypt-2.6.8.tar.gz cd mcrypt-2.6.8/ ln -s /usr/local/bin/libmcrypt-config /usr/bin/libmcrypt-config /sbin/ldconfig export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH ./configure make make install
安装错误排查
如果安装过程中,抛出“configure: error: *** libmcrypt was not found”错误
*** 'libmcrypt-config --version' returned 2.4.0, but LIBMCRYPT (2.5.8) *** was found! If libmcrypt-config was correct, then it is best *** to remove the old version of LIBMCRYPT. You may also be able to fix the error *** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing *** /etc/ld.so.conf. Make sure you have run ldconfig if that is *** required on your system. *** If libmcrypt-config was wrong, set the environment variable LIBMCRYPT_CONFIG *** to point to the correct copy of libmcrypt-config, and remove the file config.cache *** before re-running configure configure: error: *** libmcrypt was not found
这是因为环境变量的问题,gcc编译的时候根据自身定义的变量寻找相关函数库等文件,libmcrypt也是刚安装的,在变量中没有定义出来,所以手动添加环境变量使其生效:
# ln -s /usr/local/bin/libmcrypt-config /usr/bin/libmcrypt-config
# export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
然后 #./configure 过后,继续 # make && make install , 成功!
更多安装PHP库,详见米扑博客:LNMP(CentOS+Nginx+Mysql+PHP)服务器环境配置 (经典推荐)
3. 下载安装PHP扩展 mcrypt.so
PHP 7.2 之前,PHP 安装包自带有 mcrypt 库,目录在:/opt/php-5.6.11/ext/mcrypt/
安装步骤:
1)编译安装
cd /opt/php-5.6.11/ext/mcrypt/ /usr/local/php/bin/phpize ./configure make make install Installing shared extensions: /usr/local/php/lib/php/extensions/no-debug-non-zts-20131226/
2)编辑 php.ini 文件,添加自带的 mcrypt.so 动态库
vim /usr/local/php/etc/php.ini
在末尾添加一行
extension=/usr/local/php/lib/php/extensions/no-debug-non-zts-20131226/mcrypt.so
3)重启 php-fpm 或 apache,使其失效
# /etc/init.d/php-fpm restart Restarting php-fpm daemon: php-fpm.
PHP 7.2 之后,PHP 安装包移除了 mcrypt 库,因此必须自己手动下载 php 库
1)下载 mcrypt-1.0.1.tgz
pecl 官网:http://pecl.php.net/package/mcrypt
安装扩展 mcrypt
tar zxvf mcrypt-1.0.1.tgz cd mcrypt-1.0.1 /usr/local/php/bin/phpize ./configure --with-php-config=/usr/local/php/bin/php-config make make install Installing shared extensions: /usr/local/php/lib/php/extensions/no-debug-zts-20170718/
2)编辑 php.ini 文件,添加自编译的 mcrypt.so 动态库
vim /usr/local/php/etc/php.ini
在末尾添加一行
extension=/usr/local/php/lib/php/extensions/no-debug-zts-20170718/mcrypt.so
3)重启 php-fpm 或 apache,使其失效
# /etc/init.d/php-fpm restart Restarting php-fpm daemon: php-fpm.
补充:
php 自带的扩展目录为 /home/data/tool-server/LNMP/php-7.2.8/ext/
编译常见的扩展的动态库如下:
# ll /usr/local/php/lib/php/extensions/no-debug-zts-20170718/ -rwxr-xr-x 1 root root 1201584 Dec 26 22:57 gd.so -rwxr-xr-x 1 root root 1177792 Dec 19 21:53 imagick.so -rwxr-xr-x 1 root root 3424944 Dec 26 22:57 mbstring.so -rwxr-xr-x 1 root root 149504 Dec 27 12:05 mcrypt.so -rwxr-xr-x 1 root root 386312 Dec 19 21:52 memcached.so -rwxr-xr-x 1 root root 3530874 Dec 19 21:47 opcache.a -rwxr-xr-x 1 root root 1972464 Dec 19 21:47 opcache.so -rwxr-xr-x 1 root root 36728 Dec 19 21:52 pdo_mysql.so -rwxr-xr-x 1 root root 1827760 Dec 19 21:53 redis.so -rwxr-xr-x 1 root root 108760 Dec 26 22:55 xmlreader.so -rwxr-xr-x 1 root root 183920 Dec 26 22:57 xml.so -rwxr-xr-x 1 root root 118416 Dec 26 22:55 xmlwriter.so -rwxr-xr-x 1 root root 131016 Dec 26 22:57 xsl.so
4. 查看 mcrypt
通过 phpinfo() 查看 mcrypt 动态库
检测PHP是否支持 mcrypt 模块,并查看支持哪些加密算法和模式
$cipher_list = mcrypt_list_algorithms(); // mcrypt支持的加密算法列表 $mode_list = mcrypt_list_modes(); // mcrypt支持的加密模式列表 var_dump($cipher_list); var_dump($mode_list);
运行结果:
cipher_list
array (size=19) 0 => string 'cast-128' (length=8) 1 => string 'gost' (length=4) 2 => string 'rijndael-128' (length=12) 3 => string 'twofish' (length=7) 4 => string 'arcfour' (length=7) 5 => string 'cast-256' (length=8) 6 => string 'loki97' (length=6) 7 => string 'rijndael-192' (length=12) 8 => string 'saferplus' (length=9) 9 => string 'wake' (length=4) 10 => string 'blowfish-compat' (length=15) 11 => string 'des' (length=3) 12 => string 'rijndael-256' (length=12) 13 => string 'serpent' (length=7) 14 => string 'xtea' (length=4) 15 => string 'blowfish' (length=8) 16 => string 'enigma' (length=6) 17 => string 'rc2' (length=3) 18 => string 'tripledes' (length=9)
其中 rijndael-128、rijndael-192、rijndael-256都是AES算法
mode_list
array (size=8) 0 => string 'cbc' (length=3) 1 => string 'cfb' (length=3) 2 => string 'ctr' (length=3) 3 => string 'ecb' (length=3) 4 => string 'ncfb' (length=4) 5 => string 'nofb' (length=4) 6 => string 'ofb' (length=3) 7 => string 'stream' (length=6)
AES算法加密模式和填充方式
AES支持五中模式:CBC、CFB、ECB、OFB、PCBC
AES支持三种填充:NoPadding、PKCS5Padding、ISO10126Padding,不支持SSL3Padding,不支持“NONE”模式
其中AES/ECB/NoPadding和米扑科技的项目现在使用的AESUtil得出的结果相同(在16的整数倍情况下)
不带模式和填充来获取AES算法的时候,其默认使用ECB/PKCS5Padding
算法/模式/填充
AES/CBC/NoPadding
AES/CBC/PKCS5Padding
AES/CBC/ISO10126Padding
AES/CFB/NoPadding
AES/CFB/PKCS5Padding
AES/CFB/ISO10126Padding
AES/ECB/NoPadding
AES/ECB/PKCS5Padding
AES/ECB/ISO10126Padding
AES/OFB/NoPadding
AES/OFB/PKCS5Padding
AES/OFB/ISO10126Padding
AES/PCBC/NoPadding
AES/PCBC/PKCS5Padding
AES/PCBC/ISO10126Padding
可以看到,在原始数据长度为16的整数倍时,假如原始数据长度等于16*n,则使用NoPadding时加密后数据长度等于16*n,其它情况下加密数据长度等于16*(n+1)。在不足16的整数倍的情况下,假如原始数据长度等于16*n+m[其中m小于16],除了NoPadding填充之外的任何方式,加密数据长度都等于16*(n+1);NoPadding填充情况下,CBC、ECB、PCBC三种模式是不支持的,CFB、OFB两种模式下则加密数据长度等于原始数据长度。
本文示例采用的 AES/CBC/NoPadding
PHP 对称加密AES算法应用示例
// AES 加密 function encrypt_aes($string='', $key='mimvp') { $cipher = MCRYPT_RIJNDAEL_128; $mode = MCRYPT_MODE_CBC; $iv = substr(md5($key), 0, 16); $private_key = substr(md5($key), 0, 32); // 必须为16,24,32个字符 $encrypted = mcrypt_encrypt($cipher, $private_key, $string, $mode, $iv); return base64_encode($encrypted); } // AES 解密 function decrypt_aes($string='', $key='mimvp') { $string = base64_decode($string); $cipher = MCRYPT_RIJNDAEL_128; $mode = MCRYPT_MODE_CBC; $iv = substr(md5($key), 0, 16); $private_key = substr(md5($key), 0, 32); // 必须为16,24,32个字符 $decrypted = rtrim(mcrypt_decrypt($cipher, $private_key, $string, $mode, $iv), "\0"); return $decrypted; } $data = 'I love mimvp.com'; $data_encrypt = encrypt_aes($data); echo '<br><br> encrypt_aes : ' . $data_encrypt; echo '<br><br> decrypt_aes : ' . decrypt_aes($data_encrypt); $data = 'I love mimvp.com in 2016.09.12 @mimvp.com $1,000,000,000'; $data_encrypt = encrypt_aes($data); echo '<br><br> encrypt_aes : ' . $data_encrypt; echo '<br><br> decrypt_aes : ' . decrypt_aes($data_encrypt);
为了方便与其他语言进行数据交换,也可以手动指定 $iv 为一个固定的可见字符串,但是长度要与 mcrypt_create_iv 生成的一致,否则会报一个 The IV parameter must be as long as the blocksize in 的警告。这里的长度是16,所以固定的字符串常量也要是16个字符,可以利用代码生成其16位的随机字符串(注意:加密和解密的都必须一致,可在函数参数里传递此参数)
$iv = mcrypt_create_iv(mcrypt_get_iv_size($cipher, $mode), MCRYPT_RAND);
运行结果:
encrypt_aes : HsjNQpu+/yxeMNmaErqiqA==
decrypt_aes : I love mimvp.com
encrypt_aes : HsjNQpu+/yxeMNmaErqiqPLjk/N4VmlhYlnrjZCcnZhwJPoML1eTNG+cLwFUxFv8Se+xOkRddaM5c7umF+npLQ==
decrypt_aes : I love mimvp.com in 2016.09.12 @mimvp.com $1,000,000,000
从加密解密结果可见:
1)AES 加密算法字符串会跟着加密字符串的长度增加而增加,不同于md5等是固定的长度,更多算法长度参见米扑博客《php 加密算法md5, sha1》
2)AES 加密算法,支持任意字符的加密,如特殊字符 @、$、空格、逗号等
3)注意私钥字符串,长度必须为16,24,32位,且加密解密的私钥需一致
参考推荐:
Python 常用加密算法 base64, md5, sha1
LNMP(CentOS+Nginx+Mysql+PHP)服务器环境配置 (推荐)
版权所有: 本文系米扑博客原创、转载、摘录,或修订后发表,最后更新于 2018-12-27 12:12:32
侵权处理: 本个人博客,不盈利,若侵犯了您的作品权,请联系博主删除,莫恶意,索钱财,感谢!
转载注明: PHP 对称加密AES算法 (米扑博客)
感谢分享,很强大。