高级加密标准(AES、Rijndael)

来源:互联网 发布:js 修改样式 编辑:程序博客网 时间:2024/04/26 07:41

AES,也就是高级加密标准。
2000年,Rijndael被选择为高级加密标准。
AES是一个迭代型密码。加密的过程有些繁琐,其实弄懂了每一步,也不是太难理解。今天就一起学习一下AES吧!
先来看看AES的总体描述,在学习任何一个知识前需要了解下整体的框架。
1, 给定一个明文x,将State初始化为x,并进行AddRoundKey操作,即将RoundKey与State异或。
2, 对前Nr-1轮中的每一轮,用S盒对State进行一次代换操作SubBytes;对State做一置换ShiftRows;再对State做一次操作MixColumns;然后进行AddRoundKey操作。
3, 依次进行SubBytes,ShiftRows,AddRoundKey。
4, 将State定义为密文y。
上面都是些什么鬼!!!完全看不懂啊。。。
我们一步一步分析就可以了。
首先进行一些说明,AES是具有128比特的分组长度,也就是说每一次加密都是对128比特的数据进行加密,也就是16个字节,4个字,当然是二进制信息了,要是字母、汉字怎么办,很简单,变成二进制就ok了。就是我们说的明文,这个大家都知道!在AES的各种操作中我们都是以字节为单位,进行操作,也就是说,上面的很多看不懂的操作都是以字节为单位进行的。
其次AES有三种可选的密钥长度,即128比特、192比特、256比特。对应的加密轮数分别为10,12,14,也就是AES要对明文进行这么多轮的变换。这里我们只讲解Nr=10的情况,也就是加密轮数为10。
下面开始进入正题(合着上面的都不是正题),我们先看一下密钥的产生,上面的加密操作我们先不看(当然后面会解释的),来看下密钥的生成。
AES10轮加密需要11轮密钥,每一轮密钥包含16个字节(也就是4个字),记为KEY0,KEY1,……,KEY15,这个很容易理解的,为什么每一轮需要16个字节呢,因为我们加密的明文的分组长度为128比特,也就是16个字节。要对应起来啊!在下面的解释中会体现出来的。
现在我们需要初始的密钥,也就是这16个字节。当然你随便想是什么就可以是什么,好像似乎没有什么限制,当然最好选的随机一些,不是随便!
把这16个字节作为第一轮的密钥,然后我们通过一个KeyExpansion来对它进行扩展,也就是求出后面10轮的密钥,凑够11轮啊!
KeyExpansion首先是对当前轮的密钥进行两个操作,一个叫做RotWord,一个叫做SubWord。
先看RotWord,从名字就可以看出是对字的操作。每一轮有4个字,RotWord就是对每个字的4个字节进行移位操作,循环左移8位,也就是循环左移1个字节:
假如我们的字为0xABCDEFGH,那么对这个字进行RotWord后,变成0xCDEFGHAB,这个好理解吧,也就是换个位置,老二变成了老大,老三变成了老二,老四变成了老三,老大堕落了,变成了老末。就是简单的移位。
然后是SubWord,SubWord就更简单了,需要使用AES的S盒,S盒是个什么玩意,就是你输入进去一个数,然后出来一个数,只要对我们的字节进行替换就行了。S盒是一个16*16的矩阵,输入是8比特的数,输入也是8比特的数。比如现在密钥的其中一个字为0xABCDEFGH,把AB输入进去,出来的是A’B’,当然后面还有,最后这个字变成了0xA’B’C’D’E’F’G’H’,这个查表就可以了。
经过这两步以后还没完,后面就是KeyExpansion的另外一部分,
给出10个字:
RCon[1] = 01000000
RCon[2] = 02000000
RCon[3] = 04000000
RCon[4] = 08000000
RCon[5] = 10000000
RCon[6] = 20000000
RCon[7] = 40000000
RCon[8] = 80000000
RCon[9] = 1B000000
RCon[10] = 36000000
至于为什么是这样,我也不知道。
for i = 0 to 3
w[i] = ( key[4i] + key[4i+1] + key[4i+2) + key[4i+3] )
key就是初始的16比特的密钥。
for i = 4 to 43
temp = w[i-1]
if(i%4 == 0)
then temp = SubWord(RotWord(temp))^RCon[i/4]
w[i] = w[i-4] ^ temp
return (w[0],……w[43]);
上面的w就是代表字的意思,初始密钥为w[0],w[1],w[2],w[3],然后根据上面的KeyExpansion操作我们就得到了11轮的密钥,每一轮密钥是4个字,16个字节。
加密部分:
前奏说了这么多,终于到了加密的部分:
再来复习下加密的过程:
1, 给定一个明文x,将State初始化为x,并进行AddRoundKey操作,即将RoundKey与State异或。
2,对前Nr-1轮中的每一轮,用S盒对State进行一次代换操作SubBytes;对State做一置换ShiftRows;再对State做一次操作MixColumns;然后进行AddRoundKey操作。
3, 依次进行SubBytes,ShiftRows,AddRoundKey。
4,将State定义为密文y。
X是16个字节的明文,我们把它写成一个4*4的矩阵,
X0 X4 X8 X12
X1 X5 X9 X13
X2 X6 X10 X14
X3 X7 X11 X15
注意我们写的顺序,是按照列写的。
这个就是我们初始的State,State也是4*4的矩阵。现在我们明文换了个名字。并且还要换个写法:
S(0,0) S(0,1) S(0,2) S(0,3)
S(1,0) S(1,1) S(1,2) S(1,3)
S(2,0) S(2,1) S(2,2) S(2,3)
S(3,0) S(3,1) S(3,2) S(3,3)
每一个S都是一个字节,我们来继续看第一步:
给定一个明文x,将State初始化为x,并进行AddRoundKey操作,即将RoundKey与State异或。
哦!下面该是AddRoundKey操作了,我们刚才产生了11轮密钥,这时候就要用上了,将State与第一轮密钥进行异或,轮密钥是16个字节,正好这里明文也是16个字节,所以进行异或就好了。这样第一步我们就完成了,简单吧。
然后我们看第二步:对前Nr-1轮中的每一轮,用S盒对State进行一次代换操作SubBytes;对State做一置换ShiftRows;再对State做一次操作MixColumns;然后进行AddRoundKey操作。
S盒就是一个替换操作,与刚才密钥的产生使用方法是一样的,然后进行ShiftRows操作,也就是对这个4*4的矩阵进行一个行的变换,这个也是非常的简单:
第0行我们保持不变,还是S(0,0),S(0,1),S(0,2),S(0,3);
第1行我们将它循环左移一个格:也就是变成了S(1,1),S(1,2),S(1,3),S(1,0);
第2行我们循环左移两个格;
第3行我们循环左移三个格。
最后变成了下面这样:
S(0,1) S(0,2) S(0,3) S(0,0)
S(1,1) S(1,2) S(1,3) S(1,0)
S(2,1) S(2,2) S(2,3) S(2,0)
S(3,1) S(3,2) S(3,3) S(3,0)
这样就完成了ShiftRows的操作,第二步我们还没完成,
下面是MixColumns操作,也就是列混淆,这里涉及域的概念,默认你们会的!
设x和x+1是一个乘域元素,对应的比特串为00000010和00000011。这里我们都是在模2的情况下计算的。
C表示对第C列元素进行操作,我们需要进行4次,因为有4列啊!
For I = 0 to 3
Do ti = s(I,c) //对每一列进行操作。
U0 = FieldMult(x,to)^FieldMult(x+1,t1)^t2^t3
U1 = FieldMult(x,t1)^FieldMult(x+1,t2)^t3^t0;
U2 = FieldMult(x,t2)^FieldMult(x+1,t3)^t0^t1;
U3 = FieldMult(x,t3)^FieldMult(x+1,t0)^t1^t2;
For I = 0 to 3
S(I,c)=Ui

异或都是在模2的情况下计算的。域的运算其实并不难,在这我就不解释了。。。
也就是我们把一列的四个字节给t,经过上面的变换变成了U0,U1,U2,U3,作为列的元素,也就是替换原来的S。
等等,第二步还没完成,还要进行AddRoundKey操作,也就是与当前轮的密钥进行异或,每一轮的密钥都是16个字节的。这样我们就完成了第二步。
第三步就简单了,依次进行SubBytes,ShiftRows,AddRoundKey。
SubBytes就是输入到S盒,再替换,ShiftRows就是行的循环移位,上面已经解释了。AddRoundKey就更不用说了。
然后是第四步:将State定义为密文y。
第四步就大功告成了,我们就成功的得到了密文。
过程有些繁琐,分析起来还是比较简单的。
附上S盒:**
这里写图片描述

0 0
原创粉丝点击