AES加密解密算法的设计与实现.docx
《AES加密解密算法的设计与实现.docx》由会员分享,可在线阅读,更多相关《AES加密解密算法的设计与实现.docx(24页珍藏版)》请在冰豆网上搜索。
AES加密解密算法的设计与实现
1.引言
对称密码算法主要用于保证数据的机密性,通信双方在加密/解密过程中使用它们共享的单一密钥。
对称密码算法的使用相当广泛,密码学界已经对它们进行了深入的研究[1]。
最常用的对称密码算法是数据加密标准(DES)算法,它是由IBM在美国国家安全局(NSA)授意之下研制的一种使用56位密钥的分组密码算法[2]。
该算法从1977年公布成为美国政府的商用加密标准后,使用了30多年。
随着社会的发展,科学技术日新月异,密码分析水平、芯片处理能力和计算技术也不断地进步,二十世纪七十年代到现在应用广泛的DES数据加密标准算法因为其密钥长度较小(仅有56位),已经越来越难适应当今社会的加密技术和安全要求,其实现速度、代码大小和跨平台性也不足以适应新的各种应用要求。
1997年,RSA安全赞助了一系列的竞赛,奖励第一个成功破解以DES加密的信息的队伍1万美元,洛克·韦尔谢什(RockeVerser),马特·柯廷(MattCurtin)和贾斯廷·多尔斯基(JustinDolske)领导的DESCHALL计划获胜,该计划使用了数千台连接到互联网的计算机的闲置计算能力[3]。
证明了DES的密钥长度(56位),能被当前社会加密解密技术破解,其安全性有待提高。
1998年,电子前哨基金会(EFF,一个信息人权组织)制造了一台DES破解器[4]。
虽然其制造价格约$250,000,但是它用两天多一点儿的时间就暴力破解了一个密钥,显示出迅速破解DES的可能性,说明了DES的安全性已经开始降低。
DES的主要问题是其密钥长度较短(仅56位),已经不适应当今分布式开放网络对数据加密安全性的要求。
随着计算机能力的突飞猛进,已经超期服役的DES终于显得力不从心。
在这种形势下,迫切需要设计一种强有力的算法作为新的一代分组加密标准,所以在DES每隔五年的评估会议中,1997年美国国家标准技术研究院(NIST,NationalInstituteofStandardsandTechnology)公开征集新的数据加密标准,最后一次美国政府终于决定不再继续延用DES作为联邦加密标准,也就表明了DES将退出加密标准的舞台,而新的标准:
高级加密标准AES(AdvancedEncryptionStandard)走上了历史的舞台[5]。
该算法作为新一代的数据加密标准汇聚了安全性、效率、密钥灵活性、多样性、简单性和对称性等优点。
因此1997年美国国家标准技术研究院(NIST,NationalInstituteofStandardsandTechnology)公开征集新的数据加密标准,即AES[6]。
该算法作为新一代的数据加密标准汇聚了安全性、效率、密钥灵活性、多样性、简单性和对称性等优点。
高级加密标准(AES),这个标准用来替代上一个世纪的DES,已经被多方分析并且广为全世界所使用。
经过长达五年的甄选流程,得出了结果[7]。
高级加密标准由美国国家标准与技术研究院(NIST)在2001年11月26日发布于FIPSPUB197,并在2002年5月26日成为有效的标准[8]。
2006年,高级加密标准(AES)发展成为了对称密钥加密中最流行的算法之一。
AES是美国国家标准技术研究所NIST旨在取代DES的新一代的加密标准。
NIST对AES候选算法的基本要求是:
对称分组密码体制;密钥长度支持128、192、256位;明文分组长度128位;算法应易于各种硬件和软件实现。
1998年NIST开始AES第一轮征集、分析、测试,共产生了15个候选算法。
1999年3月完成了第二轮AES的分析、测试。
1999年8月NIST公布了五种算法(MARS,RC6,Rijndael,Serpent,Twofish)成为候选算法[9]。
经过激烈的角逐,Rijndael,由比利时人设计的算法与其它候选算法在成为高级加密标准(AES)的竞争中取得成功,于2000年10月被NIST宣布成为取代DES的新一代的数据加密标准,即AES(这也是为什么人们将AES算法叫作Rijndael算法的原因)[10]。
尽管人们对AES还有不同的看法,但总体来说,Rijndael作为新一代的数据加密标准汇聚了强安全性、高性能、高效率、易用和灵活等优点。
AES的三个密钥长度:
128、192和256比特。
它与DES相比,它的128比特密钥比DES的56比特密钥要强上10^21倍。
2.AES加密解密原理
AES和Rijndael加密法并不完全一样(虽然在实际应用中二者可以互换),因为Rijndael加密法可以支持更大范围的区块和密钥长度:
AES的区块长度固定为128比特,密钥长度则可以是128,192或256比特;而Rijndael使用的密钥和区块长度可以是32位的整数倍,以128位为下限,256比特为上限。
加密过程中使用的密钥是由Rijndael密钥生成方案产生[11]。
AES算法基于排列和置换运算。
排列是对数据重新进行安排,置换是将一个数据单元替换为另一个。
AES使用几种不同的方法来执行排列和置换运算。
大多数AES计算是在一个特别的有限域完成的。
AES加密过程是在一个4×4的字节矩阵上运作,这个矩阵又称为“体(state)”,其初值就是一个明文区块(矩阵中一个元素大小就是明文区块中的一个Byte)[12]。
(Rijndael加密法因支持更大的区块,其矩阵行数可视情况增加)加密时,各轮AES加密循环(除最后一轮外)均包含4个步骤:
轮密钥加变换AddRoundKey—矩阵中的每一个字节都与该次回合密钥(roundkey)做XOR运算;每个子密钥由密钥生成方案产生。
字节代换(通常叫做S盒变换)SubBytes—将字节变换方法制成S盒表格,通过查表把每个字节进行快速变换成对应的字节。
行移位变换ShiftRows—将矩阵中的每个横列进行循环式移位。
列混淆变换MixColumns—为了充分混合矩阵中各个直行的操作。
这个步骤使用线性转换来混合每内联的四个字节。
最后一个加密循环中省略MixColumns步骤,而以另一个AddRoundKey取代[13]。
AES是一个迭代的、对称密钥分组的密码,它可以使用128、192和256位密钥长度,并且用128位分组长度加密和解密数据。
该算法输入分组、输出分组、状态长度均为128比特[14]。
对于AES算法的运算是在一个称为状态的二维字节数组上进行。
一个状态由四行组成,每一行包括Nb个字节,Nb等于分组长度除以32,AES分组长度为128位,因此,Nb=4,该值反应了状态中32-bit字的个数(列数);密钥长度128、192和256位可分别表示为Nk=4、6或8,反应了密钥中32-bit字的个数(列数)[15]。
而AES算法的轮数Nr仅依赖于密钥长度Nk,轮数和密钥长度的关系可以表示为:
Nr=6+Nk密钥长度—分组长度—轮数的关系如表2.1所示。
表2.1Key-Block-Round三者之间关系
密钥长度((Nkwords)
分组长度(Nbwords)
轮数(Nr)
4
4
10
6
4
12
8
4
14
对于加密和解密变换,AES算法使用的轮函数由4个不同的以字节为基本单位的变换复合而成,该过程由四个不同的阶段组成]:
(1)S盒变换,用一个S盒完成分组中的按字节代替;
(2)行移位变换,一个简单的置换;(3)列混淆变换,一个利用在域GF(28)上的算术性的代替;(4)轮密钥加变换,一个利用当前分组和扩展密钥的一个部分进行按位异或[16]。
AES对数据的加密过程是通过把输入的明文和密钥由轮函数经Nr轮迭代来实现的,结尾轮与前Nr-1轮不同。
前Nr-1轮依次进行S盒变换、行移位变换、列混淆变换和轮密钥加变换;结尾轮与前Nr-1轮相比去掉了列混淆变换[17]。
而解密过程与加密过程相反,通过把输入的密文和密钥由轮函数经Nr轮迭代来实现的,结尾轮与前Nr-1轮不同[18]。
前Nr-1轮依次进行逆行移位变换、逆S盒变换、轮密钥加变换和逆列混淆变换;结尾轮与前Nr-1轮相比去掉了逆列混淆变换。
AES算法的加密解密过程如下所示:
3.AES加密解密算法的组成部分
3.1密钥部分
3.1.1AES的S盒
staticunsignedcharAesSbox[16*16]=
{
//AES的S盒
/*0123456789abcdef*/
/*0*/0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,
/*1*/0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,
/*2*/0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,
/*3*/0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,
/*4*/0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,
/*5*/0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,
/*6*/0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,
/*7*/0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,
/*8*/0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,
/*9*/0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,
/*a*/0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,
/*b*/0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,
/*c*/0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,
/*d*/0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,
/*e*/0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,
/*f*/0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16
};
3.1.2AES的逆S盒
staticunsignedcharAesiSbox[16*16]=
{
//AES的逆S盒
/*0123456789abcdef*/
/*0*/0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38,0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb,
/*1*/0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87,0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb,
/*2*/0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d,0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e,
/*3*/0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2,0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25,
/*4*/0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16,0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92,
/*5*/0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda,0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84,
/*6*/0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a,0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06,
/*7*/0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02,0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b,
/*8*/0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea,0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73,
/*9*/0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85,0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e,
/*a*/0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89,0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b,
/*b*/0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20,0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4,
/*c*/0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31,0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f,
/*d*/0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d,0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef,
/*e*/0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0,0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61,
/*f*/0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26,0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d
};
3.1.3轮常量
staticunsignedcharAesRcon[11*4]=
{
//轮常量最右边三个字总为0
0x00,0x00,0x00,0x00,
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
};
3.1.4密钥移位函数
unsignedchar*RotWord(unsignedchar*word)
{
byte*temp=newbyte[4];
temp[0]=word[1];//实现左移一个字节
temp[1]=word[2];
temp[2]=word[3];
temp[3]=word[0];
returntemp;
};
3.1.5密钥字代换函数
unsignedchar*SubWord(unsignedchar*word)
{
byte*temp=newbyte[4];
for(intj=0;j<4;j++)
{
temp[j]=AesSbox[16*(word[j]>>4)+(word[j]&0x0f)];//将该字节的高4位作为行值,低4位作为列值,取出S盒中对应元素作为输出
}
returntemp;
};
3.1.6密钥扩展算法
AES加密解密过程中,每一轮都需要一个与输入分组具有相同长度的扩展密钥W[i]的参与[19]。
由于外部输入的加密密钥长度有限,所以在算法中要用一个密钥扩展程序把外部密钥扩展成更长的比特串,以生成各轮的加密和解密密钥。
AES算法利用外部输入密钥,涉及上述的模块:
轮常量AesRcon,密钥移位函数RotWord,密钥字代换函数SubWord。
通过生成器产生Nr+1轮轮密钥,每个轮密钥由Nb个字组成,共有Nb(Nr+1)个字W[i],i=0,1,……,Nb(Nr+1)-1。
voidKeyExpansion()
{
introw;
memset(w,0,16*15);
for(row=0;row{
w[4*row+0]=key[4*row];
w[4*row+1]=key[4*row+1];
w[4*row+2]=key[4*row+2];
w[4*row+3]=key[4*row+3];
}
byte*temp=newbyte[4];
for(row=Nk;row<4*(Nr+1);row++)
{
temp[0]=w[4*row-4];//当前列的前一列
temp[1]=w[4*row-3];
temp[2]=w[4*row-2];
temp[3]=w[4*row-1];
if(row%Nk==0)//逢nk时,对当前列的前一列作特殊处理
{
temp=SubWord(RotWord(temp));//先移位,再代换,最后和轮常量异或
temp[0]=(byte)((int)temp[0]^(int)AesRcon[4*(row/Nk)+0]);
temp[1]=(byte)((int)temp[1]^(int)AesRcon[4*(row/Nk)+1]);
temp[2]=(byte)((int)temp[2]^(int)AesRcon[4*(row/Nk)+2]);
temp[3]=(byte)((int)temp[3]^(int)AesRcon[4*(row/Nk)+3]);
}
//elseif(Nk>6&&(row%Nk==4))//这个还没有搞清楚
//{
//temp=SubWord(temp);
//
}
//w[row]=w[row-Nk]xortemp
w[4*row+0]=(byte)((int)w[4*(row-Nk)+0]^(int)temp[0]);
w[4*row+1]=(byte)((int)w[4*(row-Nk)+1]^(int)temp[1]);
w[4*row+2]=(byte)((int)w[4*(row-Nk)+2]^(int)temp[2]);
w[4*row+3]=(byte)((int)w[4*(row-Nk)+3]^(int)temp[3]);
}
};
3.2加密的部分
3.2.1轮密钥加变换AddRoundKey(与密钥扩展的异或运算)
轮密钥加变换中,回合密钥(roundkey)将会与原矩阵合并[20]。
在每次的加密循环中,都会由主密钥产生一把回合密钥(通过Rijndael密钥生成方案产生),这把密钥大小会跟原矩阵一样,以与原矩阵中每个对应的字节作异或加法。
轮密钥加变换用于将输入或中间态S的每一列与一个密钥字W[i]进行按位异或,其中,
由原始密钥通过密钥扩展算法产生。
voidAddRoundKey(intround)
{
inti,j;//i行j列//因为密钥w是一列一列排列的,即k0k4k8k12
for(j=0;j<4;j++)//k1k5k9k13
{
//k2k6k10k14
for(i=0;i<4;i++)//k3k7k11k15
{
//所以i行j列的下标是4*((round*4)+j)+i即16*round+4*j+i
State[i][j]=(unsignedchar)((int)State[i][j]^(int)w[4*((round*4)+j)+i]);
}
}
};
3.2.2字节代换SubBytes(即S盒变换)
S盒变换,是一个基于S盒的非线性置换,它用于输入或中间态的每一个字节通过一个简单的查表操作,将其映射为另一个字节。
映射方法是:
把输入字节的高4位作为S盒的行值,低4位作为列值,然后取出S盒中对应行和列的元素作为输出。
例如,输入为“89”(十六进制)的值所对应的S盒的行值为“8”,列值为“9”,S盒中相应位置的值为“a7”,就