常用的加密分为对称加密和非对称加密,对称加密就是发送方和接收方都用同一个秘钥进行加密解密,而非对称加密则使用一对公钥和私钥来进行加密,发送发只需要用接收方的公钥将数据加密即可。
AES是一种常见的对称加密算法,英语:Advanced Encryption Standard,又称Rijndael加密,它是一种分块加密方法,换句话说就是将明文块分成一组组小部分然后进行加密再组合,而根据分组大小可分为:AES-128,AES-196,AES-256三种,对应的分组大小分别是128bit,196bit,256bit。在网上转来的一张图:
而如何将这些明文块进行加密组合,又分为四种模式:ECB、CBC、CFB、OFB,除了第一种模式,后面三种模式都需要一个初始向量iv来辅助加密。初始向量的大小也是同区块大小保持一致,是个固定长度的随机字串,初始向量只是为了给加密算法提供一个可用的种子。
还有一点是,如果需要加密的源数据长度不是分组大小的整数倍,那么就需要对数据进行填充,一般的填充算法有PKSC5和PKSC7填充算法。举个例子,如果源数据大小是10bytes,如果进行分组,还需要6bytes才能满足分组的要求。那么只需要在后面补上6个6即可:
x x x x x x x x x x 6 6 6 6 6 6
如果刚好不用填充,还需要再补齐区块大小个字节,这么做是为了在去除填充数据时,可以准确无误。
php中有一个mcrypt扩展,使用它提供的加密函数即可进行我们需要的对称加密。
mcrypt_encrypt(): 该方法接受5个参数,分别是算法名称,密钥,待加密源数据,加密模式,以及初始向量。最后一个参数,如果是ECB模式则不是必须的。需要注意的是如果密钥和初始向量的长度不是区块大小的长度,php会返回false。
mcrypt_decrypt(): 参数同加密方法一样,只不过源数据改成已加密后的数据。
php会使用 ‘\0‘ 自动填充数据,你也可以使用自己的填充算法。
下面有一个简单的加密类,是参考网上的代码稍微修改的。使用的是PKSC7填充。
class Aes {
private $init_key;
private $auto_padding;
private $aes_bytes;
private $block_size;
private $key;
private $iv;
private $map = [
'128' => MCRYPT_RIJNDAEL_128,
'196' => MCRYPT_RIJNDAEL_192,
'256' => MCRYPT_RIJNDAEL_256,
];
public function __construct($init_key, $aes_bytes, $auto_padding){
$this->init_key = $init_key;
$this->auto_padding = $auto_padding;
$this->aes_bytes = $aes_bytes;
$this->block_size = mcrypt_get_block_size($this->map[$this->aes_bytes], MCRYPT_MODE_CBC);
$this->key = substr( hash('sha256',$this->init_key), 0, $this->block_size );
$this->iv = mcrypt_create_iv( mcrypt_get_iv_size($this->map[$this->aes_bytes], MCRYPT_MODE_CBC) );
}
//CBC mode
public function encrypt($data){
$data = trim($data);
if(!$this->auto_padding) {
$data = $this->addPKCS7Padding($data);
}
$encrypt = mcrypt_encrypt($this->map[$this->aes_bytes], $this->key, $data, MCRYPT_MODE_CBC, $this->iv);
return base64_encode( $encrypt );
}
public function decrypt($aes_data){
$aes_data = base64_decode($aes_data);
$decrypt = mcrypt_decrypt($this->map[$this->aes_bytes], $this->key, $aes_data, MCRYPT_MODE_CBC, $this->iv);
return $this->stripPKCS7Padding( trim($decrypt) );
}
// padding
public function addPKCS7Padding($data){
$data = trim($data);
$pad = $this->block_size - (strlen($data) % $this->block_size);
if( $pad <= $this->block_size ) {
$padStr = chr($pad) ;
$data .= str_repeat($padStr, $pad);
}
return $data;
}
public function stripPKCS7Padding($data){
$num = ord(substr($data,-1));
return substr($data,0,-$num);
}
}
$aes = new Aes('sama','128',false);
$en = $aes->encrypt('helloworldmydear');
$de = $aes->decrypt($en);
测试可行。