随着计算机通信技术的飞速发展以及互联网的广泛应用,人们对信息安全的需求也越来越高。信息安全已经成了当今尤为重要的且亟待解决的问题。目前,高级加密标准(AdvancedEncryptionStandard,AES)还没有为人所知的漏洞,AES算法可以说是当前密码算法设计最高水平的反映。用硬件实现数据加密已经成为信息安全的主流。国外一些机构已经推出IP核,国内在加密算法的研究及应用方面起步较晚,随着AES算法日益受到人们的广泛关注,对硬件实现的AES产品的需求也稳步攀升。
文章阐述了Rijndael算法的设计特色,介绍了AES在密码分析方面国内外已
有的一些理论分析成果,描述了AES算法采用软件和硬件实现方案。此外,本文章从数学基础的知识上阐明了AES算法的四个步骤。从AES算法抵抗强力攻击能力,抵抗差分分析和线性密码分析的能力,抵抗渗透攻击能力,抵抗代数计算攻击能力,抵抗XSL攻击能力,弱密钥的分析这几个方面进行了分析从而说明AES的安全性能。我们根据算法的安全性、代价以及算法与实现特性的原则
实现了AES的算法,从密钥编排方案分析了密钥的设计准则和选取。 关键词:AES算法 加密 解密 安全性能分析
第一章 绪 论
1. 题目背景
科技的发展特别是网络的发展使计算机深入到了各行各业的方方面面,计算机在带来方便和提高了工作效率的同时却也带来了各种各样的新问题,其中信息安全问题最为突出,随着计算机信息安全要求的不断提高, 计算机保密系统已变得越来越重要,密码学应用不再是局限于军事、国防等有限领域,而是迅速的走进了千家万户。
2. AES算法密码分析的进展
对称密码加密系统中最著名的是数据加密标准 D E S ( D a t a E n c r y p t i o n S t a n d a r d ) 、 高级加密标准 A E S ( A d v a n c e d E n e r y p t i o n S t a n d a r d ) 和国际数据加密标准 I D E A( I n t e r na t i o n a l D a t a E n e r y p t i o n A l g o r i t hm) 。1 9 7 7年,美国国家标准局正式公布并实施了数据加密标准D E S ,公开了它的加密算法 ,并批准用于非机密单位和商业上的保密通信。随后,D E S成为全世界使用最广泛的加密标准。但是,经过多年的使用,已经发现了D E S的很多不足之处, 对 D E S的破解方 法也有日趋得逞之势。美国国家标准和技术协 会 NI S T( t h e N a t i o n a l I n s t i t u t e o f S t a n d a r d s a n d T e c h — n o l o g y ) 在 1 9 9 7年 1月2日正式宣布了公开征集高 级加密标准 A E S 。2 0 0 0年 l 0月2日, N I S T宣布 R i j n d a e l 算法被选中成为将来的 A E S 。R i j n d a e l 算法 是在 1 9 9 9年下半年, 由研究员 J o a n D a e m e n和 V i n c e n t R i j m e n创建的。2 0 0 1年1 1 月2 6日, N I S T正式公布了新标准 A E S , 其编号为 F I P S P U B S 1 9 7 J 。新标准 A E S将会代替旧的D E S而日益成为加密各种形式的电子数据的实际标准。
2002年亚洲密码分析研讨会上,Courtois[16]提出一种称为XSL攻击的分组密码分析新方法,主要思想是用一系列次数低、方程数大于变元数的超定方程组
来描述密码系统,通过解方程组来破解分组密码。同年美洲密码分析研讨会上,Murphy[17]设计了一种新的算法BES(Big Encryption System),将AES中GF(28)和GF(2)上的两种域运算归结为域GF(28)上的运算,使AES成为某种消息空间和密钥空间下的BES,通过研究形式更为简洁的BES,可以更清晰地了解AES算法内部的数学结构。2002年第297期《科学》杂志[18]高度评价了这两个最新分析成果。
韦宝典[25]利用Walsh谱理论分析Rijndael算法S盒的严格雪崩特性、扩散特性和相关免疫性等密码性质,提出了广义自相关函数的概念,解决了严格雪崩准则和扩散准则阶数的确定问题;基于等价类的划分、线性方程组的求解和标准基之对偶基的计算,给出了域元素分量代数表达式的3种求法,提出了一种基于生日悖论、利用活动性进行攻击的新方法;指出了Square-6攻击是不成功的,并给出了修正攻击方案。
第二章 基础设置
AES算法是一些相当复杂的运算,虽然本文要实现的只是8位处理器上实现128位的运算,但还是很有必要采用模块化思想按照层次结构来设计及实现一些其它的辅助函数,而不是把它们内嵌在算法函数内,这样既能够避免算法函数的程序代码的过分冗长、使代码清晰易懂、突出算法过程又能够使程序易于测试、排错、更新和复用。由于本文重点在乘法类算法,下面只介绍一些关键的辅助函数,其它辅助函数要到相关算法使用到时再简略介绍。
1. AES简介
密码算法的理论与实现研究是信息安全研究的基础。对各类电子信息进行加密,在其存储、处理、传送以及交换过程中实施保护,是保证信息安全的有效措施。数据加密标准DES于1977年1月向社会公布,它是第一个世界公认的实用分组密码算法标准。但在经过20年的应用后,DES已被认为不可靠。3DES作为DES的替代,密钥长度为168bits,可克服穷举攻击问题。同时,3DES的底层加密算法对密码分析攻击有很强的免疫力。但由于用软件实现该算法的速度慢,使得3DES不能成为长期使用的加密算法标准,需要一种新的高级加密标准来替代。AES具有密钥灵活性及较高的可实现性,具有较高的安全性能及实现效率,其密钥建立时间极短,且灵敏性良好。Rijndeal算法给出了最佳查分特征概率,进行了算法抵抗差分密码分析以及线性密码分析。无论Rijndeal使用反馈模式或无反馈模式,其硬件和软件实现性生能都表现优秀。此外,Rijndeal对内存的极低需求使其适合于在存储器受限环境下使用,并能够表现出极好的性能。
AES是一个迭代的、对称密钥分组的密码,它可以使用128、192和256位密钥,并且用128位(16字节)分组加密和解密数据。与公共密钥密码使用密钥对不同,对称密钥密码使用相同的密钥加密和解密数据。通过分组密码返回的加密数据的位数与输入数据相同。迭代加密使用一个循环结构,在该循环中重复置换(permutations)和替换(substitutions)输入数据。
AES加密算法包括字节替换SubBytes()、行移位ShiftRows0、列混合MixColumns0和密钥加AddRoundKey()等函数。本文只研究分组长度和密钥长度均为128位的情况,记做AES一128。AES一128算法对状态矩阵进行操作。状态矩阵是128位数据按列优先原则排列的4x4矩阵,矩阵中的每一个元素为一个字节。AES一128算法要进行10轮轮变换,加密时轮变换主要有字节替换SubBytes()、行移位ShiftRows0、列混合MixColumns0和密钥加AddRoundKey()运算。对于每次轮变换,AES算法需要一个轮密钥,该轮密钥由初始密钥经密钥扩展函数生成。
1.1 AES与3DES的比较
算法名称 算法类型 密钥长度 速解密时间(建设资源消度 机器每秒尝试255个密钥) AES 对称block密码 3DES 对称feistel密码 128、192、256位 112位或低 46亿年 168位 中 高 1490000亿年 低 耗
2. AES算法的数学基础
有限域就是具有有限个元素的域,元素个数必须是一个素数的幂P,n为正整数
并称为域的阶,P为素数并称为有限域的特征j。在Rijndael的描述中均使用以2为特征的有限域,并用符号“o”表示2特征域中的加法运算。对每一个素数幂恰好存在一个有限域,用CF(p)表示。当凡=1时的有限域记为GF(P),其元素可以用集合{0,1,…,P一1}来表示,该域的两种运算则是“模P的整数加法”和“模P的整数乘法”。
3. AES和Rijndael的区别
Rijndael和AES之间的唯一差别在于各自所支持的分组长度和密码密钥长度的范围不同。
Rijndael是具有可变分组长度和可变密钥长度的分组密码。其分组长度和密钥长度均可独立地设定为32比特的任意倍数,最小值为128比特,最大值是256比特。我们可以定义具有更大分组长度和密钥长度的各种版本的Rijndael,但目前似乎没有必要。
AES将分组长度固定为128比特,而且仅支持128、192或256比特的密钥长度。在AES的选择过程中,Rijndael所具有的额外的分组长度和密钥长度没有评估。因此,这定在当前的FIPS标准中也为被采用。
4. AES算法的分析
一个密码算法的有效性首先体现在可靠的安全性上。Rijndael算法设计采用针对差分和线性密码分析提出的宽轨迹策略(WTS),其最大优势是可以给出算法最佳差分特征的概率以及最佳线性逼近偏差的界;使用简单的部件组织成清晰的结构,便于算法安全性的分析。当然,在密码学界永远没有绝对的安全,Rijndael算法也不例外,如其明显的代数结构对安全性的潜在威胁已经受到一些学者的质
疑。本文从简化算法攻击、算法结构性质分析以及密码分析的进展等方面对AES算法的密码分析状况进行讨论。
4.1 简化算法攻击
目前尚未出现对完整Rijndael算法的成功攻击,只提出了几种针对简化算法的攻击方法。最有名的当数密码设计者自己提出的Square攻击,其主要思想是利用第4轮字节替换前后平衡性的改变来猜测密钥字节,对128比特密钥下4到6轮简化算法有效。Biham[2]等对Square攻击进行改进,时间复杂度降为原来的一半,并认为颠倒轮密钥的顺序可将攻击复杂度降低28。Lucks[3]利用密钥生成算法的弱点,将Square攻击的密钥长度扩展到192和256比特,攻击7轮简化算法比穷尽搜索快。Ferguson[4]利用“部分和”技术将6轮Square攻击的复杂度从272降到244,并推广到7轮和8轮简化算法,指出密钥生成算法中几个违背设计准则的特性,利用慢扩散性设计了一个针对256比特密钥下9轮简化算法的密钥相关攻击方案。
Gilbert[5]利用局部函数间的冲突特性对4到7轮简化算法进行了攻击。Cheon等将5轮不可能差分攻击推广到6轮,复杂度高于相应的Square攻击,但仍快于密钥穷尽搜索。Koeune[6]描述了一种计时攻击,通过对每个密钥数千次的测量,展现攻破一个不良的现实设计的过程。Golic[7]则指出AES算法虽然能够通过乘法掩盖来抵抗简单能量攻击(SPA),对差分能量攻击(DPA)却无能为力。
4.2 算法结构性质分析
密码代数结构的任何弱点都将有利于密码的分析和破译。因此,在对Rijndael简化算法进行攻击尝试的同时,人们也把相当多的精力集中到算法内部结构各种性质的研究上。Ferguson[8]给出了Rijndael算法一个直观而紧凑的代数表示形式;Filiol[9]则将算法的每一输出比特看作以明文比特和密钥比特为变量的布尔函数
fi(p1,,pn,k1,,kn'),用Mōbius变换将之计算出来,研究其低次项的分布
情况,比较fi与完全随机的布尔函数代数正规式的差异,结果发现Rijndael算法
布尔函数的随机特性并不十分理想。
Barkan[10] 替换算法中的不变常量(如既约多项式、列混合运算中的系数和S盒中的仿射变换),产生新的等价对偶密码(平方对偶、对数对偶和自对偶等数百种之多)。在此基础上,可以选择比原算法快的对偶算法,在加解密中使用不同的对偶密码或每次随机选择不同的对偶密码以抵抗错误攻击和能量攻击。但是,由于对偶密码的结构容易分析,并易于转换成原算法,可能会有助于实施差分或线性攻击,所以对偶密码的存在也可能是对Rijndael算法的一种潜在威胁。
Song[11]为SPN分组密码引入了替换差分的概念,研究S盒替换距离的分布特性,并认为,如果知道给定分组密码S盒的替换距离,便可在密码分析中选择有一定输入差分的明文来确定可能的密钥,这种分析方法不依赖于密钥,可用于分析Rijndael算法的第1轮。Fuller[12]等指出Rijndael算法S盒的分量函数之间存在等价关系si(x)sj(Dijxa)bxc。这种等价关系有助于降低S盒硬件实现成本,但从安全角度看,可能会引发对Rijndael算法的攻击。他们利用布尔函数局部结构中的相邻特性,通过寻找等价参数Dij、a、b和c的方法间接证明了分量函数之间的等价关系。Youssef[13]则将S盒分量函数间的等价关系推广到整个轮函数。
Murphy[14]发现任何明文或明文差分经过Rijndael算法线性扩散层16轮迭代后会重现,Wernsdorf[15]则指出Rijndael算法的轮函数构成交换群。
5. AES 算法的设计原理
GF(28)中乘法使用的多项式是8次不可约多项式列表中的第一个多项式。 ByteSubstitution(称为S盒)在设计时考虑到抵抗差分密码分析、线性密码分析的要求,应满足以下条件: (1) 可逆性;
(2) 输入比特的线性组合与输出比特的组合之间的最大非平凡相关性的极小
化;
(3) 异或差分表中最大非平凡值的极小化; (4) GF(28)中代数表示的复杂性;
(5) 描述的简单性。
满足前3条准则的S盒的构造方法已被给出,AES的作者从众多候选构造中选择将x映射到它的逆的S盒。该映射过于简单,为了抵抗插入攻击,加入仿射变换:
b(x)(x7x6x2x)a(x)(x7x6x5x41)modx81
模数多项式x81选择为可能是最简单的模数多项式。可以找到其它的S盒满足以上准则。
MixColumn变换符合以下准则: (1) 可逆性;
(2) GF(28)中的线性性; (3) 适当的扩散性能; (4) 8位处理器上实现速度快; (5) 对称性; (6) 描述的简单性。
选择模数多项式x41可满足准则2、5、6。准则1、3、4要求系数的值要小,故选00、01、02 、 03。 ByteRotation符合以下准则: (1) 4个位移量互不相同且C00; (2) 能抵抗差分截断攻击; (3) 能抗Square攻击; (4) 简单。
从满足准则2和准则3出发,AES的作者选取了最简单的组合。
6.AES算法的优化
为了改善AES算法的时间性能以及提高数据吞吐量,将AES一128按列优先的原则进行排列。若输入的128位数据(16Byte)So,S1…,,按列优先的原则排列成4x4矩阵。
字节替换,采用s盒查找表实现(加密时,采用s盒;解密时,采用逆s盒),每个查找表的大小为256Byte,共占用512Byte。行移位是按行进行移位,第1行保持不变。加密时,第2行~第4行分别循环左移1Byte~3Byte;解密时,第2行一第4行分别循环右移
1Byte-3Byte。
假设行移位前的状态矩阵和行移位后的状态矩阵分别为:s和t,矩阵的每一列分别用s0、s1、s2、s3、to、t1、t2、t3表示,则加密时行移位可用如下方法实现:
to=(so&0xff000000)|(s1&0x00ff0000)|(s2&0x0000ff00)|(s3&0x000000ff); tl=(sl&0xff0000000)|(s2&0x00ff0000)|(s3&0x0000ff00)|(so&0x000000ff); t2=(s2&0xff000000)|(s3&0x00ff0000)|(so&0x0000ff00)|(sl&0x000000f0; t3=(s3&0xff000000)|(so&0X00ff0000)|(sl&0X0000ff00)|(s2&&0x000000ff); 解密时行移位可用如下方法实现 :
to=(so&0xff000000)|(s3&0x00ff0000)|(s2&0x0000ff00)|(s1&0x000000ff); tl=(sl&0xff0000000)|(s0&0x00ff0000)|(s3&0x0000ff00)|(s2&0x000000ff); t2=(s2&0xff000000)|(s1&0x00ff0000)|(so&0x0000ff00)|(s3&0x000000f0; t3=(s3&0xff000000)|(s2&0X00ff0000)|(sl&0X0000ff00)|(s0&&0x000000ff);
6.1 列混合和逆列混合的优化
7. AES算法的框架描述
Rijndael算法是一个可变数据块长和可变密钥长的分组迭代加密算法,数据块长和密钥长可分别为128,192或256比特,但为了满足AES的要求,分组长度为128比特,密钥长度为128,192或256比特。AES密码算法采用的是代替一置换网络(SPN)结构,每一轮操作由4层组成:第1层(字节替换)为非线性层,用S盒对每一轮中的单个字节分别进行替换;第2层(行移位)和第3层(列混合)是线性混合层,对当前的状态阵按行移位,按列混合;第4层(密钥加层)用子密钥与当前状态阵进行字节上的异或。
具体算法结构如图1所示。
X(*) 明文X 字节代替BS 子密钥K0 行移位SR 列混合MC r轮迭代 K1 密文Y Xr (a)AES算法框图 (b)一轮AES结
图1 AES算法结构
图1中,(a)图给出了算法的整体结构,输入明文x与子密钥I(0异或,然后经过r轮迭代最终生成密文Y,其中第1到r一1轮迭代结构为图(b),第r轮与前面各轮稍微有点不同,缺少混合层。
8. AES加、解密的输入/输出
Rijndael的输入/输出可看作8位字节的一维数组。对加密来说,其输入是一个明文分组和一个密钥,输出是一个密文分组。对解密而言,输入是一个密文分组和一个密钥,而输出是一个明文分组。Rijndael的轮变换及其每一步均作用在中间结果上,我们将该中间结果称为状态。状态可以形象地表示为一个矩形的字节数组,该数组共有4行。状态中的列数记为Nb,它等于分组长度除以32.将明文分组记为
P0P1P2P3P4Nb1
其中,P0表示第一个字节, 地,将密文分组记为
P4Nb1表示明文分组的最后一个字节。类似
C0C1C2C3C4Nb1
将状态记为
ai,j,0i4,0jNb
这里,ai,j表示位于第i行第i列的字节。输入字节依次映射到状态字节
a0,0a1,0a2,0a3,0a0,1a1,1a2,1a3,1,上。
当加密是,输入是一个明文分组,映射是
ai,jPi4j,0i4,0jNb
当解密是,输入是一个密文分组,映射是
ai,jCi4j,0i4,0jNb
在加密结束时,密文分组以相同的顺序从状态字节中取出
Ciaimod4,i/4,0i4Nb
在解密结束时,明文分组按以下顺序从状态中得到
Piaimod4,i/4,0i4Nb
类似地,密钥被映射到两维密码密钥上。密码密钥可以形象地表示为一个与状态类似的矩形数组,该数组也有4行。密码密钥的列数记为Nk,它等于密钥长度除以32。密钥的各字节被依次映射到密码密钥的各字节上:
k0,0k1,0k2,0k3,0k0,1k1,1k2,1k3,1k0,2,。如果将密钥记为
z0z1z2z3z4Nk1
那么
ki,jzi4j,0i4,0jNk
状态与密码密钥的表示以及明文-状态与密钥-密码密钥的映射,如图所示
P0 P4 P8 P12 P1 P5 P9 P13 k0 k4k8 k12 k16 k20 P2 P6 P10 P14 k1 k5 k9 P11 P15 k2 k13 k17 k21 P3 P7
k6 k10 k14 k18 k22 当Nb=4、Nk=6时状态和密码密钥的大
k3 k7 k11 k15 k19 k23 致分布
9. AES加密算法实现
AES中的操作均是以字节作为基础的,用到的变量也都是以字节为基础。State可以用4×4的矩阵表示。AES算法结构对加密和解密的操作,算法由轮密钥开始,并用Nr表示对一个数据分组加密的轮数(加密轮数与密钥长度的关系如表2所示)。AES算法的主循环State矩阵执行Nr1轮迭代运算,每轮都包括所有 4个阶段的代换,分别是在规范中被称为 SubBytes(字节替换)、ShiftRows(行位移变换)、MixColumns(列混合变换) 和AddRoundKey,(由于外部输入的加密密钥K长度有限 ,所以在算法中要用一个密钥扩展程序(Keyexpansion)把外部密钥 K 扩展成更长的比特串,以生成各轮的加密和解密密钥。)最后执行只包括 3个阶段 (省略 MixColumns变换)的最后一轮运算。
表2 AES参数
密钥长度(bits) 明文分组长度(bits) 轮数 每轮密钥长度(bits) 扩展密钥长度(bytes)
128 128 10 128 176 192 128 12 128 206 256 128 14 128 240 9.1 密钥扩展
通过生成器产生Nr+1个轮密钥,每个轮密钥由Nb个字组成,共有Nb(Nr+1)个字。在加密过程中,需要Nr+1个轮密钥,需要构造4(Nr+1)个32位字。首先将输入的4个字节直接复制到扩展密钥数组的前4个字中,得到W[0],W[1],W[2],W[3];然后每次用4个字填充扩展密钥数余下的部分。 //keyexpand
printf(\"after keyexpand:\\n\"); for(i=4;i<8;i++) { if(i%4==0) { rotword[0]=w[1][i-1]; rotword[1]=w[2][i-1]; rotword[2]=w[3][i-1]; rotword[3]=w[0][i-1]; printf(\"rotword():\");
for(j=0;j<4;j++) printf(\"%02x \
for(j=0;j<4;j++) subword[j]=sbox[rotword[j]]; printf(\"\\nsubword():\"); for(j=0;j<4;j++) printf(\"%02x \ printf(\"\\n\\n\");
for(j=0;j<4;j++) rcon[j]=subword[j]^ Rcon[N][j] ; printf(\"after ^Rcon():\"); for(j=0;j<4;j++) printf(\"%02x \ printf(\"\\n\\n\");
for(j=0;j<4;j++) w[j][i%4]=rcon[j]^ w[j][i-4] ; printf(\"w[%d] :\ for(j=0;j<4;j++) printf(\" %02x \ count++; } else { for(j=0;j<4;j++) w[j][i%4]=w[j][i%4]^w[j][(i%4)-1]; printf(\"w[%d] :\ for(j=0;j<4;j++) printf(\" %02x \ count++; }
printf(\"\\n\\n\"); }
printf(\"密钥扩展 Round key:\\n\"); for(i=0;i<4;i++) {for(j=0;j<4;j++) printf(\"\\%02x \ printf(\"\\n\");} printf(\"\\n\");
9.2 字节替换
SubBytes()变换是一个基于S盒的非线性置换,它用于将输入或中间态的每一个字节通过一个简单的查表操作,将其映射为另一个字节。映射方法是把输入字节的高四位作为S盒的行值,低四位作为列值,然后取出S盒中对应的行和列的元素作为输出。 unsigned char subbytes(unsigned char state[4][4])
{printf(\"after subbyte:\\n\"); //取出中间态state映射到S盒中的值赋给中间态state for(i=0;i<4;i++) {for(j=0;j<4;j++) state[i][j]=sbox[state[i][j]]; }
for(i=0;i<4;i++) //输出到屏幕显示state {for(j=0;j<4;j++) printf(\"\\%02x \ printf(\"\\n\"); }
printf(\"\\n\"); return 0; }
9.3 行移位
ShiftRows()完成基于行的循环移位操作,变换方法是第0行不动,第一行循环左移一个字节,第二位循环左移两个字节,第三行循环左移三个字节。 unsigned char shiftrows(unsigned char state[4][4])
{printf(\"after shiftrows:\\n\"); // 在中间态的行上, k=state[1][0]; // 第0行不变
state[1][0]=state[1][1]; // 第一行循环左移一个字节 state[1][1]=state[1][2]; // 第二行循环左移两个字节 state[1][2]=state[1][3]; // 第三行循环左移三个字节 state[1][3]=k;
k=state[2][0];
state[2][0]=state[2][2]; state[2][2]=k;
k=state[2][1];
state[2][1]=state[2][3]; state[2][3]=k;
k=state[3][0];
state[3][0]=state[3][3]; state[3][3]=state[3][2]; state[3][2]=state[3][1]; state[3][1]=k;
for(i=0;i<4;i++) //输出到屏幕显示state {for(j=0;j<4;j++) printf(\"\\%02x \ printf(\"\\n\"); }
printf(\"\\n\"); return 0; }
9.4 列混合
MixColumns()实现逐列混合,方法是s’(x)=c(x)*s(x)mod(x^4+1) unsigned char mixcolumns(unsigned char state[4][4])
{ printf(\"after mixcolumns:\\n\");// 实现 (02 03 01 01) 与中间态state分别相乘后异或得相应值
for(i=0;i<4;i++) // (01 02 03 01) { // (01 01 02 03) k=state[0][i]; // (03 01 01 02)
temp[0] = state[0][i] ^ state[1][i] ^ state[2][i] ^ state[3][i] ;
temp[1] = state[0][i] ^ state[1][i] ; temp[1] = xtime(temp[1]); state[0][i] ^= temp[1] ^ temp[0] ;
temp[1] = state[1][i] ^ state[2][i] ; temp[1] = xtime(temp[1]); state[1][i] ^= temp[1] ^ temp[0] ;
temp[1] = state[2][i] ^ state[3][i] ; temp[1] = xtime(temp[1]); state[2][i] ^= temp[1] ^ temp[0] ;
temp[1] = state[3][i] ^ k ; temp[1] = xtime(temp[1]); state[3][i] ^= temp[1] ^ temp[0] ;
}
for(i=0;i<4;i++) //输出到屏幕显示state {for(j=0;j<4;j++) printf(\"\\%02x \ printf(\"\\n\"); }
printf(\"\\n\"); return 0; }
9.5 轮密钥加
AddRoundKey()用于将输入或中间态S的每一列与一个密钥字ki进行按位异或,每一个轮密钥由Nb个字组成。
unsigned char addroundkey(unsigned char state[4][4],unsigned char w[4][4]) { printf(\"addroundkey %d:\\n\
//将中间态state中的每一列与一个密钥字(w[4][4]中的一列)进行按位异或 for(i=0;i<4;i++) //完了又赋值给state {for(j=0;j<4;j++) state[i][j]^=w[i][j];} for(i=0;i<4;i++) //输出到屏幕显示出来state {for(j=0;j<4;j++) printf(\"\\%02x \ printf(\"\\n\");} printf(\"\\n\"); return 0; }
9.6 逆字节替换
与字节代替类似,逆字节代替基于逆S盒实现。 unsigned char InvSubbytes(unsigned char state[4][4])
{ for(i=0;i<4;i++) //基于逆S盒的映射替代 {for(j=0;j<4;j++)
{ state[i][j] = rsbox[state[i][j]];} } printf(\"after InvSubbyte:\\n\"); for(i=0;i<4;i++) {for(j=0;j<4;j++) //输出到屏幕显示state printf(\"\\%02x \ printf(\"\\n\"); } printf(\"\\n\"); return 0; }
9.7 逆列混合
逆列混淆的处理办法与MixColumns()类似,每一列都通过与一个固定的多项式d(x)相乘进行交换。
unsigned char InvMixColumns(unsigned char state[4][4]) { printf(\"after InvMixColumns :\\n\");
//实现(0e 0b 0d 09)与中间态state分别相乘后异或得相应值
for(i=0;i<4;i++) // (09 0e 0b 0d) { temp[0] = state[0][i]; // (0d 09 0e 0b) temp[1] = state[1][i]; // (0b 0d 09 0e) temp[2] = state[2][i]; temp[3] = state[3][i];
state[0][i] = Multiply(temp[0], 0x0e) ^ Multiply(temp[1], 0x0b) ^ Multiply(temp[2], 0x0d) ^ Multiply(temp[3], 0x09);
state[1][i] = Multiply(temp[0], 0x09) ^ Multiply(temp[1], 0x0e) ^ Multiply(temp[2], 0x0b) ^ Multiply(temp[3], 0x0d);
state[2][i] = Multiply(temp[0], 0x0d) ^ Multiply(temp[1], 0x09) ^ Multiply(temp[2], 0x0e) ^ Multiply(temp[3], 0x0b);
state[3][i] = Multiply(temp[0], 0x0b) ^ Multiply(temp[1], 0x0d) ^ Multiply(temp[2], 0x09) ^ Multiply(temp[3], 0x0e); }
for(i=0;i<4;i++) //输出到屏幕显示state {for(j=0;j<4;j++)
printf(\"\\%02x \printf(\"\\n\");} printf(\"\\n\"); return 0; }
9.8 加密
加密部分我分了两种情况,一种是自动检查加密程序的正确性,之前在程序里给明文和密钥赋上初值,运行程序检验结果是否正确;另一种是用户手动输入32位的十六进制数,进行加密,我是把每一具体项模块化,将功能在每个具体模块中实现,只需要直接调用,视觉效果强,一目了然。
下面是实现加密功能一些关键代码
void AES_encrypt(unsigned char State[][N], unsigned char RoundKey[][N])
{message[16]={0x32,0x43,0xf6,0xa8,0x88,0x5a,0x30,0x8d,0x31,0x31,0x98,0xa2,0xe0,0x37,0x07,0x34};
key[16]={0x2b,0x7e,0x15,0x16,0x28,0xae,0xd2,0xa6,0xab,0xf7,0x15,0x88,0x09,0xcf,0x4f,0x3c};
for(i=0;i<4;i++){ for(j=0;j<4;j++) // 分别获取明文和密钥 {state[j][i]=message[m];w[j][i]=key[m];m++;} } . addroundkey(state,w); for(round=2;round<11;round++) { printf(\"第 %d 轮加密 : \\n\subbytes(state); shiftrows(state); mixcolumns(state); keyexpand(w, round); addroundkey(state,w); }
subbytes(state); //最后一轮 shiftrows(state); keyexpand(w, 10); addroundkey(state,w); }
9.9 解密
AES解密我也是分成了两个部分,第一部分是在程序中对密文和密钥赋初
值,通过与标准对照检查解密过程的正确性;第二部分是用户手动输入密文和密钥,程序对其进行解密,得到最后的明文。
解密过程基本如下:
1)获取输入的明文和密钥 2)通过密钥扩展过程获取各轮密钥 3)轮密钥加变换过程 4)逆行移位 5)逆字节替代 6)轮密钥加变换 7)逆列混淆
4—7步共9次循环,最后一轮实现4—6步,完成解密过程。 主要代码如下:
void AES_decrypt(unsigned char State[][N], unsigned char w[][N])
{key[16]={0x2b,0x7e,0x15,0x16,0x28,0xae,0xd2,0xa6,0xab,0xf7,0x15,0x88,0x09,0xcf,0x4f,0x3c};
cipher[16]={0x39,0x25,0x84,0x1d,0x02,0xdc,0x09,0xfb,0xdc,0x11,0x85,0x97,0x19,0x6a,0x0b,0x32};
printf(\"%02x \ /获取密文和密钥 for(i=0;i<4;i++) { for(j=0;j<4;j++) {state[j][i]=cipher[m];w[j][i]=key[m];m++;} } Keyexpand(w,round ); //获得密钥扩展列表 AddRoundKey(State, w); //首轮 for (i = 9; i > 0; i --) //1-9轮 { InvShiftRows(state);
InvSubbytes(state); Keyexpand(w,round ); AddRoundKey(State, w); InvMixColumns(State); } InvShiftRows(State); //最后一轮 InvSubBytes(State); Keyexpand(w,0 ); AddRoundKey(State, w);
第三章 A E S算法的安全性
对于Rijndael算法的安全性讨论,通过对以下已知的攻击方法来进行分析,
这些攻击有:
3.1 穷举攻击法
Rijndael算法中最短的密钥长度是128比特,如果用穷举法则需要2128次,
计算量是非常大的,故使用目前技术的穷举法是无效的。
3.2 差分攻击法
这种攻击法是利用大量已知的明文/密文对之间的差异来推测出密钥。对于
Rijndael算法,当轮数超过三轮,若存在1/2(n位分组块的)长度可预测性的差异,这种攻击法就可以推测出密钥的位元值,在Rijndael算法中已经证明Rijndael经过四轮运算后,存在不超过2比例的可预测性差异,五轮运算后不超过2。。比例的可预测差异,因此可以说这种攻击法对Rijndael算法是无效的。
3.3 线性攻击法
这种攻击法利用大量收集到的明文/密文对,根据其中可预测的相对关系推导出一个代数展开式,只要能找出相对关系数超过2的线性轨迹,就可以找出密钥值。Rijndael算法已经被证明执行四轮运算后不存在相关系数大于2的线性轨迹;在执行八轮后,其相关系数大于2的相关系数也不存在,因此可以说这种攻击法对Rijndael算法是无效的。
3.4 平方攻击法
这种攻击是一种明文攻击,攻击强度不依赖于s盒、列混合矩阵和密钥扩散
准则的选取,但至今为止这种攻击法只能够对经过不超过六次轮运算的Rijndael算法有效,计算量为2∞+,因此可以说这种攻击法对Rijndael算法是无效的。
3.5 内插攻击法
这种攻击法是攻击者利用加密的输人与输出配对,建立一些多项式。如果加
密的元件有一个乘法的代数展开式,并且与管理的复杂度结合在一起时,这种攻击便是可行的。攻击的方式是如果攻击者建立的代数展开式的阶度很小,只需要一些加密法的输入和输出配对就可以得到代数展开式的各项系数。但是,Rijndael算法中的Fs域,它的展开式为:
63+8FX27+B5X9+0lX223+F4X23+25X~7+Fgx+09X瑚+05X,是非常复杂的,因此可以说这种攻击法对Rijndael算法是无效的。
从以上分析可以看出,Rijndael算法对已知的攻击具有较好的免疫性,安全性比较高。
3.6 AES算法抵抗XSL攻击能力分析
最近又出现了一种代数计算攻击。它是NicolasCourtois和Josef Pieprayk提出的。他们在近期的一篇论文中指出:Rijndael可以被重新定义为冗余二次方程组。例如:对于128位的Rijndael,要想从单一明文中恢复密钥,可以将问题转换为含有8000个二次方程组,其中有1600个未知数的代数问题。因此,Rijndael算法的安全性就依赖于没有有效的方法解决上述方程组。然而,Shamir等人在Euroerypt2000中发表了XL(OR FXL)算法,声称可以在亚指数时间(subexponentiN time)解决上述问题。这表明类似于Rijndael的加密算法的安全性并不是随着加密的轮数而指数增加的。
在实际中,XL算法没有成功地攻击过Rijndael算法。但是,依照Rijndael建立的系统并不是随机的,它有许多特征:可重新定义、稀疏性、结构化。因此,在Nicolas Courtois和Josef Pieprayk的最新论文中研究了如何提高XL算法,使之适应于一些特殊的系统。该文中设计了一种新型的攻击,称之为XSL攻击。这种算法是启发式的,并且很难估计它的复杂度。理论上,XSL攻击可用于任何分组加密方法,但在对付A Es上没有更多的优势。
在AES(Rijndae1)算法中存在大量的对称性,而假如密码性能中也存在大量对称性的话那是很利于密码分析的,所以该算法采取了适当的措施来消除密码性能中的对称性,具体的方法是通过在每一轮中采用不同的轮常数来实现。密码自身及其逆密码使用了不同的变换,这样的举措实际上消除了D.Davies描述的DES中存在的弱密钥和半弱密钥存在的可能性。同时,密钥扩展的非线性实际上消除了等价密钥存在的可能性。当密码严重地依赖于密钥来提供非线性时,象I—DEA中的那些弱密钥就会出现。mjndael算法采用的是一种密钥迭代型密钥,所有的非线性都是由一个与密钥独立的s一盒来提供,因此也就不存在这种类型的弱密钥。
第四章 AES的软件实现
1 软件系统概述
AES不但具有良好的安全性,但而且适合在多种处理器办软件编程上方便快捷的实现。本文是基于32位操作系统下,用Visual C++ 软件开放了一个界面友好的MFC平台。
结论
本程序是处理的AES分组大小和密钥长度都为128位,迭代轮数为10轮。由于我能力有限,程序还有很多不足之处,比如不能自动填充缺失位等,只能说是完成了AES的基本功能,我也希望能将它的功能变得更强大,但多次修改后均没有成功。
通过多次调试,对SubBytes,ShiftRows,MixColumns,AddRoundKey等加密过程,InvMixColumns,InvShiftRows,InvSubBytes等解密过程的编程运行过程有了清晰的认识,深入理解了AES的加密和解密过程,对算法、密码保密性和安全性有了新的认识,收获很多。
AES的研究从理论到应用,己经深人到了信息安全技术的各个领域,深入研究与开发
新的AES实现和应用具有重要的理论和实践意义。随着密码技术的高速发展,高级加密标准AES(Rijndae1)算法将逐渐取代DES在IPSec、SSL和ATM中的使用,并广泛应用于虚拟专用网、远程访问服务器(RAS)、SONET(同步光网络)、高速ATM/Ethernet路由器、卫星通信、移动通信、电子金融业务等领域。此外,网络保密系统、财政保密、电子游戏保密等方面也将采用AES加密算法,将现有的关于AES研究成果与其他领域的相关技术与应用相结合,从应用的角度拓展数据加密技术,从而获得新的应用,是AES(R~ndea1)的发展方向。
小组分工
成员心得
参 考 文 献
[1][期刊论文] 张金辉, 郭晓彪, 符鑫, ZHANG Jin-hui, GUO Xiao-biao, FU Xin - 《信息网络安全》2011年5期 [2]王红珍,张根耀, 李竹林, Information Technology, 《信息技术 》2011年 09期
[3][学位论文] 李刚, 2006 - 东北大学:控制理论与控制工程
[4][期刊论文] 吴小博, WU Xiao-bo - 《计算机安全》2007年12期
[5]Courtois N T,Pieprayk J.Cryptanalysis of Block ciphers with overdefined Systems of Equations[A]·AsisCrypt 2002[C].Berlin:Sprnger-Verlag,20002.267-287.
[6]Knudsen L R,Wagner D·Integral cryptanalysis(extended abatract)·In:Proceedings of Fast Software Encryption-FSE’02,Leuven,Belgium,February,2002
附录
因篇幅问题不能全部显示,请点此查看更多更全内容