AES加密、解密算法原理(4100字)

来源:m.fanwen118.com时间:2021.5.2

AES加密、解密算法原理和AVR实现

摘要 AES是美国高级加密标准算法,将在未来几十年里代替DES在各个领域中得到广泛应用。本文在研究分析AES加密算法原理的基础上,着重说明算法的实现步骤,并结合AVR汇编语言完整地实现AES加密和解密。根据AES原理,提出几种列变化的优化算法,并根据实验结果分析和比较它们的优缺点。

关键词 AES算法 DES AVR汇编语言 加密算法 解密算法

引言

随着对称密码的发展,DES数据加密标准算法由于密钥长度较小(56位),已经不适应当今分布式开放网络对数据加密安全性的要求,因此19xx年NIST公开征集新的数据加密标准,即AES[1]。经过三轮的筛选,比利时Joan Daeman和Vincent Rijmen提交的Rijndael算法被提议为AES的最终算法。此算法将成为美国新的数据加密标准而被广泛应用在各个领域中。尽管人们对AES还有不同的看法,但总体来说,AES作为新一代的数据加密标准汇聚了强安全性、高性能、高效率、易用和灵活等优点。AES设计有三个密钥长度:128,192,256位,相对而言,AES的128密钥比DES的56密钥强1021倍[2]。AES算法主要包括三个方面:轮变化、圈数和密钥扩展。本文以128为例,介绍算法的基本原理;结合AVR汇编语言,实现高级数据加密算法AES。

1 AES加密、解密算法原理和AVR实现

AES是分组密钥,算法输入128位数据,密钥长度也是128位。用Nr表示对一个数据分组加密的轮数(加密轮数与密钥长度的关系如表1所列)。每一轮都需要一个与输入分组具有相同长度的扩展密钥Expandedkey(i)的参与。由于外部输入的加密密钥K长度有限,所以在算法中要用一个密钥扩展程序(Keyexpansion)把外部密钥K扩展成更长的比特串,以生成各轮的加密和解密密钥。

1.1 圈变化

AES每一个圈变换由以下三个层组成:

非线性层——进行Subbyte变换;

线行混合层——进行ShiftRow和MixColumn运算;

密钥加层——进行AddRoundKey运算。

① Subbyte变换是作用在状态中每个字节上的一种非线性字节转换,可以通过计算出来的S盒进行映射。

Schange:

ldi zh,$01;将指针指向S盒的首地址

mov zl,r2;将要查找的数据作为指针低地址

ldtemp,z+;取出这个对应的数据

mov r2,temp;交换数据完成查表

?

ret

② ShiftRow是一个字节换位。它将状态中的行按照不同的偏移量进行循环移位,而这个偏移量也是根据Nb的不同而选择的[3]。

shiftrow:;这是一个字节换位的子程序

mov temp,r3;因为是4×4

mov r3,r7; r2 r6 r10 r14 r2 r6 r10 r14

mov r7,r11; r3 r7 r11 r15---r7 r11 r15 r3

mov r11,r15; r4 r8 r12 r17 r12 r17 r4 r8

mov r15,temp; r5 r9 r13 r18 r18 r5 r9 r13

mov temp,r4

mov temp1,r8

mov r4,r12

mov r8,r17

mov r12,temp

mov r17,temp1

mov temp,r18

mov r18,r13

mov r13,r9

mov r9,r5

mov r5,temp

ret

③ 在MixColumn变换中,把状态中的每一列看作GF(28)上的多项式a(x)与固定多项式c(x)相乘的结果。b(x)=c(x)*a(x)的系数这样计算:*运算不是普通的乘法运算,而是特殊的运算,即

b(x)=c(x)?a(x)(mod x4+1)

对于这个运算

b0=02。a0+03。a1+a2+a3

令xtime(a0)=02。a0

其中,符号“。”表示模一个八次不可约多项式的同余乘法[3]。

mov temp,a0;这是一个mixcolimn子程序

rcall xtime;调用xtime程序

mov a0,temp

mov temp,a1

rcall xtime

eor a0,a1

eor a0,temp

eor a0,a2

eor a0,a3;完成b(x)的计算

?

xtime:;这是一个子程序

ldi temp1,$1b

lsl temp

brcs next1;如果最高位是1,则转移

next: ret;否则什么也不变化

next1:eor temp,temp1

rjmp next

对于逆变化,其矩阵C要改变成相应的D,即b(x)=d(x)*a(x)。

④ 密钥加层运算(addround)是将圈密钥状态中的对应字节按位“异或”。

⑤ 根据线性变化的性质[1],解密运算是加密变化的逆变化。这里不再详细叙述。

1.2 轮变化

对不同的分组长度,其对应的轮变化次数是不同的,如表1所列。

表1 AES类型与基参数的关系

1.3 密钥扩展

AES算法利用外部输入密钥K(密钥串的字数为Nk),通过密钥的扩展程序得到共计4(Nr+1)字的扩展密钥。它涉及如下三个模块:

① 位置变换(rotword)——把一个4字节的序列[A,B,C,D]变化成[B,C,D,A]; ② S盒变换(subword)——对一个4字节进行S盒代替;

③ 变换Rcon[i]——Rcon[i]表示32位比特字[xi-1,00,00,00]。这里的x是(02),如

Rcon[1]=[01000000];Rcon[2]=[02000000];Rcon[3]=[04000000]??

扩展密钥的生成:扩展密钥的前Nk个字就是外部密钥K;以后的字W[[i]]等于它前一个字W[[i-1]]与前第Nk个字W[[i-Nk]]的“异或”,即W[[i]]=W[[i-1]] W[[i- Nk]]。但是若i为Nk的倍数,则W[i]=W[i-Nk] Subword(Rotword(W[[i-1]])) Rcon[i/Nk]。 程序执行的时候,主要调用以上几个子程序,具体实现如下:

Keyexpansion:

rcall rotwoed

rcall subword

rcall Rcon

?

AES的加密与解密流程如图1所示。

图1 AES的加密和解密流程

2 AES加密、解密算法的优化

由以上算法的流程中可以清楚地看到,整个算法中程序耗时最多的就是圈变化部分,因此对于算法的优化也就在此;而圈变化部分可以优化的也就是列变化。因为列变化是一个模乘同余规则。由于AES加密和解密是不对称的,如果不对其进行优化,会使算法的解密速度远远大于加密的速度[1]。

① 加密运算。对列变换(Mixcolumn)可以通过调用xtime子程序进行优化。具体算法[1]实现如下:

另一种有效的优化方法就是离线构造一个表格,即列变化表格。这样只要通过查表的方式就可以提高加密速度。

② 解密算法的优化。由于解密的列变换的系数分别是09、0E、0B和0D。在AVR单片机上实现以上的乘法显然是需要很多的时间,从而导致了解密的性能降低。

优化方法一:对列变化进行分解使倍乘次数降低。

仔细研究解密矩阵的系数,不难发现解密矩阵和加密矩阵有着一定的联系,即解密矩阵等于加密矩阵和一个矩阵的相乘。通过这样的联系,就可以对算法进行优化:

这样一来,只用几个简单的“异或”就可以实现列变化,使倍乘的次数降低,提高解密的速度。

优化方法二:构造表格。

同加密构造方法一样,可以构造四个表格T[ea]=e×a; T[9a]=9×a;T[9a]=9×a;T[ba]=b×a。这样一来,也只需要进行查表和简单的异或就可以完成解密的任务。虽然这种方法将增加额外的开销,但是它却是一种有效的方法。

3 AES加密与解密的实验仿真

根据以上实验步骤和优化方法得出表2、3所列实验结果。

表2 AES-128不同加密方法性能比较

设主密钥为:000102030405060708090a0b0c0d0e0f(128bit)。

加密明文:00112233445566778899AABBCCDDEEFF。

密文:69C4E0D86A7B0430D8CDB78070B4C55A。

解密密文:69C4E0D86A7B0430D8CDB78070B4C55A。

明文:00112233445566778899AABBCCDDEEFF。

总之,AES密码是一个非对称密码体制,它的解密要比加密复杂和费时。解密优化算法没有增加存储空间的基础上,以列变化为基础进行处理,程序比原始的要小,而且节约了时间。解密优化方法速度最快,效率最高,但要增加系统的存储空间,因此它的程序也是最大的一个。

注:AES-128数据加密解密程序见本刊网站(.cn)。

结语

AES高级数据加密算法不管是从安全性、效率,还是密钥的灵活性等方面都优于DES数据加密算法,在今后将逐步代替DES而被广泛应用。本文基于AVR的高速计算性能实现了AES算法,并结合汇编语言进行了算法的优化。根据实际应用的具体需要,可以选用相应的方法。

参考文献

1 宋震,等. 密码学. 北京:中国水利水电出版社,2002

2 杨义先.现代密码新理论.北京:科学出版社,2002

3 谷大武,等.高级加密标准(AES)算法—Rijndael的设计.北京:清华大学出版社,2003 4 耿德根,等.AVR单片机应用技术.北京:北京航空航天大学出版社,2002

5 宋建国,等.AVR高速嵌入式单片机原理与应用.北京:北京航空航天大学出版社,2001 6 NIST. Advanced Encryption Standard (AES) .Federal Information Processing Standards Publication,2001


第二篇:编程实现AES算法的加密解密过程 20600字

信息安全工程课程

实验报告

编程实现AES算法的加密解密过程

课程名称:信息安全工程

学生姓名:

学生学号:

专业班级:

任课教师:蔡忠闽

目录

1 背景与意义 ................................................................................................................................... 4

2 实验要求....................................................................................................................................... 4

3.系统设计....................................................................................................................................... 5

3.1系统主要目标 ..................................................................................................................... 5

3.2主要软件需求(运行环境) ............................................................................................. 5

4 AES算法加密和解密原理分析 .................................................................................................. 5

4.1加密过程基本变换 ............................................................................................................. 7

4.2解密过程基本变换 ............................................................................................................. 7

4.3密钥扩展算法 ..................................................................................................................... 8

5.系统功能程序设计 ....................................................................................................................... 8

6. 测试报告 ................................................................................................................................... 18

6.1 加密 ................................................................................................................................. 18

6.2 解密 ................................................................................................................................. 19

7 实验总结 ................................................................................................................................... 19

1 背景与意义

科技的发展使计算机深入到了我们生活的的方方面面,计算机在带来方便和提高了工作效率的同时却也带来了各种各样的新问题,其中信息安全问题最为突出,随着计算机信息安全要求的不断提高, 计算机保密系统已变得越来越重要,所以我们需要一种较为可靠的加密算法来保护我们信息的安全。

由于DES已经无法满足高保密性的要求,美国于19xx年1月开始征集新一代数据加密标准(即高级数据加密标准,Advanced Encryption Standard,AES)。20xx年10月2日,正式宣布选择比利时密码学家所开发的Rijndael算法成为AES的最终算法。

AES(The Advanced Encryption Standard)是美国国家标准与技术研究所用于加密电子数据的规范。它被预期能成为人们公认的加密包括金融、电信和政府数字信息的方法。AES 是一个新的可以用于保护电子数据的加密算法。明确地说,AES 是一个迭代的、对称密钥分组的密码,它可以使用128、192 和 256 位密钥,并且用 128 位(16字节)分组加密和解密数据。与公共密钥密码使用密钥对不同,对称密钥密码使用相同的密钥加密和解密数据。通过分组密码返回的加密数据的位数与输入 数据相同。迭代加密使用一个循环结构,在该循环中重复置换和替换输入数据。 该算法为比利时密码学家Joan Daemen和Vincent Rijmen所设计,结合两位作者的名字,以Rijndael之命名之,投稿高级加密标准的甄选流程。(Rijdael的发音近于 "Rhine doll"。)AES在软体及硬件上都能快速地加解密,相对来说较易于实作,且只需要很少的记忆体。作为一个新的加密标准,目前正被部署应用到更广大的范围.

2 实验要求

(1)一人一组

(2)AES算法加密和解密原理分析

(3)提交完整的源程序(使用网络上的现成程序一定要注明出处)

(4)提交程序的设计,说明文档

(5)用ECB和分组链模式CBC,对给定内容进行加密和解密,提交解密结果,并提交实验心得,着重阐述对实验的理解

(6)程序调试成功后,处理以下内容:

A、AES 加密

明文:各自的姓名+邮箱

秘钥:各自的手机号

B、AES解密

密文:邮箱附件给出

秘钥:(给出秘钥为ASCII码形式,请将ASCII码转为二进制,不满128位在其后补零):13072981063

3.系统设计

3.1系统主要目标

1.在深入理解AES加密/解密算法理论的基础上,设计一个AES加密/解密软件系统;

2.完成一个明文分组的加解密,明文和密钥是十六进制,输入明文和密钥,输出密文,进行加密后,能够进行正确的解密;

3. 按要求提供所设计系统的报告及完整的软件。

3.2主要软件需求(运行环境)

本软件适用VC语言编写,编译成功后的EXE文件可以在装有windows系统的任何计算机上使用。 测试平台:Windows 8

使用软件:Visual Studio 2012/C++

4 AES算法加密和解密原理分析

AES是一个迭代的、对称密钥分组的密码,它可以使用128、192和256位密钥长度,并且用128位分组长度加密和解密数据[2]。该算法输入分组、输出分组、状态长度均为128比特。

对于AES算法的运算是在一个称为状态的二维字节数组上进行。一个状态由四行组成,每一行包括Nb个字节,Nb等于分组长度除以32,AES分组长度为128位,因此,Nb=4,该值反应了状态中32-bit字的个数(列数);密钥长度128、192和256位可分别表示为Nk=4、6或8,反应了密钥中32-bit字的个数(列数)。而AES算法的轮数Nr仅依赖于密钥长度Nk,轮数和密钥长度的关系可以表示为:Nr=6+Nk。密钥长度—分组长度—轮数的关系如表1所示。

表1 Key-Block-Round关系

编程实现AES算法的加密解密过程

对于加密和解密变换,AES算法使用的轮函数由4个不同的以字节为基本单位的变换复合而成,该过程由四个不同的阶段组成[3]:

(1)S盒变换,用一个S盒完成分组中的按字节代替;(2)行移位变换,一个简单的置换;(3)列混淆变换,一个利用在域GF(28) 上的算术性的代替;(4)轮密钥加变换,一个利用当前分组和扩展密钥的一个部分进行按位异或。

AES对数据的加密过程是通过把输入的明文和密钥由轮函数经Nr轮迭代来实现的,结尾轮与前Nr-1轮不同。前Nr-1轮依次进行S盒变换、行移位变换、列混淆变换和轮密钥加变换;结尾轮与前Nr-1

轮相比去掉了列混淆变换。

而解密过程与加密过程相反,通过把输入的密文和密钥由轮函数经Nr轮迭代来实现的,结尾轮与前Nr-1轮不同。前Nr-1轮依次进行逆行移位变换、逆S盒变换、轮密钥加变换和逆列混淆变换;结尾轮与前Nr-1轮相比去掉了逆列混淆变换。

AES算法的加密解密过程如图1所示:

编程实现AES算法的加密解密过程

编程实现AES算法的加密解密过程

编程实现AES算法的加密解密过程

图1 AES加密解密流程

4.1加密过程基本变换

(1) S盒变换

S盒变换是一个基于S盒的非线性置换,它用于输入或中间态的每一个字节通过一个简单的查表操作,将其映射为另一个字节。映射方法是:把输入字节的高4位作为S盒的行值,低4位作为列值,然后取出S盒中对应行和列的元素作为输出。例如,输入为“89”(十六进制)的值所对应的S盒的行值为“8”,列值为“9”,S盒中相应位置的值为“a7”,就说明“89”被映射为“87”。

(2) 列混淆变换

列混淆变换实现逐列混淆,其方法是:

s'(x)?c(x)?s(x)mod(x4?1)

32c(x)?{03}?x?{01}?x?{01}?x?{02}内的数表示是字节。 其中,

用矩阵表示为

'?s0,??02c?'???s1,c???01

'??s2,?01c?'???s3,c???03?030101??s0,c??s?020301???1,c? 010203??s2,c????010102??s3,c?

(3) 行移位变换

行移位变换完成基于行的循环移位操作,即行移位变换的作用在中间态的行上,第0行不动,第1行循环左移1个字节,第2行循环左移2个字节,第3行循环左移3个字节。

(4) 轮密钥加变换

轮密钥加变换用于将输入或中间态S的每一列与一个密钥字W[i]进行按位异或,其中, W[i](i?0,1,???,4(Nr?1)?1)由原始密钥通过密钥扩展算法产生。

4.2解密过程基本变换

解密过程是加密的逆过程,S盒变换、行移位变换、列混淆变换都要进行求逆变换,即逆S盒变换、逆行移位变换、逆列混淆变换。而轮密钥加变换与加密过程相同。

(1) 逆S盒变换

与S盒变换类似,逆S盒变换是基于逆S盒实现的。

(2) 逆行移位变换

与行移位变换相反,逆行移位变换将态State的后三行按相反的方向进行移位操作,即第0行保持不变,第1行向右移1个字节,第2行向右移2个字节,第3行向右移3个字节。

(3) 逆列混淆变换

逆列混淆变换的处理方法与列混淆变换类似,每一列都通过与一个固定的多项相乘进行变换。 写为矩阵乘法的形式,逆列混淆变换按以下方式对列进行变换:

'?s0,??0E0B0D09??s0,c?c?'????s?s090E0B0D?1,c?????1,c? '??s2,?0D090E0B??s2,c?c?'?????s0B0D090E???s3,c??3,c???

4.3密钥扩展算法

AES加密解密过程中,每一轮都需要一个与输入分组具有相同长度的扩展密钥W[i]的参与。由于外部输入的加密密钥长度有限,所以在算法中要用一个密钥扩展程序把外部密钥扩展成更长的比特串,以生成各轮的加密和解密密钥。

通过生成器产生Nr+1轮轮密钥,每个轮密钥由Nb个字组成,共有Nb(Nr+1)个字W[i],i=0,1,??,Nb(Nr+1)-1。

5.系统功能程序设计

(代码参考自CSDN论坛)

#include "StdAfx.h"

#include "(AES加解密).h"

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

byte in[4][Nb]; //in数组用于读入需要或解密的数据

byte key[4][Nk]; //key数组用于读入初始密钥

byte w[Nr+1][Nk][4]; //w数组用于保存所有扩展后的密钥

//S盒

byte S_box[256]=

{

0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,\ 0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,\ 0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,\ 0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,\ 0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,\ 0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,\ 0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,\ 0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,\ 0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,\ 0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,\ 0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,\ 0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,\ 0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,\ 0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,\ 0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,\ 0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16 };

//逆S盒

byte InvS_box[256] =

{0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38,0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb,\ 0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87,0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb,\ 0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d,0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e,\ 0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2,0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25,\ 0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16,0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92,\ 0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda,0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84,\ 0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a,0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06,\ 0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02,0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b,\ 0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea,0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73,\

0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85,0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e,\ 0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89,0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b,\ 0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20,0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4,\ 0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31,0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f,\ 0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d,0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef,\ 0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0,0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61,\ 0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26,0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d };

//表alog[256]是生成元表示到多项式的映射表。使用的生成元为x+1

byte alog[256] =

{0x01,0x03,0x05,0x0f,0x11,0x33,0x55,0xff,0x1a,0x2e,0x72,0x96,0xa1,0xf8,0x13,0x35,\ 0x5f,0xe1,0x38,0x48,0xd8,0x73,0x95,0xa4,0xf7,0x02,0x06,0x0a,0x1e,0x22,0x66,0xaa,\ 0xe5,0x34,0x5c,0xe4,0x37,0x59,0xeb,0x26,0x6a,0xbe,0xd9,0x70,0x90,0xab,0xe6,0x31,\ 0x53,0xf5,0x04,0x0c,0x14,0x3c,0x44,0xcc,0x4f,0xd1,0x68,0xb8,0xd3,0x6e,0xb2,0xcd,\ 0x4c,0xd4,0x67,0xa9,0xe0,0x3b,0x4d,0xd7,0x62,0xa6,0xf1,0x08,0x18,0x28,0x78,0x88,\ 0x83,0x9e,0xb9,0xd0,0x6b,0xbd,0xdc,0x7f,0x81,0x98,0xb3,0xce,0x49,0xdb,0x76,0x9a,\ 0xb5,0xc4,0x57,0xf9,0x10,0x30,0x50,0xf0,0x0b,0x1d,0x27,0x69,0xbb,0xd6,0x61,0xa3,\ 0xfe,0x19,0x2b,0x7d,0x87,0x92,0xad,0xec,0x2f,0x71,0x93,0xae,0xe9,0x20,0x60,0xa0,\ 0xfb,0x16,0x3a,0x4e,0xd2,0x6d,0xb7,0xc2,0x5d,0xe7,0x32,0x56,0xfa,0x15,0x3f,0x41,\ 0xc3,0x5e,0xe2,0x3d,0x47,0xc9,0x40,0xc0,0x5b,0xed,0x2c,0x74,0x9c,0xbf,0xda,0x75,\ 0x9f,0xba,0xd5,0x64,0xac,0xef,0x2a,0x7e,0x82,0x9d,0xbc,0xdf,0x7a,0x8e,0x89,0x80,\ 0x9b,0xb6,0xc1,0x58,0xe8,0x23,0x65,0xaf,0xea,0x25,0x6f,0xb1,0xc8,0x43,0xc5,0x54,\ 0xfc,0x1f,0x21,0x63,0xa5,0xf4,0x07,0x09,0x1b,0x2d,0x77,0x99,0xb0,0xcb,0x46,0xca,\ 0x45,0xcf,0x4a,0xde,0x79,0x8b,0x86,0x91,0xa8,0xe3,0x3e,0x42,0xc6,0x51,0xf3,0x0e,\ 0x12,0x36,0x5a,0xee,0x29,0x7b,0x8d,0x8c,0x8f,0x8a,0x85,0x94,0xa7,0xf2,0x0d,0x17,\ 0x39,0x4b,0xdd,0x7c,0x84,0x97,0xa2,0xfd,0x1c,0x24,0x6c,0xb4,0xc7,0x52,0xf6,0x01};

//log[256]是多项式表示到生成元的映射表。使用的生成元为x+1

byte log[256] =

{0x00,0x00,0x19,0x01,0x32,0x02,0x1a,0xc6,0x4b,0xc7,0x1b,0x68,0x33,0xee,0xdf,0x03,\ 0x64,0x04,0xe0,0x0e,0x34,0x8d,0x81,0xef,0x4c,0x71,0x08,0xc8,0xf8,0x69,0x1c,0xc1,\ 0x7d,0xc2,0x1d,0xb5,0xf9,0xb9,0x27,0x6a,0x4d,0xe4,0xa6,0x72,0x9a,0xc9,0x09,0x78,\ 0x65,0x2f,0x8a,0x05,0x21,0x0f,0xe1,0x24,0x12,0xf0,0x82,0x45,0x35,0x93,0xda,0x8e,\ 0x96,0x8f,0xdb,0xbd,0x36,0xd0,0xce,0x94,0x13,0x5c,0xd2,0xf1,0x40,0x46,0x83,0x38,\ 0x66,0xdd,0xfd,0x30,0xbf,0x06,0x8b,0x62,0xb3,0x25,0xe2,0x98,0x22,0x88,0x91,0x10,\ 0x7e,0x6e,0x48,0xc3,0xa3,0xb6,0x1e,0x42,0x3a,0x6b,0x28,0x54,0xfa,0x85,0x3d,0xba,\ 0x2b,0x79,0x0a,0x15,0x9b,0x9f,0x5e,0xca,0x4e,0xd4,0xac,0xe5,0xf3,0x73,0xa7,0x57,\ 0xaf,0x58,0xa8,0x50,0xf4,0xea,0xd6,0x74,0x4f,0xae,0xe9,0xd5,0xe7,0xe6,0xad,0xe8,\ 0x2c,0xd7,0x75,0x7a,0xeb,0x16,0x0b,0xf5,0x59,0xcb,0x5f,0xb0,0x9c,0xa9,0x51,0xa0,\ 0x7f,0x0c,0xf6,0x6f,0x17,0xc4,0x49,0xec,0xd8,0x43,0x1f,0x2d,0xa4,0x76,0x7b,0xb7,\ 0xcc,0xbb,0x3e,0x5a,0xfb,0x60,0xb1,0x86,0x3b,0x52,0xa1,0x6c,0xaa,0x55,0x29,0x9d,\ 0x97,0xb2,0x87,0x90,0x61,0xbe,0xdc,0xfc,0xbc,0x95,0xcf,0xcd,0x37,0x3f,0x5b,0xd1,\ 0x53,0x39,0x84,0x3c,0x41,0xa2,0x6d,0x47,0x14,0x2a,0x9e,0x5d,0x56,0xf2,0xd3,0xab,\ 0x44,0x11,0x92,0xd9,0x23,0x20,0x2e,0x89,0xb4,0x7c,0xb8,0x26,0x77,0x99,0xe3,0xa5,\ 0x67,0x4a,0xed,0xde,0xc5,0x31,0xfe,0x18,0x0d,0x63,0x8c,0x80,0xc0,0xf7,0x70,0x07}; //密钥扩展中使用的异或轮常数

byte Rcon[10][4]=

{

{0x01,0x00,0x00,0x00},{0x02,0x00,0x00,0x00},{0x04,0x00,0x00,0x00},

{0x08,0x00,0x00,0x00},{0x10,0x00,0x00,0x00},{0x20,0x00,0x00,0x00},

{0x40,0x00,0x00,0x00},{0x80,0x00,0x00,0x00},{0x1b,0x00,0x00,0x00},

{0x36,0x00,0x00,0x00}

};

//轮密钥加

void AddRoundKey(byte state[4][Nb],byte p[4][Nb])

{

int i, j;

for(i = 0; i < 4; i++)

{

for(j = 0; j < Nb; j++)

{

state[i][j] = state[i][j]^p[i][j];//状态数组与每一轮子密钥异或

}

}

}

//字节替换

void SubBytes(byte state[4][Nb])

{

int i, j;

for(i = 0; i < 4; i++)

{

for(j = 0; j < Nb; j++)

{

state[i][j] = S_box[state[i][j]];

}

}

}

//行移位

void ShiftRows(byte state[4][Nb]) //void memcpy(void *destin,void *source,unsigned n) 操作为从source复制一个n个字节的块到destin

{

byte temp[4];

int time; //向左循环移位的位数

for(time = 1; time < 4; time++)

{

memcpy(temp, state[time], time);//先存储需要左移的位到temp中

memcpy(state[time], state[time]+time, 4-time);//将余下的块左移

memcpy(state[time]+4-time, temp, time);//将事先存于temp中的位放到状态数组中

}

}

//列混合中使用的mul函数

byte mul(byte a, byte b)

{

if(a != 0 && b != 0)

{

return alog[(log[a] + log[b]) % 255];//参考代码,不太懂

}

else

return 0;

}

//列混合

void MixColumns(byte state[4][Nb])

{

byte temp[4][Nb];

int i, j;

//将state函数存入temp中

for(i = 0; i < 4; i++)

{

for(j = 0; j < Nb; j++)

{

temp[i][j] = state[i][j];

}

}

//按列做调用mul函数做列混合,以状态的每一列作为输入与混合每一列的数据得到新的列

for(i = 0; i < 4; i++)

{

state[0][i] = mul(0x02, temp[0][i]) ^ mul(0x03, temp[1][i]) ^ temp[2][i] ^ temp[3][i]; state[1][i] = mul(0x02, temp[1][i]) ^ mul(0x03, temp[2][i]) ^ temp[0][i] ^ temp[3][i]; state[2][i] = mul(0x02, temp[2][i]) ^ mul(0x03, temp[3][i]) ^ temp[1][i] ^ temp[0][i]; state[3][i] = mul(0x02, temp[3][i]) ^ mul(0x03, temp[0][i]) ^ temp[2][i] ^ temp[1][i]; }

}

//字节变换 密钥扩展中使用

void SubWords(byte a[Nk])

{

int i;

for(i = 0; i < Nk; i++)

{

a[i] = S_box[a[i]];

}

}

//左循环移位(只移一位) 密钥扩展中使用

void RotWord(byte temp[Nb])

{

byte temp1;

int i;

temp1 = temp[0];

for(i = 1; i < Nb; i++)

{

temp[i-1] = temp[i];

}

temp[Nb-1] = temp1;

}

//密钥扩展

void KeyExpansion(byte key[4][Nk],byte w[Nr+1][Nk][4])

{

byte k[Nb * (Nr + 1)][4]; //计算是用二维数组(便于计算),最后存于三维数组w中

byte temp[Nk];

byte b [4][4];

int i,j,l;

//存储初始密钥

for(i = 0; i < 4; i++)

{

for(j = 0; j < Nk; j++)

{

k[i][j] = key[i][j];

}

}

//计算扩展密钥

for(i = Nk; i < Nb * (Nr + 1); i++)

{

for(j = 0; j < 4; j++)

{

temp[j] = k[i - 1][j];

}

if(i%Nk == 0)

{

RotWord(temp);

SubWords(temp);

for(j = 0; j < 4 ; j++)

{

temp[j] = temp[j]^Rcon[i/Nk-1][j];

}

}

for(j = 0; j < 4; j++)

{

k[i][j] = k[i-Nk][j]^temp[j]; printf("%x ", k[i][j]);

}

printf("\n");

}

for (i = 0; i < Nr + 1; i++)

{

for (j = 0; j < Nk; j++)

{

for (l = 0; l < 4; l++)

{

w[i][j][l] = k[4 * i + j][l];

}

}

for (j = 0; j < Nk; j++)

{

for (l = 0; l < 4; l++)

{

b[j][l] = w[i][l][j];

}

}

for (j = 0; j < Nk; j++)

{

for (l = 0; l < 4; l++)

{

w[i][j][l] = b[j][l];

}

}

}

}

//加密模块

void Cipher(char file1[64], char file2[64])

{

byte state[4][Nb];

int i, j, k;

int round = 0;

byte w[Nr+1][Nk][4];

byte out[4][Nb];

FILE *fp;

OpenFile(file1, file2); //从文件中读取初始密钥和明文

KeyExpansion(key,w); //调用密钥扩展函数将所有的扩展密钥存于w[][][]数组中

//将读入的明文进行转秩

for(i = 0; i < 4; i++)

{

for(j = 0; j < Nb; j++)

{

state[j][i] = in[i][j];

}

}

//将初始明文和初始密钥存于文件中并在程序中输出

if ((fp = fopen("加密要求输出结果.txt", "w")) == NULL) {

AfxMessageBox("打开文件错误!");

exit(0);

}

fprintf(fp,"初始明文:\n");

for(i = 0; i < 4; i++)

{

fprintf(fp,"\n");

for(j = 0; j < Nb; j++)

{

fprintf(fp,"%0x ",state[i][j]);

}

}

fprintf(fp, "\n\n初始密钥:\n");

for(i = 0; i < 4; i++)

{

fprintf(fp,"\n");

for(j = 0; j < Nb; j++)

{

fprintf(fp,"%0x ",w[0][j][i]);

}

}

AddRoundKey(state,w[round]); //初始轮密钥加

//开始循环Nr轮

for(round = 1; round < Nr; round++)

{

SubBytes(state);

ShiftRows(state);

MixColumns(state);

AddRoundKey(state, w[round]);

if (round == 8)

{

fprintf(fp, "\n\n第九轮轮密钥:\n");

for (j = 0; j < 4; j++)

{

fprintf(fp, "\nw[%d]= ", (round+1)*4+j); for (k = 0; k < 4; k++)

{

fprintf(fp, "%x ", w[round+1][k][j]); }

}

fprintf(fp, "\n\n明文加密到第九轮:\n"); for (j = 0; j < 4; j++)

{

fprintf(fp, "\n");

for (k = 0; k < 4; k++)

{

fprintf(fp, "%x ", state[j][k]); }

}

}

}

SubBytes(state);

ShiftRows(state);

AddRoundKey(state, w[round]);

fprintf(fp, "\n\n第十轮轮密钥:\n");

for (j = 0; j < 4; j++)

{

fprintf(fp, "\nw[%d]= ",round*4+j);

for (k = 0; k < 4; k++)

{

fprintf(fp, "%x ", w[round][k][j]);

}

}

fprintf(fp, "\n\n加密完成后输出:\n");

for (j = 0; j < 4; j++)

{

fprintf(fp, "\n");

for (k = 0; k < 4; k++)

{

fprintf(fp, "%x ", state[j][k]);

}

}

fclose(fp);

if ((fp = fopen("CipherMessage.txt", "w")) == NULL)

{

AfxMessageBox("打开文件错误!");

exit(0);

}

for(i = 0; i < 4; i++)

{

for(j = 0; j < Nb; j++)

{

out[j][i] = state[i][j];

}

}

for(i = 0; i < 4; i++)

{

for(j = 0; j < Nb; j++)

{

fprintf(fp, "%c", out[i][j]); //此处的密文输出是以列优先

}

}

fclose(fp);

}

//逆行移位

void InvShiftRows(byte state[4][Nb]) //void memcpy(void *destin,void *source,unsigned n) 操作为从source复制一个n个字节的块到destin

{

byte temp[4];

int time,position; //向左循环移位的位数(向右移一位同向左移三位)position用于记录所移的是第几行

for(time = 3, position = 1; time > 0, position < 4; time--, position++)

{

memcpy(temp, state[position], time);

memcpy(state[position], state[position]+time, 4-time);

memcpy(state[position]+4-time, temp, time);

}

}

//逆字节替代

void InvSubBytes(byte state[4][Nb])

{

int i, j;

for(i = 0; i < 4; i++)

{

for(j = 0; j < Nb; j++)

{

state[i][j] = InvS_box[state[i][j]];

}

}

}

//逆列混合

void InvMixColumns(byte state[4][Nb])

{

byte temp[4][Nb];

int i, j;

for(i = 0; i < 4; i++)

{

for(j = 0; j < Nb; j++)

{

temp[i][j] = state[i][j];

}

}

for(i = 0; i < 4; i++)

{

state[0][i] = mul(0x0e, temp[0][i]) ^ mul(0x0b, temp[1][i]) ^ mul(0x0d, temp[2][i]) ^ mul(0x09, temp[3][i]);

state[1][i] = mul(0x0e, temp[1][i]) ^ mul(0x0b, temp[2][i]) ^ mul(0x09, temp[0][i]) ^ mul(0x0d, temp[3][i]);

state[2][i] = mul(0x0e, temp[2][i]) ^ mul(0x0b, temp[3][i]) ^ mul(0x09, temp[1][i]) ^ mul(0x0d, temp[0][i]);

state[3][i] = mul(0x0e, temp[3][i]) ^ mul(0x0b, temp[0][i]) ^ mul(0x09, temp[2][i]) ^ mul(0x0d, temp[1][i]);

}

}

//解密模块

void InvCipher(char file1[64], char file2[64])

{

byte state[4][Nb];

byte w[Nr+1][Nk][4];

byte out[4][Nb];

int i, j, k;

FILE *fp;

int round = 10;

OpenFile(file1, file2);

KeyExpansion(key,w);

for(i = 0; i < 4; i++)

{

for(j = 0; j < Nb; j++)

{

state[j][i] = in[i][j];

}

}

//将初始密文和初始密钥存入文件中并在程序中输出

if ((fp = fopen("解密要求输出结果.txt", "w")) == NULL)

{

AfxMessageBox("打开文件错误!");

exit(0);

}

fprintf(fp,"初始密文:\n");

for(i = 0; i < 4; i++)

{

fprintf(fp,"\n");

for(j = 0; j < Nb; j++)

{

fprintf(fp,"%0x ",state[i][j]);

}

}

fprintf(fp, "\n\n初始密钥:\n");

for(i = 0; i < 4; i++)

{

fprintf(fp,"\n");

for(j = 0; j < Nb; j++)

{

fprintf(fp,"%0x ",w[0][j][i]);

}

}

AddRoundKey(state,w[round]);

for(round = Nr - 1; round > 0; round--)

{

printf("第%d轮\n", round);

InvShiftRows(state);

InvSubBytes(state);

AddRoundKey(state, w[round]);

InvMixColumns(state);

if (round == 2)

{

fprintf(fp, "\n\n第九轮轮密钥:\n");

for (j = 0; j < 4; j++)

{

fprintf(fp, "\nw[%d]= ", (round-1)*4+j);

for (k = 0; k < 4; k++)

{

fprintf(fp, "%x ", w[round-1][k][j]);//列优先输出 }

}

fprintf(fp, "\n\n密文解密到第九轮输出:\n");

for (j = 0; j < 4; j++)

{

fprintf(fp, "\n");

for (k = 0; k < 4; k++)

{

fprintf(fp, "%x ", state[j][k]);

}

}

}

}

InvShiftRows(state);

InvSubBytes(state);

AddRoundKey(state,w[round]);

fprintf(fp, "\n\n最后一轮轮密钥:\n");

for (j = 0; j < 4; j++)

{

fprintf(fp, "\nw[%d]= ",round*4+j);

for (k = 0; k < 4; k++)

{

fprintf(fp, "%x ", w[round][k][j]);

}

}

fprintf(fp, "\n\n解密完成后输出:\n");

for (j = 0; j < 4; j++)

{

fprintf(fp, "\n");

for (k = 0; k < 4; k++)

{

fprintf(fp, "%x ", state[j][k]);

}

}

fclose(fp);

if ((fp = fopen("InvCipherMessage.txt", "w")) == NULL) {

AfxMessageBox("打开文件错误!");

exit(0);

}

for(i = 0; i < 4; i++)

{

for(j = 0; j < Nb; j++)

{

out[i][j] = state[i][j];

}

}

for(i = 0; i < 4; i++)

{

for(j = 0; j < Nb; j++)

{

out[i][j] = state[j][i];

fprintf(fp, "%c", out[i][j]);

}

}

fclose(fp);

}

void OpenFile(char file1[64], char file2[64])

{

FILE *fp;

int i, j;

if ((fp = fopen(file1, "r")) == NULL)//打开密钥 {

exit(0);

}

for (i = 0; i < 4; i++)

{

for (j = 0; j < 4; j++)

{

fscanf(fp, "%c", &key[i][j]);

}

}

fclose(fp);

if ((fp = fopen(file2, "r")) == NULL)//打开消息 {

exit(0);

}

} for (i = 0; i < 4; i++)

编程实现AES算法的加密解密过程

{ for (j = 0;

编程实现AES算法的加密解密过程

j < 4; j++) { fscanf(fp, "%c", &in[i][j]); } } fclose(fp);

6. 测试报告

6.1 加密

下面是我的程序运行界面:

下面的是我的程序运行结果: “CipherMessage.txt”:

6.2 解密

下面是我的程序运行界面:

编程实现AES算法的加密解密过程

下面的是我的程序运行结果:

“InvCipherMessage.txt”:

编程实现AES算法的加密解密过程

7 实验总结

本次课程设计对我来说是一个不小的挑战,在工作过程之中也遇到过种种问题与困难。但是最终在不断坚持下,最终完成了实验。然而,程序中仍存在诸多问题需要在今后更深入的学习和实践后改进,完成例如使用面向对象的思想与语言进行编程,设计更加良好的人机交互界面等高级要求。

通过完成本次实验,不仅使我对AES加密解密的原理、实现过程等诸多细节有了完整、透彻的理解,对算法、密码保密性和安全性有了新的认识,而且在具体实现中学习到了很多的知识与能力,认识到了自身存在的许多不足,对今后的学习工作起到了极大的帮助。

更多类似范文
┣ 电算化实验总结 1400字
┣ 会计电算化实验总结 900字
┣ 会计电算化实验总结 2000字
┣ 计算机原理实验总结 600字
┣ 更多加密算法实验总结
┗ 搜索类似范文