vlambda博客
学习文章列表

AES加解密 对称加密

美国国家标准和技术研究所(NIST)经过三轮候选算法筛选,从众多的分组密码中选中Rijndael算法作为高级加密标准(AES)。

三个基础概念:

秘钥,填充,模式

一、 密钥

密钥是AES算法实现加密和解密的根本。对称加密算法之所以对称,是因为这类算法对明文的加密和解密需要使用同一个密钥。

AES支持三种长度的密钥:128位,192位,256位

AES128,AES192,AES256,实际上就是指的AES算法对不同长度密钥的使用。

AES为分组密码,分组密码也就是把明文分成一组一组的,每组长度相等,每次加密一组数据,直到加密完整个明文。在AES标准规范中,分组长度只能是128位,也就是说,每个分组为16个字节(每个字节8位)。密钥的长度可以使用128位、192位或256位。密钥的长度不同,推荐加密轮数也不同,如下表所示:

AES 密钥长度(32位比特字) 分组长度(32位比特字) 加密轮数
AES-128 4
4
10
AES-192 6
4
12
AES-256 8
4 14



这里实现的是AES-128,也就是密钥的长度为128位,加密轮数为10轮。

上面说到,AES的加密公式为C = E(K,P),在加密函数E中,会执行一个轮函数,并且执行10次这个轮函数,这个轮函数的前9次执行的操作是一样的,只有第10次有所不同。也就是说,一个明文分组会被加密10轮。AES的核心就是实现一轮中的所有操作。


AES对称加密:

                                                    

AES加解密 对称加密



二、填充:

PKCS5Padding(默认):

在PKCS5Padding中,明确定义Block的大小是8位,只对于8字节(BlockSize=8)进行填充,填充内容为0x01-0x08;

如果明文块少于16个字节(128bit),在明文块末尾补足相应数量的字符,且每个字节的值等于缺少的字符数。

例如如明文:{1,2,3,4,5,a,b,c,d,e},缺少6个字节,则补全为{1,2,3,4,5,a,b,c,d,e,6,6,6,6,6,6}


PKCS7Padding:

PKCS7Padding定义中,对于块的大小是不确定的,可以在1-255之间。


ZeroPADDING:

剩余部分填充0


 NoPadding:

不做任何填充,但是要求明文必须是16字节的整数倍。


分组密码的填充


AES加解密 对称加密

                                             

 

AES加解密 对称加密

                                                       

 

 

流密码:

AES加解密 对称加密

 

 

三、 四种模式:

3.1 ECB模式

AES加解密 对称加密

优点:

1.简单;

2.有利于并行计算;

3.误差不会被传送;

缺点:

1.不能隐藏明文的模式;

2.可能对明文进行主动攻击;

AES加解密 对称加密

 

3.2 CBC模式:

AES加解密 对称加密

优点:

1.不容易主动攻击,安全性好于ECB,适合传输长度长的报文,是SSL、IPSec的标准。

缺点:

1.不利于并行计算;

2.误差传递;

3.需要初始化向量IV

 

3.3 CFB模式:

 优点:

1.隐藏了明文模式;

2.分组密码转化为流模式;

3.可以及时加密传送小于分组的数据;

缺点:

1.不利于并行计算;

2.误差传送:一个明文单元损坏影响多个单元;

3.唯一的IV;

 

3.4 OFB模式:

 优点:

1.隐藏了明文模式;

2.分组密码转化为流模式;

3.可以及时加密传送小于分组的数据;

缺点:

1.不利于并行计算;

2.对明文的主动攻击是可能的;

3.误差传送:一个明文单元损坏影响多个单元;


PHP:

/*data:待加密的明文信息数据。method:密码学方式。openssl_get_cipher_methods() 可获取有效密码方式列表。key,key。options 是以下标记的按位或:OPENSSL_RAW_DATA 、 OPENSSL_ZERO_PADDING: 1、0 2、OPENSSL_RAW_DATA=1 (推荐)用PKCS#7进行补位,返回原始数据,base64_encode后和0的结果相同。 3、OPENSSL_ZERO_PADDING=2 AES-128-CBC的加密结果为空,可换成其他模式 4、OPENSSL_NO_PADDING=3iv:非 NULL 的初始化向量。tag:使用 AEAD 密码模式(GCM 或 CCM)时传引用的验证标签。aad:附加的验证数据。tag_length:验证 tag 的长度。GCM 模式时,它的范围是 4 到 16。 * */$data = '白杨,不错,不错,不错,小小很乖。';$method = 'AES-128-CFB';$key = "约定的密码";$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($method));// opetions:0echo "opetions:0".PHP_EOL;$encrypted = openssl_encrypt($data, $method,$key, 0, $iv);echo $encrypted.PHP_EOL; //输出:sABO6CZqu8MYGCrPvnNkxEf9c48Fw7UeNnvuanZVDc4OGoRy1XpPM6lprvVQBpDtpzUKnYZBtWNhE7ySr7naaQ==$decrypted = openssl_decrypt($encrypted, $method,$key, 0, $iv);echo $decrypted.PHP_EOL.PHP_EOL; //输出:白杨,不错,不错,不错,小小很乖。// opetions:OPENSSL_RAW_DATA 1echo "opetions:OPENSSL_RAW_DATA".PHP_EOL;$encrypted = openssl_encrypt($data, $method,$key, 1, $iv);echo $encrypted.PHP_EOL;//输出:几行��I��Vnz��这样的原始数$decrypted = openssl_decrypt($encrypted, $method,$key, 1, $iv);echo $decrypted.PHP_EOL.PHP_EOL;//输出:白杨,不错,不错,不错,小小很乖。// opetions:OPENSSL_ZERO_PADDING 2echo "opetions:OPENSSL_ZERO_PADDING".PHP_EOL;$encrypted = openssl_encrypt($data, $method,$key, 2, $iv);$encrypted = base64_encode($encrypted);echo $encrypted.PHP_EOL;$decrypted = openssl_decrypt(base64_decode($encrypted), $method,$key, 2, $iv);echo $decrypted.PHP_EOL.PHP_EOL;// opetions:OPENSSL_NO_PADDING 3echo "opetions:OPENSSL_NO_PADDING".PHP_EOL;$str_padded = $data;if (strlen($str_padded) % 16) { $str_padded = str_pad($str_padded,strlen($str_padded) + 16 - strlen($str_padded) % 16, "\0");}$encrypted = openssl_encrypt($str_padded, $method, $key, OPENSSL_NO_PADDING,$iv);$encrypted = base64_encode($encrypted);echo $encrypted.PHP_EOL;$m = openssl_decrypt( base64_decode($encrypted) , $method, $key, OPENSSL_NO_PADDING,$iv);echo rtrim( rtrim( $m,chr(0) ), chr(7) ).PHP_EOL;