DES、IDEA和Rijndeal的算法流程
1 DES算法的描述
图3-1 DES的算法流程图
如(图3-1)所示:DES对64-位的明文分组进行操作。通过一个初始置换IP,将明文分组分成左半部分(L)和右半部分(R),各32位长。然后进行16轮完全相同的运算,这些运算被称为函数f,在运算过程中数据与密钥结合。经过16轮后,左、右半部分合在一起经过一个末置换IP-1(初始置换的逆置换),这样该算法就完成了。
图3-2 一轮DES的过程
在每一轮中(如图 3-2),密钥位移位,然后再从密钥的56位中选出48位。通过一个扩展置换将数据的右半部分扩展成48位,并通过一个异或操作与48位密钥结合,通过8个S盒将这48位替代成新的32位数据,再将其置换一次。这四步运算构成了函数f。然后,通过另一个异或运算,函数f的输出与左半部分结合,其结果即成为新的右半部分,原来的右半部分分成为新的左半部分。将该操作重复16次,便实现了DES的16轮运算。
假设Bi是第i次迭代的结果,Li和Ri是Bi的左半部分和右半部分,Ki是第i轮的48-位密钥,且f是实现代替,置换及密钥异或等运算的函数,那么每一轮就是:
Li=Ri-1
Ri=Li-1⊕f(Ri-1,Ki)
总述:DES是一个对称算法:加密和解密用的是同一算法(除密钥编排不同以外)。密钥的长度为56位。(密钥通常表示为64-位的数,但每个第8位都用作奇偶校验,可以忽略。)密钥可以是任意的56-位的数,所有的保密性依赖于密钥。
2 IDEA算法的描述:
图3-3 IDEA算法的流程图
图3-3是IDEA的一个纵览。64-位数据分组被分成4个16-位子分组:X1,X2,X3,和X4。这四个子分组成为算法的第一轮输入,总共有8轮。在每一轮中,这四个子分组相互间相异或,相加,相乘,且与6个16-位子密钥相异或,相加,相乘。在轮与轮间,第二和第三个子分组交换。最后在输出变换中四个子分组与四个子密钥进行运算。
在每一轮中,执行的顺序如下:
1. X1和第一个子密钥相乘。
2. X2和第二个子密钥相乘。
3. X3和第三个子密钥相乘。
4. X4和第四个子密钥相乘。
5. 将第1步和第3步的结果相异或。
6. 将第2步和第4步的结果相异或。
7. 将第5步的结果与第五个子密钥相乘。
8. 将第6步和第7步的结果相加。
9. 将第8步的结果与第六个子密钥相乘。
10.将第7步和第9步的结果相加。
11.将第1步和第9步的结果相异或。
12.将第3步和第9步的结果相异或。
13.将第2步和第10步的结果相异或。
14.将第4步和第10步的结果相异或。
每一轮的输出是第11、12、13和14步的结果形成的4个子分组。将中间两个分组交换(最后一轮除外)后,即为下一轮的输入。
经过8轮运算之后,有一个最终的输出变换:
Xi: 16-位明文子分组
Yi: 16-位密文子分组
Zi(r):16-位子密钥
: 16-位子密钥的相异或: 16-位整数的模216加: 16-位整数与216对应0子分组的模216+1乘1. X1和第一个子密钥相乘。
2. X2和第二个子密钥相加。
3. X3和第三个子密钥相加。
4. X4和第四个子密钥相乘。
最后,这4个子分组重新连接到一起产生密文。
产生子密钥也很容易。这个算法用了52个子密钥(8轮中的每一轮需要6个,其他4个用于输出变换)。首先,将128-位密钥分成8个16-位子密钥。这些是算法的第一批8个子密钥(第一轮6个,第二轮的头2个)。然后,密钥向左环移动25位产生另外8个子密钥,如此进行直到算法结束。
3 Rijndeal算法
设计思想:
RIJNDEAL密码的设计力求满足以下3条标准:
1. 抗所有已知的攻击。
2. 在多个平台上速度快,编码紧凑。
3. 设计简单。
当前的大多数分组密码,其轮函数Feistel结构或准Feistel结构,即将中间状态的部分比特不加改变地简单转置到其他位置。RIJNDEL没有这种结构,其轮函数是由三个不同的可逆一致变换组成的,称它们为三个“层”。所谓“一致变换”是指状态的每个比特都是类似的方法进行处理的。不同层的特定选择大部分是建立在“宽轨迹策略”的应用基础上的;简单地说“宽轨迹策略”就是提供抗线性密码分析和差分密码分析能力的一种设计。为实现宽轨迹策略,轮函数三层中的每一曾都有它自己的功能:
线性混合层 确保多轮之上的高度扩散。
非线性层 将具有最优的“最差情形非线性特性”的S盒并行使用。
密钥加层 单轮子密钥简单地异或到中间状态上,实现一次性掩盖。
在第一轮之前,应用了一个初始密钥加层。这一设计的用意很简单,就是为了使攻击者无法从明文端剥去其它计算部件。
为了使加密和解密算法在结构上更加接近,最后一轮的线性混合层与前面各轮的线性混合层不同。可以证明这种设计不以任何方式提高或降低该密码的安全性。
Rijndael是一个迭代型分组密码,其分组长度和密钥长度都可变,各自可以独立地指定128比特、比特、256比特。
Rijndael的明文分组称为状态,所有的操作都在状态之间进行。状态可以用以字节为元素的矩阵阵列图表示,该阵列有4行,列数记为Nb,Vb等于分组长度除以32。
密钥种子(Cipher Key)类似地用一个以字节为元素的矩阵阵列图表示,该阵列有4行,列数记为Nk,Nk等于分组长度除以32。以下的图就是Nb=6的状态和Nk=4的密钥种子。
A00
A01
A02
A03
A04
A05
A10
A11
A12
A13
A14
A15
A20
A21
A22
A23
A24
A25
A30
A31
A32
A33
A34
A35
K00
K01
K02
K03
K10
K11
K12
K13
K20
K21
K22
K23
K30
K31
K32
K33
一个明文按a00a10a20a30a01a11a21a31…的顺序影射到状态阵列中。同理,密钥也用相同的方法。当输出课文分组时,也是按相同的顺序从状态阵列中取出各字节的。将课文分组看作4Nb维向量,每一个分量是一个字节,记为(t0t1t2…t4Nb-1).则课文分组的第n个分量对应于状态阵列的第(j,k)位置上的元素,其中n=j+4k,0<=j<=3。
迭代的轮数记为Nr,Nr与Nb和Nk有关,以下的表给出了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的轮函数由四个不同的计算部件所组成,分别是:字节代替(ByteSub)、行移位(ShiftRow)、列混合(MixColumn)、加密钥(AddRoundKey)。
节代替(ByteSub) 是将状态阵列的每个字节做相同的变换,该变换由以下两个子变换所合成:
1. 首先将字节看作GF(28)上的原素,映射到自己的乘法逆;0字节影射到它自身。
2. 其次,将字节做如下的(GF(2)上的;可逆的)仿射变换:
= +
以上两个子变换合成的实现,采用一个8比特输入/8比特输出的S盒。
行移位(ShiftRow)
是将状态阵列的每个列视为系数在GF(28)上、次数小于4的多项式,被同一个固定的多项式c(x)进行x4+1的乘法。当然要求c(x)是模x4+1可逆的多项式,否则列混合变换就是不可逆的,因而会使不同的明文分组具有相同的对应密文分组。RUNDAEL的设计者所给出的c(x)为(系数用16进制数表示):
c(x)=’03’x3+’01’x2+’01’x+’02’
c(x)是与x4+1互素的,因此是模x4+1可逆的。由前面的讨论制知,列混合运算可表示为GF(28)上的可逆线性变换:
=这个运算需要做GF(28)上的乘法,但由于所乘的因子是三个固定的元素02,03,01,所以这些乘法运算仍然是比较简单的(注意到乘法运算所使用的模多项式为m(x)=x8+x4+x3+x+1)。
加密钥(AddRoundKey)
是将但轮子密钥阵列简单地与课文阵列进行比特异或。这里当然要求子密钥阵列与课文阵列是同阶的。
密钥扩展:
我们知道RUNDAEL的加密密钥的长度为4Nb(Nr+1)比特),这些加密密钥需要用4Nk字节密钥种子经密钥扩展算法得到。将密钥种子阵列的每一列称为一个字,则密钥种子共有Nk个字,要将其扩展为Nb(Nr+1)个字的加密密钥,其中前Nk个字的加密密钥就是种子阵列,后面的字是根据前面的字递归定义的。扩展算法有针对NK<=6和针对Nk>6的两个版本。
其中,函数SubByte(w)的输出字的每一个字节都是用RIJNDAEL的S盒作用到输入字W的对应字节所得到的。函数SubBit(w)的输出字是输入字W的1字节循环移位,即当输入字为W=(a,b,c,d)时,输出字为SubByte(w)=(b,c,d,a)。Rcon[j/Nk]为轮常数字,其值为(字节用16进制表示,同时理解为GF(28)上的元素):
Rcon[1]=(01,00,00,00)
Rcon[j]=((02)j-1,00,00,00);j=2,3,…
可以看出,加密密钥的前Nk个字是密钥种子,这之后的每一个字W[j]等于前一个字W[j-1]与Nk个位置之前的字W[j-Nk]的异或;不过当j/Nk为整数时,须先将前一个字W[j-1]经过以下一系列的变换:
1字节的循环移位RotByte→用S盒进行变换SubByte→异或轮常数Rcon[j/Nk]。
Nk>6或Nk<=6的密钥扩展算法的差别在于多了一种条件下的操作:当j为4的倍数时,须先将前一个字W[j-1]经过SubByte变换。
密码的加密算法
RIJNDAEL密码的加密算法为顺序完成以下操作:初始的密钥加:(Nr-1)轮迭代;一个结尾轮。
密钥扩展可以事先进行(预计算),且RIJNDAEL密码的加密算法可以用这一扩展密钥来描述:Rijndael(State,ExpandedKey)。