AES(Advanced Encryption Standard)是一种对称密钥加密算法,即双方使用同一段密码对数据进行加解密操作。
AES的分块区组长度必须是128 bit,密钥长度可以是128 bit,192 bit或256 bit,分别称为“AES-128”、“AES-192”、“AES-256”。 加密过程中使用的密钥是由Rijndael密钥生成方案产生。

加密原理

AES加密过程是在一个4×4的字节矩阵上运作,这个矩阵又称为“体(state)”,其初值就是一个明文区块(矩阵中一个元素大小就是明文区块中的一个Byte)。加密时,各轮AES加密循环(除最后一轮外)均包含4个步骤:

  1. MixColumns—为了充分混合矩阵中各个直行的操作。这个步骤使用线性转换来混合每内联的四个字节。
  2. SubBytes—通过一个非线性的替换函数,用查找表的方式把每个字节替换成对应的字节。
  3. ShiftRows—将矩阵中的每个横列进行循环式移位。
  4. AddRoundKey—矩阵中的每一个字节都与该次回合密钥(round key)做XOR运算;每个子密钥由密钥生成方案产生。

参考资料:

  1. AES加密算法的C++实现
  2. 高级加密标准

五种加密模式

AES是一种基于分组的加密模式,允许使用同一个分组密码密钥对多于一块的数据进行加密,并保证其安全性。分组密码自身只能加密长度等于密码分组长度的单块数据,若要加密变长数据,则数据必须先被划分为一些单独的密码块。通常而言,最后一块数据也需要使用合适填充方式将数据扩展到匹配密码块大小的长度。一种工作模式描述了加密每一数据块的过程,并常常使用基于一个通常称为初始化向量的附加输入值以进行随机化,以保证安全。

初始化向量(IV,Initialization Vector)是许多任务作模式中用于将加密随机化的一个位块,且通常无须保密随加密后的密文一起发出。

  1. ECB(电子密码本)
    最简单的加密模式,将需要加密数据分成若干块,对每块分别进行加密。

  2. CBC(密码块链接)
    数据分块后,每一块数据与上一块密文异或后再进行加密。

  3. CFB(密文反馈)
    加密模式和CBC类似,但其可以将块密码变为自同步的流密码, 不需要对数据进行填充操作。

  4. OFB(输出反馈)
    算法比较复杂,将块密码变成同步的流密码,它产生密钥流的块,然后将其与平文块进行异或,得到密文。

  5. CTR(计数器模式)
    与OFB相似,CTR将块密码变为流密码。它通过递增一个加密计数器以产生连续的密钥流。

ECB模式下IV为可选参数,CRT不使用IV而使用counter;ECB、CBC、OFB填充为密钥长度的整数倍,CFB填充为分块大小除以8的整数倍,CTR不需要进行数据填充。

实例代码

以CBC模式为例,以下是Python中的AES的加密代码,先要安装pycrypto‎

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# coding: utf-8
from Crypto.Cipher import AES
from Crypto import Random
import base64
key = Random.new().read(AES.block_size) # 随机生成密钥
iv = Random.new().read(AES.block_size) # 随机生成IV
BS = 16 # 分组数据长度
# 填充补齐最后一块数据
# 例如需要补5个字节,在后面填充5个\x05
# 补12个字节则填充12个\x0c
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS)
# 删除补充的数据
# 最后一位是\x06则删除末尾6个字节
unpad = lambda s : s[0:-ord(s[-1])]
msg = "Hello AES Encryption"
# Encryption
cbc_cipher = AES.new(key, AES.MODE_CBC, IV=iv)
cipher_text = iv + cbc_cipher.encrypt(pad(msg)) # 将IV和密文一起传送
# Decryption
cbc_decipher = AES.new(key, AES.MODE_CBC, IV=cipher_text[:16]) # 密文前16位为IV
# 前16位为IV,不需要解密
decrypted_text = cbc_decipher.decrypt(cipher_text[16:])
print 'CBC Mode Encrypted text: ', base64.urlsafe_b64encode(cipher_text) # 对字节数据进行base64编码
print 'CBC Mode Decrypted text: ', unpad(decrypted_text) # 去除末尾的填充字符

输出结果:

1
2
CBC Mode Encrypted text: lm4YYUlm3SWSDN3IU1UyFlCOETDvL49RWM_7xl95aUwl8JCdEiF4V3SEyqvniIzD
CBC Mode Decrypted text: Hello AES Encryption

总结

AES是广泛使用的一种加密方式,而pycrypto模块提供了比较方便的加密支持,不同加密模式的参数略有不同,在实际项目中应视需求,参考官方文档。