AES加密【转】

来自:http://www.cnblogs.com/block2016/p/5596676.html

AES是一个对称密码,旨在取代DES成为广泛使用的标准。

一、AES的加密过程

 AES加密【转】

二、AES的数据结构

加密解密算法的输入是一个128位分组。这些分组被描述成4×4的字节方阵,这个分组被复制到state数组中,并在加密和解密的每一阶段都被修改。在字节方阵中,每一格都是一个字,包含了4字节。在矩阵中字是按列排序的。

 AES加密【转】

 加密由N轮构成,轮数依赖于**长度:16字节**对应10轮,24字节**对应12轮,32字节对应14轮。

 AES加密【转】

三、加密解密的详细结构

AES未使用Feistel结构。其前N-1轮由4个不同的变换组成:字节代替、行移位、列混淆和轮**加。最后一轮仅包含三个变换。而在第一轮前面有一个起始的单变换(轮**加),可以视为0轮。

  字节代替SubBytes):用一个S盒完成分组的字节到字节的代替。

  行移位ShiftRows):一个简单的置换。

  列混淆MixColumns):利用域GF(28)上的算术特性的一个代替。

  轮**加AddRoundKey):当前分组和扩展**的一部分进行按位异或XOR

 AES加密【转】

首尾使用轮**加的理由:若将其他不需要**的阶段放在首尾,在不知道**的情况下就能计算其逆,这就不能增加算法的安全性。

加密原理:轮**加实际是一种Vernam密码形式,其本身不难被**。另外三个阶段一起提供了混淆、扩散和非线性功能。这三个阶段没有涉及**,就它们自身而言,并未提供算法的安全性。然而,该算法经历一个分组的XOR加密(轮**加),再对该分组混淆扩散(其他三个阶段),再接着又是XOR加密,如此交替进行,这种方式非常有效非常安全。

可逆原理:每个阶段均可逆。对字节代替、行移位和列混淆,在解密算法中用它们相对应的逆函数。轮**加的逆就是用同样的轮**和分组相异或,其原理就是ABB = A。和大多数分组密码一样,AES解密算法按逆序利用扩展**,然而其解密算法和加密算法并不一样,这是由AES的特定结构决定的。图5.3中加密和解密流程在纵向上是相反的,在每个水平点上,state数组在加密和解密函数中都是一样的。

 AES加密【转】

四、AES的变换函数

1、字节代替变换

 AES加密【转】

字节代替变换是一个简单的查表操作。AES定义了一个S盒,它是由16×16个字节组成是矩阵,包含了8位所能表示的256个数的一个置换。State中每个字节按照如下方式映射为一个新的字节:把该字节的高4位作为行值,低4位作为列值,以这些数值为索引从S盒的对应位置取出元素作为输出。如,十六进制数{95}所对应的S盒行值是9,列值是5S盒中在此位置的值是{2A},相应的,{95}被映射为{2A}

S盒的构造

(1)按字节值的升序逐行初始化S盒(相当于每个值都代表了坐标)

(2)把S盒的每个字节映射为它在有限域GF(28)中的逆

(3)把S盒中的每个字节的8个构成位记为(b7,b6,b5,b4,b3,b2,b1,b0)。对S盒的每个字节的每个位作如下变换:

  bi’=b(i+4)mod8b(i+5)mod8b(i+6)mod8b(i+7)mod8ci          (5.1

  这里ci 是指值为{63}的字节c的第i位。

  AES标准用矩阵形式描述了这个变换:

   AES加密【转】

逆字节代替变换则采用逆S盒,

S盒的构造

(1)按字节值的升序逐行初始化S

(2)利用式5.1的逆变换,该逆变换如下:

  bi’=b(i+2)mod8b(i+5)mod8b(i+7)mod8di          (5.3

  这里di 是指值为{05}的字节d的第i位。也可以用矩阵形式描述:

   AES加密【转】

3求其在GF(28)内的乘法逆

 

可逆证明:

令字节代替变换和逆字节代替变换中的矩阵分别为XY,常量cd的向量表示分别为CD。对于某个8位的向量B,式5.2变成了B’=XBC。我们需证明Y(XBC)D=B

 AES加密【转】

DES加密的S盒的区别

  1、AESS盒的原理是运用了GF(28)的乘法逆和矩阵的可逆运算来保证加密与解密过程的可逆性。DESS盒设计主要是为了确保非线性关系,并不需要可逆。因而在设计理念上有极大的不同。

  2、AESS盒与DESS盒形式上差别也很大,AESS盒输入和输出的位数相同,均为128位,大小为16×16的字节矩阵,且只有1组;而DESS盒输入6位,输出只有4位,大小是4×16的位矩阵,并且有8组。在输入的坐标选择规定上亦有不同。

 

2、行移位变换

操作本身很简单,将state数组的第一行保持不变,第二行循环左移一个字节,第三行循环左移两个字节,第四行循环左移三个字节。

 AES加密【转】

其逆变换则将移位的几行执行相反方向的移位操作即可。

基本原理

由于轮**加、字节代替变换都是逐列地作用在state数组上,每一轮的行移位变换将会打乱列排列,使得保密性得到很大的提升。

3、列混淆变换

列混淆变换实际上是使用乘法矩阵(注意:其运算中涉及的加法和乘法都是定义在GF(28)上的加法和乘法,目的就是为了确保运算结果不会溢出定义域),可用以下式子描述。

 AES加密【转】

逆向列混淆变换可由如下矩阵乘法定义

 AES加密【转】

其可逆性可以简单运算得到证明

基本原理

5.3中矩阵的系数是基于码字间有最大距离的线性编码,这使得在每列的所有字节中有良好的混淆性。列混淆变换和行移位变换使得经过几轮变换后,所有的输入位和所有的输出位相关。

此外,列混淆变换的系数,即{01}{02}{03}是基于算法实现角度考虑的。不过,逆向列混淆变换的系数则更加难以实现,然而加密被视为比解密更重要,因为:

  1、对于CFBOFB密码模式,仅用到加密算法

  2、和任何其他分组密码一样,AES能用于构造消息验证码,这仅仅用到了加密过程。

 

4、轮**加变换

这个比较简单,没有太多好说的,**扩展的复杂性是确保算法安全性的重要部分。

 

以下是描述单轮AES的另一个视角,强调各变换的机制和输入。

 AES加密【转】

 

 

五、AES的**扩展

AES**扩展算法的输入值是4个字(16字节),输出值是一个由44个字组成(176字节)的一维线性数组。以下伪码描述了这个扩展:

  KeyExpansion(byte key[16], word w[44]){

    word temp

    for(i=0; i<4; i++)  //将输入的**直接复制到扩展**数组的前四个字

      w[i]=word(key[4*i],key[4*i+1],key[4*i+2],key[4*i+3]);

    temp = w[i-1];

    if(i mod 4 == 0)  //w数组下标为4的倍数的元素采用更复杂的函数来计算

      temp = SubWord(RotWord(temp))Rcon[i/4];

    w[i] = w[i-4] + temp; //每一个新增的字w[i]依赖于w[i-1] w[i-4]

  }

  RotWord的功能是字循环,即使一个字的4个字节循环左移1个字节。

  SubWord是利用S盒对输入字的每个字节进行字节代替。

  Rcon[i]是轮常量,代表一个字,这个字最右边三个字节总是0,因此字与Rcon异或,其结果只是与该字最左边的那个字节相异或。每一轮的轮常量都不相同,其定义为

  Rcon[i] = (RC[i],0,0,0),其中RC[1] = 1RC[i] = 2•RC[i-1] 乘法是定义在域GF(28)上的。

  RC[i]的值按照十六进制表示为

 AES加密【转】

轮常量取不同值就是为了消除不同轮**产生方式上的对称性或相似性。

 

**扩展算法的设计规范:

1、找到**或轮**的部分位不足以计算出轮**的其他位;

2、它是一个可逆的变换(即知道扩展**中任何连续的Nk个字能够重新产生整个扩展**,Nk是构成**所需的字数);

3、能够在各种处理器上有效地执行;

4、使用轮常量消除对称性;

5、将**差异性扩散到轮**中的能力,即**的每个位能影响轮**的许多位;

6、足够的非线性以防止轮**的差异完全由**的差异所决定。

 

改进--等价的逆算法

上文所述的标准解密流程与标准加密流程并不完全一致,加密每一轮的流程是:字节代替-->行移位-->列混淆-->轮密加。而解密每一轮的流程是:逆向行移位-->逆向字节代替-->轮密加-->逆向列混淆。

可以对解密构成进行改进,使得解密流程与加密流程等效。

1、交换逆向行移位和逆向字节代替:

由于逆向行移位并不影响state数组中字节的内容,而逆向字节代替也不会影响state数组中字节的位置,因而两者可以交换顺序而不影响解密。

2、交换轮**加和逆向列混淆:

这两种操作均不会改变state中字节的顺序,给定状态Si和给定轮**wi,可证明

逆向列混淆(Siwi)= [逆向列混淆(Si)][逆向列混淆(wi)]

这个等式显然是正确的,因而如果要改变这两种操作的顺序,则必须改进逆向列混淆的操作,即先对轮**应用逆向列混淆(注意,无需对首尾的轮**应用逆向列混淆)。最终,改进后的解密流程如下图:

 AES加密【转】