PHP对称加密

分类:└ 技术前沿,来源:江门易腾网络科技有限公司

 对称加密算法是指,数据发信方将明文(原始数据)和密钥一起经过加密处理后,使其变成复杂的加密密文发送出去。收信方收到密文后,若要解读原文,则需要使用加密密钥及相同算法的逆算法对密文进行解密,使其恢复成可读明文。对称加密算法的优点是算法公开、计算量小、加密速度快、加密效率高,适用于加密大量数据的场合。常用的算法有DES、3DES、TDEA、Blowfish、RC2、RC4、RC5、IDEA、SKIPJACK、AES等。




PHP中如果需要使用对称加密算法,则需要mcrypt扩展的支持。PHP的mcrypt扩展提供了强大的加密解密方法,支持19种加密算法和8种加密模式,具体可以通过函数mcrypt_list_algorithms()和mcrypt_list_modes()来显示。



<?php

$type_list = mcrypt_list_algorithms();  //mcrypt支持的加密算法列表

$mode_list = mcrypt_list_modes();  //mcrypt支持的加密模式列表

print_r($type_list);

print_r($mode_list);

?>



使用DES方式加密的代码如下。


<?php

$auth_key = 'safe_key';

$salt = '!@#$%';

$content = 'Hello World';

$td = mcrypt_module_open(mcrypt_des,'','ecb','');  //使用mcrypt_des算法ecb模式

$iv_size = mcrypt_enc_get_iv_size($td);  //设置初始向量大小

$iv = mcrypt_create_iv($iv_size,mcrypt_rand);  //创建初始向量

$key_size = mcrypt_enc_get_key_size($td);  //返回所支持的最大密钥长度(以字节计算)

$key = substr(md5($auth_key.salt),0,$key_size);

mcrypt_generic_init($td, $key, $iv);  //初始化

$secret = mcrypt_generic($td, $content);  //加密并返回加密后的内容

echo base64_encode($secret);

mcrypt_generic_deinit($td);

mcrypt_module_close($td);  //结束

?>


使用DES方式解密的代码如下。


<?php

$auth_key = 'safe_key';

$salt = '!@#$%';

$secret = 'nzPa0jPaaNca+Yty/HG4PA==';

$td = mcrypt_module_open(mcrypt_des,'','ecb','');  //使用mcrypt_des算法ecb模式

$iv_size = mcrypt_enc_get_iv_size($td);  //设置初始向量大小

$iv = mcrypt_create_iv($iv_size,mcrypt_rand);  //创建初始向量

$key_size = mcrypt_enc_get_key_size($td);  //返回所支持的最大密钥长度(以字节计算)

$key = substr(md5($auth_key.salt),0,$key_size);

mcrypt_generic_init($td, $key, $iv);  //初始化

$content = mdecrypt_generic($td, base64_decode($secret));  //解密并返回内容

echo $content;

mcrypt_generic_deinit($td);

mcrypt_module_close($td);  //结束

?>



AES是Advanced Encryption Standard(高级加密标准)的缩写,在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。经过五年的甄选流程,高级加密标准由美国国家标准与技术研究院(National Institute of Standards and Technology,NIST)于2001年11月26日发布于FIPS PUB 197,并在2002年5月26日成为有效的标准。至2006年,高级加密标准已经成为对称密钥加密中最流行的算法之一。




AES目前有五种加密模式。




(1)电码本(Electronic Codebook,ECB)模式。


(2)密码分组链接(Cipher Block Chaining,CBC)模式。


(3)计数(Counter,CTR)模式。


(4)密码反馈(Cipher FeedBack,CFB)模式。


(5)输出反馈(Output FeedBack,OFB)模式。




在PHP的mcrypt扩展中,rijndael-128、rijndael-192、rijndael-256就是AES加密,三种分别使用不同的数据块和密钥长度进行加密。




在AES的ECB模式中,一般是16字节为一块,然后对这一整块进行加密,如果输入的字符串不够16字节,就需要补位。




使用AES-ECB方式进行加密数据的代码如下。


<?php

$auth_key = 'safe_key';

$salt = '!@#$%';

$content = 'Hello World';

$td= mcrypt_module_open(mcrypt_rijndael_128,'',mcrypt_mode_ecb,'');

$iv_size = mcrypt_enc_get_iv_size($td);

$iv = mcrypt_create_iv($iv_size,mcrypt_rand);

$key_size = mcrypt_enc_get_key_size($td);

$key = substr(md5($auth_key.salt),0,$key_size);

mcrypt_generic_init($td, $key, $iv);

$block=mcrypt_get_block_size(mcrypt_rijndael_128,mcrypt_mode_ecb);

$pad=$block-(strlen($content) % $block);

$content.=str_repeat(chr($pad),$pad); // 补齐不足16字符的位数内容

$secret = mcrypt_generic($td, $content);

echo bin2hex($secret);

mcrypt_generic_deinit($td);

mcrypt_module_close($td);

?>



使用AES-ECB方式进行解密数据如下。


<?php

$auth_key = 'safe_key';

$salt = '!@#$%';

$secret = 'd62d9e7e8ad4b0f044e4bd971f695a58';

$td= mcrypt_module_open(mcrypt_rijndael_128,'',mcrypt_mode_ecb,'');

$iv_size = mcrypt_enc_get_iv_size($td);

$iv = mcrypt_create_iv($iv_size,mcrypt_rand);

$key_size = mcrypt_enc_get_key_size($td);

$key = substr(md5($auth_key.salt),0,$key_size);

mcrypt_generic_init($td, $key, $iv);

$content=mdecrypt_generic($td,hex2bin($secret));


$len=strlen($content);


$ch=ord($content[$len-1]);

echo substr($content,0,$len-$ch);

mcrypt_generic_deinit($td);

mcrypt_module_close($td);

?>


AES的CBC加密模式,需要添加初始化向量(IV),默认是16个0。由于是分组加密,因此下一组的IV就用前一组的加密的密文来充当。CFB、OFB模式类似,只不过更复杂,从而破解难度更大。




使用AES-CBC方式进行加密解密数据的代码如下。


<?php

$auth_key = 'safe_key';

$salt = '!@#$%';

$content = 'Hello World';

$td= mcrypt_module_open(mcrypt_rijndael_128,'',mcrypt_mode_cbc,'');

$iv_size = mcrypt_enc_get_iv_size($td);

$iv = mcrypt_create_iv($iv_size,mcrypt_rand);

$key_size = mcrypt_enc_get_key_size($td);

$key = substr(md5($auth_key.salt),0,$key_size);

mcrypt_generic_init($td, $key, $iv);

$secret = mcrypt_generic($td, $content); // 加密数据

echo bin2hex($secret);

mcrypt_generic_deinit($td);

mcrypt_module_close($td);

$td= mcrypt_module_open(mcrypt_rijndael_128,'',mcrypt_mode_cbc,'');

mcrypt_generic_init($td, $key, $iv);

echo mdecrypt_generic($td,$secret); // 解密数据

mcrypt_generic_deinit($td);

mcrypt_module_close($td);

?>