在有些技术文献和资料里常用Rijndael代之AES算法。AES是一个对称的、块加密算法,什么意思?
“对称”的意思是:
(1)甲方选择某一种加密规则,对信息进行加密;
(2)乙方使用同一种规则,对信息进行解密。
这种加密模式有一个最大弱点:甲方必须把加密规则告诉乙方,否则无法解密。
“块”的意思是:
如果待加密数据太长,则需要按固定长度分割后,对每段明文数据依次单独加密。AES算法数据分组的长度和秘钥长度相互独立,都可以改变:
整个AES加密结构如下:
AES加密核心流程分两个:秘钥变幻和明文加密。这两个过程合起来组成AES的核心加密流程。下面分别了解一下这两个过程。
秘钥变幻
前面说过,AES秘钥长度是可变的,所以秘钥变幻的第一步是将秘钥按矩阵方式进行排列:
上图中依次是秘钥长度为128bit、192bit和256bit的情况。以128bit为例,其变幻过程如下。
1、 首先需要一个常量矩阵Rcon:
Rcon矩阵的每一项都满足有限域上的乘法,GF表示伽罗瓦域。听起来很高大上的样子,当然域论本身确实很深奥。但是说白了非常简单,即域的加法或者乘法的结果必须是{0x00,0x01,0x02,… 0xfe,0xff}这组数里的结果,就叫做有限域。有限域上的加法就是异或(xor)操作,乘法稍微有点绕。0x01乘以任何数都是任何数本身,这和普通算术是一样的。如果0x02乘以任何数时,需要区分:
1)、如果该数<0x80,结果等于该数左移位1bit;
2)、如果该数>=0x80,结果等于该数左移位1bit后再与0x1b进行异或操作。
以此类推,有了0x01、0x02的运算基础,我们就可以定义任意数的乘法了。例如任意数m和0x03的乘积可以表示为:
m*0x03=m*(0x02+0x01)=(m*0x02)+(m*0x01)
2、 接下来正式开始秘钥变幻
将秘钥 分成4个列向量
第一轮秘钥变幻的结果记作K4、K5、K6和K7,那么第一轮秘钥变换的方式如下:
同样,第二轮秘钥变换结果记作K8、K9、K10和K11,方式同上。那么秘钥一共要经历多少轮变换呢?
数据加密
一轮AES算法的数据加密包含四种操作,除了最后一轮(后面单独说明):
1)、 SubBytes:字节替换,即查表;
2)、 ShiftRows:循环移位;
3)、 MixColums:列混合;
4)、 AddRoundKey:轮秘钥加法运算。
还是以例子来说明这个过程,假如待加密数据和初始秘钥分别如下:
1)、 SubBytes:又叫S盒变换,主要操作是将明文数据里的每个字节,分别以高4bit和低4bit作为索引在S下边中进行查找。x=高4bit,y=低4bit。
待加密数据经过S变换,结果如下:
S盒变换结果是
2)、 ShiftRows 循环行移位,就太简单不过。S变换后的结果,第一行向左循环移0个字节,第二行循环左移1个字节,以此类推:
ShiftRows的结果
3)、 MixColums 行混合稍微就麻烦点,第2步结果的每一列和一个固定的常量矩阵C做有限域上的乘法运算:
所以,计算过程及结果如下:
最终计算结果如下:
4)、 AddRoundKey:就是将第3步的结果和计算出来的第一个轮秘钥(K4K5K6K7)进行逐项加法运算,注意初始秘钥是不参与AES加密运算,它只负责生成后续的各个轮秘钥:
+
=
经过上述四步处理后,一轮AES加密就完成了。
本例中,一共需要做10轮加密,其中最后一轮不需要做AddRoundKey操作。从第二轮加密开始,参与AddRoundKey运算的秘钥,就是秘钥扩展时生成的轮秘钥。现在让我们会过头来看一下,如何根据初始秘钥计算各个轮秘钥。
先看一下扩展秘钥的计算流程图,前面已经提到过:
初始秘钥前面也提到过:
看一下秘钥计算过程。 计算K4,先对K3先做S盒变换,然后“向上”循环移一个字节,最后的结果如下:
最后,上述结果和K0以及Rcon第一列进行加法运算,计算K4:
同样地,K5、K6和K7的计算方法也非常简单了,直接上结果。第一个轮秘钥如下:
计算第二个轮秘钥的方法也类似。每个轮秘钥除了其第一列计算起来特殊一点,剩下三列都还好。所以最后,所有轮秘钥的结果大概就是下面这个样子。
因此,说白了,在AES每一轮加密过程,依次执行SubBytes、ShiftRows、MixColums和AddRoundKey,只是每次加密所用到的秘钥是上述经过计算之后得到的扩展秘钥,而非AES原始输入秘钥。