10.1 对称加密
对称加密指的是采用单密钥进行加密,并且该密钥可以对数据进行加密和解密处理,目前这类加密算法安全性均比较高,数据的实际安全性取决于密钥的管理,就算黑客拿到加密后的数据,如果没有密钥,这些数据对于黑客来说也是垃圾数据而已,而拿到密钥之后可以对加密数据进行还原,所以笔者不建议使用对称加密对用户密码进行加密存储。它的原理比较简单,如图10-1所示。
图 10-1
明文数据123456可以在加密算法的作用下使用密钥0s9ansk2处理后变成d2fm83jjf,同样使用这个密钥也能把d2fm83jjf解密回123456。
在对称加密算法中常用的算法有DES、3DES、TDEA、Blowfish、RC2、RC4、RC5、IDEA、SKIPJACK、AES等。
10.1.1 3DES加密
DES(Data Encrypt Standard)又称Triple DES,是DES加密算法的一种模式,它使用3条56位的密钥对数据进行三次加密。DES加密算法是美国的一种由来已久的加密标准,这种算法通常用于加密需要传输的数据。
PHP中需要在php.ini中打开php_mcrypt.dll以及php_mcrypt_filter.dll两个lib库的引用,即去掉以下代码前面的分号:
; extension=php_mcrypt.dll ; extension=php_mcrypt_filter.dll
PHP的3DES已经有很简洁成熟的加密,我们来看一个简单的3DES加解密类,代码如下:
< ? php
class Crypt3Des {
public $key = "xxxx" ; // 加密密钥
function Crypt3Des ( $key ) {
$this->key=$key ;
}
// 加密函数
function encrypt ( $input ) {
$size = mcrypt_get_block_size ( MCRYPT_3DES , 'ecb' );
$input = $this->pkcs5_pad ( $input , $size );
$key = str_pad ( $this->key , 24 , '0' );
$td = mcrypt_module_open ( MCRYPT_3DES , '' , 'ecb' , '' );
$iv = @mcrypt_create_iv ( mcrypt_enc_get_iv_size ( $td ), MCRYPT_RAND );
@mcrypt_generic_init ( $td , $key , $iv );
$data = mcrypt_generic ( $td , $input );
mcrypt_generic_deinit ( $td );
mcrypt_module_close ( $td );
$data = base64_encode ( $data );
return $data ;
}
// 解密函数
function decrypt ( $encrypted ) {
$encrypted = base64_decode ( $encrypted );
$key = str_pad ( $this->key , 24 , '0' );
$td = mcrypt_module_open ( MCRYPT_3DES , '' , 'ecb' , '' );
$iv = @mcrypt_create_iv ( mcrypt_enc_get_iv_size ( $td ), MCRYPT_RAND );
$ks = mcrypt_enc_get_key_size ( $td );
@mcrypt_generic_init ( $td , $key , $iv );
$decrypted = mdecrypt_generic ( $td , $encrypted );
mcrypt_generic_deinit ( $td );
mcrypt_module_close ( $td );
$y=$this->pkcs5_unpad ( $decrypted );
return $y ;
}
function pkcs5_pad ( $text , $blocksize ) {
$pad = $blocksize - ( strlen ( $text ) % $blocksize );
return $text . str_repeat ( chr ( $pad ), $pad );
}
function pkcs5_unpad ( $text ) {
$pad = ord ( $text{strlen ( $text ) -1} );
if ( $pad > strlen ( $text )) {
return false ;
}
if ( strspn ( $text , chr ( $pad ), strlen ( $text ) - $pad ) ! = $pad ) {
return false ;
}
return substr ( $text , 0 , -1 * $pad );
}
function PaddingPKCS7 ( $data ) {
$block_size = mcrypt_get_block_size ( MCRYPT_3DES , MCRYPT_MODE_CBC );
$padding_char = $block_size - ( strlen ( $data ) % $block_size );
$data .= str_repeat ( chr ( $padding_char ), $padding_char );
return $data ;
}
} ? >
使用方法很简单,只要实例化这个类,直接调用相应函数即可,如下所示:
$rep=new Crypt3Des ( ' 加密 key' );
$input="hello 3des" ;
echo " 原文: ".$input."<br/>" ;
$encrypt_card=$rep->encrypt ( $input );
echo " 加密: ".$encrypt_card."<br/>" ;
echo " 解密: ".$rep->decrypt ( $rep->encrypt ( $input ));
我们来看看经过它处理后的数据,如图10-2所示。
图 10-2
10.1.2 AES加密
AES(Advanced Encryption Standard)加密在密码学中又称Rijndael加密法,比3DES更加安全,密钥长度的最少支持为128、192、256位,所以逐渐替代原先的DES。
PHP中需要在php.ini中打开php_mcrypt.dll库的引用,设置方法我们已在上一小节介绍过,我们来看一个PHP中AES的加解密实例:
< ? php
class Aes{
public $_secrect_key='' ; // 密钥
function Aes ( $key ) {
$this->_secrect_key = $key ;
}
/**
* 加密方法
* @param string $str
* @return string
*/
function encrypt ( $str ) {
//AES , 128 ECB 模式加密数据
$screct_key = $this->_secrect_key ;
$screct_key = base64_decode ( $screct_key );
$str = trim ( $str );
$str = $this->addPKCS7Padding ( $str );
$iv = mcrypt_create_iv ( mcrypt_get_iv_size ( MCRYPT_RIJNDAEL_128 , MCRYPT_MODE_ECB ), MCRYPT_RAND );
$encrypt_str = mcrypt_encrypt ( MCRYPT_RIJNDAEL_128 , $screct_key , $str , MCRYPT_MODE_ECB , $iv );
return base64_encode ( $encrypt_str );
}
/**
* 解密方法
* @param string $str
* @return string
*/
function decrypt ( $str ) {
//AES , 128 ECB 模式加密数据
$screct_key = $this->_secrect_key ;
$str = base64_decode ( $str );
$screct_key = base64_decode ( $screct_key );
$iv = mcrypt_create_iv ( mcrypt_get_iv_size ( MCRYPT_RIJNDAEL_128 , MCRYPT_MODE_ECB ), MCRYPT_RAND );
$encrypt_str = mcrypt_decrypt ( MCRYPT_RIJNDAEL_128 , $screct_key , $str , MCRYPT_MODE_ECB , $iv );
$encrypt_str = trim ( $encrypt_str );
$encrypt_str = $this->stripPKSC7Padding ( $encrypt_str );
return $encrypt_str ;
}
/**
* 填充算法
* @param string $source
* @return string
*/
function addPKCS7Padding ( $source ) {
$source = trim ( $source );
$block = mcrypt_get_block_size ( 'rijndael-128' , 'ecb' );
$pad = $block - ( strlen ( $source ) % $block );
if ( $pad <= $block ) {
$char = chr ( $pad );
$source .= str_repeat ( $char , $pad );
}
return $source ;
}
/**
* 移去填充算法
* @param string $source
* @return string
*/
function stripPKSC7Padding ( $source ) {
$source = trim ( $source );
$char = substr ( $source , -1 );
$num = ord ( $char );
if ( $num==62 ) return $source ;
$source = substr ( $source , 0 , -$num );
return $source ;
}
}
这个加密类使用起来也相当简单:
$rep=new Aes ( 'xxxx' );
$input="hello aes" ;
echo " 原文: ".$input."<br/>" ;
$encrypt_card=$rep->encrypt ( $input );
echo " 加密: ".$encrypt_card."<br/>" ;
echo " 解密: ".$rep->decrypt ( $rep->encrypt ( $input ));
我们来看看使用它加解密后的效果,如图10-3所示。
图 10-3