,AES的基本要求是:比三重DES快、至少与三重DES一样安全、数据分组长度为128-bit、密钥长度为128/192/256-bit,对应于密钥的不同长度,加密轮的次数也不尽相同。选定Rijndael算法为新的AES算法。算法的原型是Square算法,其设计策略为宽轨迹策略(针对差分分析和线性分析提出的,最大优点是可以给出算法的最佳差分特征的概率以及最佳线性逼近的偏差的界;由此可以分析算法抵抗差分密码分析以及线性密码分析的能力。)
AES加密标准是当下最广泛使用的对称密钥加密体系。AES加密标准已经广泛应用在互联网安全领域,譬如IPsec、TLS、Wi-Fi加密标准IEEE 802.11i、SSH、Skype等领域。
Rijndael设计思想
Rijndael没有Feistel结构,其轮函数是由三个不同的可逆均匀变换(每个比特都是用类似的方法进行处理的)组成的,称它们为3个“层”。不同的层选择的大部分是建立在“宽轨迹策略”的应用基础之上。
- 线性混合层 确保多轮之上的高度扩散
- 非线性层 将具有最优的“最坏情况非线性特征”的S盒并行使用
- 密钥加密 单轮子密钥简单地异或到中间状态上,实现一次性掩盖
在第一轮之前,用了一个初始密钥加层(其目的为在不知道密钥的情况下,对最后一个密钥加层以后的任一曾可简单地剥去,因此初始密钥加层对密码的安全性无任何意义。为了使加密算法和解密算法在结构上更加接近,最后一轮的线性混合曾与前面各轮的线性混合层不同,这类似于DES的最后一轮不做左右交换(这种设计不以任何方式提高或降低该密码的安全性)
Rijndael算法说明
该算法是一个迭代型分组密码,分组长度和密钥长度都可改变,各自可以独自地制定为128-bit、192-bit、256-bit
状态、种子密钥和轮数
算法的中间结果需要进行分组,称该分组为状态。所有的操作都在状态上进行。状态可以用以字节为元素的矩阵阵列表示,该阵列有4行,列数计为Nb。Nb等于分组长度除以32。
种子密钥类似地用一个以字节为元素的矩阵阵列表示,该阵列有4行,列数记为Nk,Nk等于分组长度除以32。
当然,可以将这些分组看成一维数组,数组中的每一个元素是上述阵列中的四个字节元素组成的列向量,显然,数组的长度可以分为4,6,8三种。四个字节的元素构成的列向量有时也称为字。
算法的输入和输出被看作是由8-bit字节构成的一维数组,其元素的下标范围为0(4Nb-1),因此,输入和输出以字节为单位的分组长度分别为16,24和32。输入的种子密钥也堪称是由8-bit字节构成的一维数组,其下标的范围为0(4Nb-1)。因此,种子密钥以字节为单位的分组长度也分别为16,24和32。
算法的输入是以字节为单位,按照列优先的顺序依次填入矩阵中。密钥也是一样。而输出也同样是依照相同的顺序取出。
迭代的轮数计为Nr,该数值与Nb和Nk相关
Nr | Nb=4 | Nb=6 | Nb=8 |
---|---|---|---|
Nk=4 | 10 | 12 | 14 |
Nk=6 | 12 | 12 | 14 |
Nk=8 | 14 | 14 | 14 |
轮函数
Rijndael的轮函数由4个不同的计算部件组成:字节代换(ByteSub)、行移位(ShiftRow)、列混合(MixColumn)、密钥加(AddRoundKey)
字节代换
字节代换是非线性变换,独立地对状态的每个字节进行。代换表(S-Box)是可逆的。
- 将字节看作GF(2^8)上的元素,映射到自己的乘法逆元,'00'映射到自己。(可以通过矩阵计算得出)
- 对字节做仿射变换
行移位
将状态阵列的各行进行循环移位,不同用的状态行的位移量不同。第0行不移动,第1行循环左移C1个字节,第二行循环左移C2个字节,第三行循环左移C3个字节。
Nb | C1 | C2 | C3 |
---|---|---|---|
4 | 1 | 2 | 3 |
6 | 1 | 2 | 3 |
8 | 1 | 3 | 4 |
列混合
列混合是AES中主要的Diffusion工序。其方式为对于每一个列,乘以一个4×4的矩阵。再加上一个相关的系数向量。
密钥加
密钥加时将轮密钥简单地与状态进行逐行比特异或。轮密钥由种子密钥通过密钥编排算法得到,轮密钥长度等于分组长度Nb
密钥编排
由密钥扩展和轮密钥选取两部分组成,其基本原则如下
- 轮密钥的比特数等于分组长度乘以轮数加1
- 种子密钥被扩展成为扩展密钥
- 轮密钥从扩展密钥中取,其中第一轮轮密钥取扩展密钥的前Nb个字,第2轮轮密钥去接下来的Nb个字,如此下去。
密钥扩展
扩展密钥以4字节为元素的一维阵列
扩展算法会根据Nk<=6和Nk>6有不同
当Nk<=6时,扩展算法如下:
KeyExpansion(byte Key[4 * Nk], W[Nb * (Nr + 1]){
for(i = 0; i < Nk; i++){
W[i] = (Key[4 * i], Key[4 * i + 1], Key[4 * i + 2], Key[4 * i + 3]);
for(i = Nk; i < Nb * (Nr + 1); i++){
temp = W[i - 1];
if(i % Nb == 0) temp = SubByte(RotByte(temp))^Rcon[i / Nk];
W[i] = W[i - Nk] ^ temp;
其中Key[4 * Nk]为种子密钥。函数SubByte返回4字节字,其中每一个字节都是用Rijndael的S盒作用到输入字对应的字节得到。函数RotByte也返回4字节字,由输入的字循环移位得到。
当Nk>6时,扩展算法如下:
KeyExpansion(byte Key[4 * Nk], W[Nb * (Nr + 1]){
for(i = 0; i < Nk; i++){
W[i] = (Key[4 * i], Key[4 * i + 1], Key[4 * i + 2], Key[4 * i + 3]);
for(i = Nk; i < Nb * (Nr + 1); i++){
temp = W[i - 1];
if(i % Nb == 0) temp = SubByte(RotByte(temp))^Rcon[i / Nk];
W[i] = W[i - Nk] ^ temp;