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

下载地址:mcrypt-2.6.8.tar.gz

 

2. 安装 mcrypt

# tar zxvf mcrypt-2.6.8.tar.gz
# cd mcrypt-2.6.8/
# /sbin/ldconfig
#./configure
# make
# make install
# cd ../

如果安装过程中,抛出“configure: error: *** libmcrypt was not found”错误,这是因为环境变量的问题,gcc编译的时候根据自身定义的变量寻找相关函数库等文件,libmcrypt也是刚安装的,在变量中没有定义出来,所以手动添加环境变量使其生效:

[root@mimvp-bj mcrypt-2.6.8]# export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH

然后 #./configure 过后,继续 # make && make install , 成功!

更多安装PHP库,详见米扑博客:LNMP(CentOS+Nginx+Mysql+PHP)服务器环境配置 (经典推荐

 

3. 配置 mcrypt

手动添加到 php.ini 文件里

重启 apache 或 php-fpm ,使其生效

 

4. 查看 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

 

算法/模式/填充                    16字节加密后数据长度         不满16字节加密后长度

AES/CBC/NoPadding             16                         不支持
AES/CBC/PKCS5Padding          32                         16
AES/CBC/ISO10126Padding       32                          16
AES/CFB/NoPadding             16                          原始数据长度
AES/CFB/PKCS5Padding          32                          16
AES/CFB/ISO10126Padding       32                          16
AES/ECB/NoPadding             16                          不支持
AES/ECB/PKCS5Padding          32                          16
AES/ECB/ISO10126Padding       32                          16
AES/OFB/NoPadding             16                          原始数据长度
AES/OFB/PKCS5Padding          32                          16
AES/OFB/ISO10126Padding       32                          16
AES/PCBC/NoPadding            16                          不支持
AES/PCBC/PKCS5Padding         32                          16
AES/PCBC/ISO10126Padding      32                          16

可以看到,在原始数据长度为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位,且加密解密的私钥需一致

 

 

参考推荐

php 加密算法md5, sha1

Python 常用加密算法 base64, md5, sha1

Python中Base64编码和解码

AES、DES、RSA三种典型加密算法

AES 加密算法的详细介绍与实现

PHP 使用cookie实现记住登录状态

PHP Session与Cookie详解

公钥,私钥,数字签名的通俗理解

LNMP(CentOS+Nginx+Mysql+PHP)服务器环境配置