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)。