Pages

Sunday, 1 December 2013

使用PHP进行AES加密

什么是AES?

AES加密算法即密码学中的高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法。该算法为比利时密码学家Joan Daemen和Vincent Rijmen所设计,结合两位作者的名字,以Rijndael之命名之。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。

怎么使用PHP进行AES加密计算?

答案是mcrypt函数。拿mcrypt_encrypt函数进行说明。

 mcrypt_encrypt说明

string mcrypt_encrypt ( string $cipher , string $key , string $data , string $mode [, string $iv ] )
 参数
cipher
一个MCRYPT_ciphername 常量,或者用字符串表示的算法名称,比如下列任意一个值:”rijndael-128″,”rijndael-192″,”rijndael-256″,”des”等。
key
用来对数据进行加密的密钥。最好不要用ASCII字符做为密钥。建议使用mhash(md5/sha)函数产生一个密钥。
data
将要被加密的数据。如果使用的是AES加密,如果数据的长度不是固定块的整数倍,将会以’\0′进行填充。也就是说在PHP中,默认使用的填充模式是NoPadding。常见的填充模式还有pkcs7-padding。下面会有例子说明。
mode
加密模式。可以是一个MCRYPT_MODE_modename常量,也可以是下列任意一个值: “ecb”, “cbc”, “cfb”, “ofb”, “nofb” , “stream”.
iv
向量值,在CBC/CFB/OFB三个模式需要用到,或者有些stream加密模式也会用到。如果该值为空,但使用的加密模式需要用到这个向量 值,那么会产生一个警告,并且自动产生一个以’\0′为填充的,满足长度要求的默认向量值 。向量长度要和block-size长度一致。

AES算法原理

AES 算法基于排列和置换运算。排列是对数据重新进行安排,置换是将一个数据单元替换为另一个。AES 使用几种不同的方法来执行排列和置换运算。
AES 是一个迭代的、对称密钥分组的密码,它可以使用128、192 和 256 位密钥,并且用 128 位(16字节)分组加密和解密数据。与公共密钥密码使用密钥对不同,对称密钥密码使用相同的密钥加密和解密数据。通过分组密码返回的加密数据的位数与输入 数据相同。迭代加密使用一个循环结构,在该循环中重复置换和替换输入数据。
AES加密算法原理
AES加密算法原理

AES加密算法 – 加密模式

  • ECB模式:

AES-ECB加密模式
AES-ECB加密模式
优点:
1.简单;
2.有利于并行计算;
3.误差不会被传送;
缺点:
1.不能隐藏明文的模式;
2.可能对明文进行主动攻击
举例:
如果明文是 12345678123456781234567812345678,分块分别进行加密,那么加密的结果类似 “C4132737962C519CC4132737962C519C C4132737962C519CC4132737962C519C”,可以看出明文的规律,不太安全。
  •  CBC模式:

    CBC加密原理:明文跟向量异或,再用KEY进行加密,结果作为下个BLOCK的初始化向量。解密原理:使用密钥先对密文解密,解密后再同初始向量异或得到明文。
    CBC需要对明文块大小进行Padding(补位),由于前后加密的相关性,只能实施串行化动作,无法并行运算。另外,CBC需要参量:密钥和初始化向量。
AES-CBC加密模式
AES-CBC加密模式
优点:
1.不容易主动攻击,安全性好于ECB,适合传输长度长的报文,是SSL、IPSec的标准。
缺点:
1.不利于并行计算;
2.误差传递;
3.需要初始化向量IV
  • CFB模式

AES-CFB加密模式
AES-CFB加密模式
 优点:
1.隐藏了明文模式;
2.分组密码转化为流模式;
3.可以及时加密传送小于分组的数据;
缺点:
1.不利于并行计算;
2.误差传送:一个明文单元损坏影响多个单元;
3.唯一的IV;

OFB模式:


优点:

1.隐藏了明文模式;
2.分组密码转化为流模式;
3.可以及时加密传送小于分组的数据;
缺点:
1.不利于并行计算;
2.对明文的主动攻击是可能的;
3.误差传送:一个明文单元损坏影响多个单元;

 pkcs7-padding填充模式

mcrypt_encrypt函数默认用的填充方式是NoPadding模式,如果想使用pkcs7-padding填充模式怎么解?
01/**
02* pkcs7补码
03*
04* @param string $string 明文
05* @param int $blocksize Blocksize , 以 byte 为单位
06*
07* @return String
08*/
09function addPkcs7Padding($string, $blocksize = 32) {
10$len = strlen($string); //取得字符串长度
11$pad = $blocksize - ($len % $blocksize); //取得补码的长度
12$string .= str_repeat(chr($pad), $pad); //用ASCII码为补码长度的字符, 补足最后一段
13return $string;
14}/**
15* 除去pkcs7 padding
16*
17* @param String 解密后的结果
18*
19* @return String
20*/
21function stripPkcs7Padding($string){
22$slast = ord(substr($string, -1));
23$slastc = chr($slast);
24$pcheck = substr($string, -$slast);
25if(preg_match("/$slastc{".$slast."}/", $string)){
26$string = substr($string, 0, strlen($string)-$slast);
27return $string;
28} else {
29return false;
30}
31}