




已阅读5页,还剩7页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
AES算法介绍高级加密标准(Advanced Encryption Standard)美国国家技术标准委员会(NIST)在2000年10月选定了比利时的研究成果Rijndael作为AES的基础。Rijndael是经过三年漫长的过程,最终从进入候选的五种方案中挑选出来的。Rijndael这个名字是从它的两个发明者Rijmen和Daemen的名字得来的。结合昨天提供的AES算法的Flash演示动画,可以更好的理解AES算法。以下是中文原文:原著:James McCaffrey翻译:小刀人原文出处:MSDN Magazine November 2003(Encrypt It)本文的代码下载:msdnmag 200311AES.exe(143KB)本文假设你熟悉C#和位(bit)操作。摘要AES(The Advanced Encryption Standard)是美国国家标准与技术研究所用于加密电子数据的规范。它被预期能成为人们公认的加密包括金融、电信和政府数字信息的方法。本文展示了AES的概貌并解析了它使用的算法。包括一个完整的C#实现和加密.NET数据的举例。在读完本文后你将能用AES加密、测试基于AES的软件并能在你的系统中使用AES加密。美国国家标准与技术研究所(NIST)在2002年5月26日建立了新的高级数据加密标准(AES)规范。本文中我将提供一个用C#编写的的能运行的AES实现,并详细解释到底什么是AES以及编码是如何工作的。我将向您展示如何用AES加密数据并扩展本文给出的代码来开发一个商业级质量的AES类。我还将解释怎样把AES结合到你的软件系统中去和为什么要这么做,以及如何测试基于AES的软件。注意本文提供的代码和基于本文的任何其它的实现都在联邦加密模块出口控制的适用范围之内(详情请参看Commercial Encryption Export Controls)。AES是一个新的可以用于保护电子数据的加密算法。明确地说,AES是一个迭代的、对称密钥分组的密码,它可以使用128、192和256位密钥,并且用128位(16字节)分组加密和解密数据。与公共密钥密码使用密钥对不同,对称密钥密码使用相同的密钥加密和解密数据。通过分组密码返回的加密数据的位数与输入数据相同。迭代加密使用一个循环结构,在该循环中重复置换(permutations)和替换(substitutions)输入数据。Figure 1显示了AES用192位密钥对一个16位字节数据块进行加密和解密的情形。Figure 1部分数据AES算法概述AES算法是基于置换和代替的。置换是数据的重新排列,而代替是用一个单元数据替换另一个。AES使用了几种不同的技术来实现置换和替换。为了阐明这些技术,让我们用Figure 1所示的数据讨论一个具体的AES加密例子。下面是你要加密的128位值以及它们对应的索引数组:00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff 01 23 45 67 89 10 11 12 13 14 15 192位密钥的值是:00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 01 23 45 67 89 10 1112 13 14 15 16 17 18 19 20 21 22 23 Figure 2S-盒(Sbox)当AES的构造函数(constructor)被调用时,用于加密方法的两个表被初始化。第一个表是代替盒称为S-盒。它是一个1616的矩阵。S-盒的前五行和前五列如Figure 2所示。在幕后,加密例程获取该密钥数组并用它来生成一个名为w的密钥调度表,Figure 3所示。Figure 3密钥调度表(Key Sched)w最初的Nk(6)行被作为种子,用原始密钥值(0x00到0x17)。剩余行从种子密钥来产生。变量Nk代表以32位字为单位的种子密钥长度。稍后我分析AES实现时你将清楚地看到w是怎样产生的。关键是这里现在有许多密钥使用而不只是一个。这些新的密钥被称为轮密钥(round keys)以将它们与原始种子密钥区别开来。Figure 4State(态)数组AES加密例程开始是拷贝16字节的输入数组到一个名为State(态)的44字节矩阵中。(参见Figure 4)。AES加密算法取名为Cipher,它操作State,其过程描述的伪代码参见Figure 5。在规范中,加密算法实现的一个预备的处理步骤被称为AddRoundKey(轮密钥加)。AddRoundKey用密钥调度表中的前四行对State矩阵实行一个字节一个字节的异或(XOR)操作,并用轮密钥表wc,r异或输入Stater,c。举个例子,如果State矩阵的第一行保存的字节是00,44,88,cc,第一列密钥调度表是00,04,08,0c,那么新的State0,2值是用w2,0(0x08或0x80)异或State0,2(0x88)的结果:1 00 01 00 00 00 01 00 0XOR 10 00 00 00 AES算法的主循环对State矩阵执行四个不同的操作,在规范中被称为SubBytes(字节替换)、ShiftRows(行位移变换)、MixColumns(列混合变换)和AddRoundKey。除了每次循环AddRoundKey都被调用并使用密钥调度表的下面四行外,AddRoundKey与预备处理步骤中的AddRoundKey相同。SubBytes例程是一个代替操作,它将State矩阵中的每个字节替换成一个由Sbox决定的新字节。比如,如果State0,1的值是0x40如果你想找到它的代替者,你取State0,1的值(0x40)并让x等于左边的数字(4)并让y等于右边的数字(0)。然后你用x和y作为索引进到Sbox表中寻找代替值,如Figure 2所示。ShiftRows是一个置换操作,它将State矩阵中的字节向左旋转。Figure 6示范了ShiftRows如何操作State。State的第0行被向左旋转0个位置,State的第1行被向左旋转1个位置,State的第2行被向左旋转2个位置,而State的第3行被向左旋转3个位置。Figure 6对State进行ShiftRows操作MixColumns是一个代替操作,它是理解AES算法时最具技巧(或者说是最需要动脑筋的部分)的部分。它用State字节列的值进行数学域加和域乘的结果代替每个字节。我将在下一节中详细解释专门的域加和域乘细节。假设State0,1的值是0x09,并且列1上的其它值分别为0x60,0xe1和0x04,那么State0,1的新值计算如下:State0,1=(State0,1*0x01)+(State1,1*0x02)+(State2,1*0x03)+(State3,1*0x01)=(0x09*0x01)+(0x60*0x02)+(0xe1*0x03)+(0x04*0x01)=0x57此处加法和乘法是专门的数学域操作,而不是平常整数的加法和乘法。SubBytes、ShiftRows、MixColumns和AddRoundKey四个操作在一个执行Nr次的循环里被调用,Nr为给定密钥大小的轮数减1。加密算法使用的轮数要么是10,12,要么是14,这依赖于种子密钥长度是128位、192位还是256位。在这个例子中,因为Nr等于12,则这四个操作被调用11次。该迭代完成后,在拷贝State矩阵到输出参数前,加密算法调用SubBytes、ShiftRows和AddRoundKey后结束。大致说来,AES加密算法的核心有四个操作。AddRoundKey使用从种子密钥值中生成的轮密钥代替4组字节。SubBytes替换用一个代替表替换单个字节。ShiftRows通过旋转4字节行的4组字节进行序列置换。MixColumns用域加和域乘的组合来替换字节。有限域GF(28)的加法和乘法正如你所看到的,AES加密算法使用相当简单明了的技术来代替和置换,除MixColumns例程以外。MixColumns使用特殊的加法和乘法。AES所用的加法和乘法是基于数学(译者注:近世代数)的域论。尤其是AES基于有限域GF(28)。GF(28)由一组从0x00到0xff的256个值组成,加上加法和乘法,因此是(28)。GF代表伽罗瓦域,以发明这一理论的数学家的名字命名。GF(28)的一个特性是一个加法或乘法的操作的结果必须是在0x00.0xff这组数中。虽然域论是相当深奥的,但GF(28)加法的最终结果却很简单。GF(28)加法就是异或(XOR)操作。然而,GF(28)的乘法有点繁难。正如你稍后将在C#实现中所看到的,AES的加密和解密例程需要知道怎样只用七个常量0x01、0x02、0x03、0x09、0x0b、0x0d和0x0e来相乘。所以我不全面介绍GF(28)的乘法,而只是针对这七种特殊情况进行说明。在GF(28)中用0x01的乘法是特殊的;它相当于普通算术中用1做乘法并且结果也同样-任何值乘0x01等于其自身。现在让我们看看用0x02做乘法。和加法的情况相同,理论是深奥的,但最终结果十分简单。只要被乘的值小于0x80,这时乘法的结果就是该值左移1比特位。如果被乘的值大于或等于0x80,这时乘法的结果就是用值0x1b异或后的值再左移1比特位。它防止了域溢出并保持乘法的乘积在范围以内。一旦你在GF(28)中用0x02建立了加法和乘法,你就可以用任何常量去定义乘法。用0x03做乘法时,你可以将0x03分解为2的幂之和。为了用0x03乘以任意字节b,因为0x03=0x02+0x01,因此:b*0x03=b*(0x02+0x01)=(b*0x02)+(b*0x01)这是可以行得通的,因为你知道如何用0x02和0x01相乘和相加,同哩,用0x0d去乘以任意字节b可以这样做:b*0x0d=b*(0x08+0x04+0x01)=(b*0x08)+(b*0x04)+(b*0x01)=(b*0x02*0x02*0x02)+(b*0x02*0x02)+(b*0x01)在加解密算法中,AES MixColumns例程的其它乘法遵循大体相同的模式,如下所示:b*0x09=b*(0x08+0x01)=(b*0x02*0x02*0x02)+(b*0x01)b*0x0b=b*(0x08+0x02+0x01)=(b*0x02*0x02*0x02)+(b*0x02)+(b*0x01)b*0x0e=b*(0x08+0x04+0x02)=(b*0x02*0x02*0x02)+(b*0x02*0x02)+(b*0x02)总之,在GF(28)中,加法是异或操作。其乘法将分解成加法和用0x02做的乘法,而用0x02做的乘法是一个有条件的左移1比特位。AES规范中包括大量有关GF(28)操作的附加信息。密钥扩展AES加密和解密算法使用了一个由种子密钥字节数组生成的密钥调度表。AES规范中称之为密钥扩展例程(KeyExpansion)。从本质上讲,从一个原始密钥中生成多重密钥以代替使用单个密钥大大增加了比特位的扩散。虽然不是无法抵御的困难,但理解KeyExpansion仍是AES算法中的一个难点。KeyExpansion例程高级伪代码如下所示:KeyExpansion(byte key,byte4w)copy the seed key into the first rows of wfor each remaining row of wuse two of the previous rows to create anew row用前面两行来产生一个新行(use two of the previous rows to create anew row)的例程用到了两个子例程,RotWord和SubWord以及一个名为Rcon的常数表(作为轮常数)。让我们先来逐个看一下这三东西,然后再回到整个KeyExpansion的讨论中来。RotWord例程很简单。它接受一个4个字节的数组并将它们向左旋转一个位置。因为轮调度表w有四列,RotWord将w的1行左旋。注意KeyExpansion使用的这个RotWord函数与加密算法使用的ShiftRows(行位移变换)例程非常相似,只是它处理的是单行密钥调度w,而不是整个加密状态表State。SubWord例程使用替换表Sbox对一给定的一行密钥调度表w进行逐字节替换。KeyExpansion操作中的替换实际上就像在加密算法中的替换一样。被代替的输入字节被分成(x,y)对,它被当作进入替换表Sbox的索引。举例来说,0x27的代替结果是x=2和y=7,并且Sbox2,7返回0xcc。KeyExpansion例程使用一个被称为轮常数表的数组Rcon。这些常数都是4个字节,每一个与密钥调度表的某一行相匹配。AES的KeyExpansion例程需要11个轮常数。你可以在Figure 7中看到这些常数清单。每个轮常数的最左边的字节是GF(28)域中2的幂次方。它的另一个表示方法是其每个值是前一个值乘上0x02,正如前一部分讨论GF(28)乘法时所描述的那样。注意0x800x02=0x36是0x80左移1个比特位后紧接着与0x1b进行异或,如前所述。现在让我们更进一步看看KeyExpansion内幕中的循环。这里所用的伪码比以前更为详细,这个循环是:for(row=Nk;row(4*Nr+1);+row)temp=wrow-1if(row%Nk=0)temp=SubWord(RotWord(temp)xor Rconrow/Nkelse if(Nk=8 and row%Nk=4)temp=SubWord(temp)wrow=wrow-Nkxor temp先不要去看if子句,你将看到密钥调度表w的每一行都是前面一行与行Nk异或的结果(4,6,或8取决于密钥的长度)。if条件的第一部分用SubWord、RotWord以及与轮常数的异或修改密钥调度表的每个第4、第6或第8行,取决于是否密钥的长度是128、192或256位。这个条件的第二部分将修改行12、20和28等等-对于256位密钥而言-每一个第8行都将添加密钥调度额外的可变性。让我们用本文开头所举的例子来考察KeyExpansion是如何开始的。种子密钥是192-bit/6-word值:00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17密钥调度字节表w的维数是4列并且Nb(Nr+1)等于4(12+1),或52行。KeyExpansion将种子密钥的值拷贝到密钥调度字节表w的第一行。因为我的种子密钥是192位(24字节),并且w表总是4列,在这种情况下KeyExapansion将种子密钥拷贝到w的前面6行。现在让我们看看KeyExapansion例程是如何填充密钥调度表其余部分的。在我的例子里,第一个被计算的行是第6行,因为第0-5行已被种子密钥的值填上了:temp=wrow-1=14 15 16 17条件(row%Nk=0)为真,因此首先RotWord子程序被应用:temp=15 16 17 14这时SubWord被应用:temp=59 47 f0 fa用Rconrow/Nk=Rcon6/6=01 00 00 00进行异或:temp=58 47 f0 fa这时用wrow-Nk=w6-6=00 01 02 03异或,产生了下面结果:w6=58 46 f2 f9密钥调度表w中其余所有行来重复这个过程本身。总而言之,AES加密和解密的一个重要部分就是从最初的种子密钥中生成多重轮密钥。这个KeyExapansion算法生成一个密钥调度并以某种方式进行替代和置换,在这种方式中,加密和解密算法极其相似。用C#编写AES类构造函数现在我已研究了构成AES加密算法的各个成分,我将用C#来实现它。官方的AES算法规范包含在联邦信息处理标准出版物197(Federal Information Processing Standards Publication 197)中。我决定尽可能贴切地以它作为我的实现的基础,但是我很快发现这个规范更是一个理论文献而非一个实现的向导。为了将这个官方规范作为资源来使用,我使用的变量名与标准出版物中所用的相同。(即便它们是那么晦涩,如Nr和W)。我的设计使用9个数据成员和一个枚举类型,如下所示:public enum KeySizeBits128,Bits192,Bits256;private int Nb;private int Nk;private int Nr;private byte key;private byte,Sbox;private byte,iSbox;private byte,w;private byte,Rcon;private byte,State;因为密钥长度只能是128位、192位或256位比特,它是非常适于用枚举类型:public enum KeySizeBits128,Bits192,Bits256;该规范文档一般用字节作为基本储存单元而不是用4字节的字作为两个重要数据成员的长度。这两个成员Nb和Nk代表以字为单位的块长以及以字为单位的密钥长度。Nr代表轮数。块长度总是16字节(或这说是128位,即为AES的4个字),因此它可以被声明为一个常量。密钥长度依照枚举参数KeySize的值被赋值为4、6或8。AES算法强调通过大量轮数来增加加密数据的复杂性。轮数是10、12或14中的任意一个并且是基于密码分析学理论的。它直接取决于密钥长度。当设计一个类接口时,我喜欢向后来做。我设想从应用程序中调用构造函数和方法。使用这个办法,我决定象下面这样来实例化一个AES对象:Aes a=new Aes(the key size,the seed key)我调用的加密和解密例程如下:a.Cipher(plainText,cipherText);a.InvCipher(cipherText,decipheredText);我选择少许笨拙的方法来命名Cipher和InvCipher,因为它们是用在AES规范文档中的。这里是AES类构造函数的代码为:public Aes(KeySize keySize,byte keyBytes)SetNbNkNr(keySize);this.key=new bytethis.Nk*4;keyBytes.CopyTo(this.key,0);BuildSbox();BuildInvSbox();BuildRcon();KeyExpansion();该构造函数首先调用一个辅助方法SetNbNkNr给Nb、Nk和Nr赋值,如Figure 8所示。如果考虑到效率,你可能将这些代码直接放入构造函数以避免方法调用的开销。接下来,你必须将传入构造函数的字节拷贝到类域变量中。密钥用其它的类域声明,并且用如下方法获得它的值:this.key=new bytethis.Nk*4;keyBytes.CopyTo(this.key,0);我决定在构造函数中调用私有辅助方法BuildSbox和BuildInvSbox来初始化替换表Sbox和iSbox。现在密钥扩展例程、Cipher方法和InvCipher方法各自都需要Sbox和iSbox,因此我本来可以在Cipher和InvCipher两个方法中初始化Sbox并调用KeyExpansion方法,但是将它们放入构造函数会代码结构更加清晰。在Figure 9中sBox被填充。填充iSbox代码类似。为了可读性对代码进行了结构化处理。正如后面你将看到的,还有另外一个可供选择的令人惊讶的方法为Sbox和iSbox表提供值。在构造函数中声明密钥调度表w、轮常数表Rcon和状态矩阵State,并用私有辅助方法来给Rcon和w赋值在我看来似乎是组织它们的最好办法,但那主要还是个风格问题。置换轮常数表Rcon的赋值代码参见Figure 7。回想一下,GF(28)中,Rcon每一行左边的字节都2的幂,因此这个表可用下面的方法建立:newVal=prevVal*0x02;AES构造函数在建立完密钥调度表w后结束,而w是在KeyExpansion方法中完成的(参见Figure 10)。其代码相当简单。规范文档使用一个假设的4-字节的字数据类型。因为C#没有那样的类型,但可以用一个4个字节的数组来模拟。在用new操作符为密钥调度表w分配空间后,w最初的Nk(4,6,或行从被传递到构造函数的种子密钥key数组中获值。this.wrow,0=this.key4*row;this.wrow,1=this.key4*row+1;this.wrow,2=this.key4*row+2;this.wrow,3=this.key4*row+3;两个字节相互的异或操作在这个代码中频频发生。它需要一些从byte到int的强制类型转换并转回到byte,因为异或操作是不能定义在C#的byte类型上,例如:temp0=(byte)(int)temp0(int)this.Rconrow/Nk,0);用来替代:temp0=temp0this.Rconrow/Nk,0;KeyExpansion方法有条件地调用私有方法SubWord和RotWord以保持同规范命名的一致性。此外,因为在C#中没有word类型,我用4字节数组实现了一个字。SubWord和RotWord的代码是相当简单,参见本文附带的AesLib源代码,它应该很容易理解。稍微具备有些技巧的部分是在SubWord中查找替代值。回想一下,为了寻找代替值,你将输入字节分成最左边的4位比特和最右边的4位比特。对于一个给定字节,用操作符右移4位将得到x索引,并且与0000 1111进行逻辑与得到y值。虽然有些长,但比实际代码更可读,我可以象下面这样:int x=word04;int y=word0&0x0f;byte substitute=this.Sboxx,y;result0=substitute;代替我原来用的代码:result0=this.Sboxword04,word0&0x0f;总的来说,AES构造函数接受一个密钥的长度为128,192或256位和一个字节数组种子密钥值。构造函数为输入块长度,种子密钥长度以及加密算法的轮数赋值,并将种子密钥拷贝到一个名为key的数据成员中。构造函数还创建了四个表:两个由加密和解密方法使用的替换表,一个轮常数表,和一个轮密钥的密钥调度表。用C#编写的AES Cipher方法Cipher方法如Figure 11所示。它真的非常简单,因为它分出了大部分的工作给私有方法AddRoundKey,SubBytes,ShiftRows和MixColumns。Cipher方法以拷贝明文输入数组到状态矩阵State为开始。最初调用AddRoundKey之后,Cipher方法比总轮数少迭代一次。在最后一轮时,正如规范中所说的那样,MixColumns调用被省略了。AddRoundKey和SubBytes私有方法的代码如Figure 12所示。AddRoundKey方法需要知道它处在那一轮,以便它正确引用4行密钥调度数组w。请注意Stater,c是用wc,r来异或并不是wr,c。SubBytes方法从输入字节中提取索引,与KeyExpansion方法中所用的右移4位和0x0f屏蔽技术相同。ShiftRows方法的代码如Figure 13所示。回想一下,ShiftRows(可能叫做RotateRows更好)将row0向左旋转0个位置,将row1向左旋转1位置等等。把State拷贝到temp矩阵之后,然后用下面的这行代码实现转换:this.Stater,(c+r)%Nb=tempr,c;这里利用%操作符的优点抱合一行。MixColumns方法(Figure 14)用GF(28)加和乘,以字节列中所有其它值的线性组合对每一个字节进行替换。乘法所用的常量系数基于域论的,并且是0x01,0x02或0x03中的任意一个值。给定某一列c,其替代式如下:State0,c=0x02*State0,c+0x03*State1,c+0x01*State2,c+0x01*State3,cState1,c=0x01*State0,c+0x02*State1,c+0x03*State2,c+0x01*State3,cState2,c=0x01*State0,c+0x01*State1,c+0x02*State2,c+0x03*State3,cState3,c=0x03*State0,c+0x01*State1,c+0x01*State2,c+0x02*State3,c这些表达式稍微有些长,因此我决定编写返回GF(28)与0x01,0x02和0x03之乘积的私有辅助函数。这些辅助函数非常短。例如,一个字节b被0x03域乘的代码如下:return(byte)(int)gfmultby02(b)(int)b);正如我前面讨论的,被0x02乘是所有GF(28)乘法的基本操作。我调用了我的gfmultby02方法,我改变了使用与规范相同的方法命名惯例,规范上称此例程为xtime。Cipher方法其输入反复应用四个操作来产生加密的输出。AddRoundKey用源于单个原始种子密钥的多重轮密钥来替代字节。SubBytes用某个替换表中的值替代字节。ShiftRows用移动字节行置换字节,而MixColumns用某一列的域加和乘法值来替代字节。用C#编写AES InvCipher方法AES解密算法背后的基本原则很简单:解密一个加密块,也就是以反向顺序还原(Undo)每个操作。尽管这是基本概念,但仍有几个细节要处理。AES规范称解密例程为InvCipher,而不是Decipher或Decrypt中的一个。这是AES背后的数学基础的反映,它基于可逆的数学操作。如果你将这个代码和Cipher代码比较的话,你会看到它比你预期的漂亮很多,但是有两点例外。首先,在InvCipher方法中逆方法调用(如InvSubBytes)顺序并不完全与在Cipher方法中相应调用(如SubBytes)的逆向顺序正好相同。其次,InvCipher调用的是一个AddRoundKey方法而不是InvAddRoundKey方法。值得注意的是InvCipher算法用密钥调度表并不是从较高编号的索引处开始向下处理至第0行。InvSubBytes,InvShiftRows和InvMixColumns方法的代码和与之有关的SubBytes,ShiftRows和MixColumns方法的代码非常接近。InvSubBytes方法几乎就是SubBytes方法,只是它用逆替换表iSbox而不是Sbox表。正如你可能猜测到的,iSbox就是还原任何被Sbox处理的对应操作。比如,如果你有字节b等于0x20,并在Sbox中找到其代替值,你得到0xb7。如果你在iSbox中找到0xb7的替代值,你便可得到0x20。相似地,InvShiftRows方法还原ShiftRows方法-row0被右移了0个位置,row1被右移了1个位置,row2被右移了2个位置,而row3被右移了3个位置。InvMixColumns方法还原MixColumns的工作,但没有用显而易见的方法。回想一下,MixColumns用原始字节列中的字节线性组合替换状态矩阵中的每个字节,并且系数是0x01,0x02,和0x03,域论再一次得到应用。它证明逆运算是相似的,只是被0x09,0x0b,0x0d和0x0e乘,如下所示:State0,c=0x0e*State0,c+0x0b*State1,c+0x0d*State2,c+0x09*State3,cState1,c=0x09*State0,c+0x0e*State1,c+0x0b*State2,c+0x0d*State3,cState2,c=0x0d*State0,c+0x09*State1,c+0x0e*State2,c+0x0b*State3,cState3,c=0x0b*State0,c+0x0d*State1,c+0x09*State2,c+0x0e*State3,c对于MixColumns方法,我决定专门写一个辅助函数,而不是内联展开已经较长的表达式或写一个普通的乘法辅助函数。让我向你展示一下我示如何编写这个任何字节b被常数0x0e(在10进制中的14)乘的函数,像任何数字一样,数字14可以被表示成2的幂的和,因此,14等于2+4+8。并且4等于2的平方,8等于2的立方,你可以将14表示为2+22+23。记住加法就是GF(28)中上的异或(),既然我已经有了gfmultby02函数,我可以用它得到我的结果:return(byte)(int)gfmultby02(gfmultby02(gfmultby02(b)/*23+*/(int)gfmultby02(gfmultby02(b)/*22+*/(int)gfmultby02(b);/*2*/用于AES加密算法的所有的操作都是可逆的,因此解密算法本质上是加密的所有操作的倒转。使用AES类用C#实现AES的特色之一就简单。看看Figure 15,它是我用来生成输出Figure 1的代码。声明了16字节明文输入硬代码值和24字节(192位)的种子密钥后,一个AES对象被初始化,加密Cipher方法将明文加密成为密文,然后再用InvCipher将密文解密。非常清楚和简单。因为AES对象针对字节数组进行处理,你可以轻松地用它处理.NET的其它数据类型。我创建了一个基于Windows的小Demo程序,它接受一个单纯的字符串-有8个字符(16-byte),对它进行加密和解密处理。运行画面如Figure 16。Figure 16加密Demo程序因为加密和解密例程都需要知道用户定义的密钥长度,我把它当作一个类范围的变量来声明,像这样:private Aes.KeySize keysize;注意种子密钥并不是由用户定义的。这个demo程序用一个空密钥(null key)作为种子密钥,通过为构造函数提供一个哑参数new byte16使得它全部由零字节组成。哑参数的长度是不相关的,因为种子密钥还是要被初始化为零。空密钥加密和解密是一个容易和有效的办法来阻止外界对数据偶然的检查。在System.Text中的Encoding.Unicode.GetBytes和Encoding.Unicode.GetString方法使得将一个.NET字符串转换成一个字节数组变得非常容易,反之亦然。实现选择现在让我们看看本文AES实现中出现的一些重要的变量,本文提供的代码可能出现的扩展,以及针对AES的密码分析学攻击。和我曾经处理的任何代码一样,AES算法也可以用其它可选的途径来实现。为什么这很重要呢?AES被试图广泛应用于各种系统,从只有很少内存容量的智能卡(smart cards)到大型的多处理器主机系统。在许多情况下,性能是关键因素,并且有时内存或处理器资源是有限的。事实上,AES的每个例程都能针对非常昂贵的内存资源进行性能优化,反之亦然。比如,为替换表Sbox分配256个值看起来好像很简单直白。但是,这些值是基于GF(28)理论的,它们都可以用编程方式来生成。逆向替换表和轮常数表也是如此。可选实现另外一个有趣的可能性是Cipher和InvCipher方法所用的GF(28)乘法。我的实现代码是一个被0x02乘的基本函数,而后是六个调用gfmultby02的附加函数。另一个可能性应该是写一个一般的乘法函数,并用它代替我目前实现的七个单独函数。另一个极端是你可以用被0x01,0x02,0x03,0x09,0x0b,0x0d和0x0e乘好的所有256个可能的字节值构成的一个完整乘积表。此外,实现GF(28)乘法另一途径是通过在两个256个字节的数组里查找,通常称为alog和log,因为它们在GF(28)中基于某些类似对数的方法。虽然这里给出的AES类完全能用于加密任何形式的.NET数据,你可能考虑想用各种方法扩展它。首先,因为本文的重点在于清楚地解释AES,所有错误检查被剥离掉,以我的经验,为某个象AES这样的类添加合理数量的错误检查将会产生三倍的代码量膨胀。因为AES使用了这么多的数组,需要做很多索引边界检查。例如,所给出的构造函数甚至都不检查种子密钥参数的长度。你可能还考虑通过添加更多的特性来扩展AES类。最明显的一个地方是添加加密和解密.NET基本数据类型的方法,比如:System.String和System.Int32。更加雄心勃勃的扩展可能会是实现一个流数据加密类。AES的安全性怎样呢?这是一个很难回答的问题,但是一般多数人的意见是:它是目前可获得的最安全的加密算
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年安全工程师考试应急管理及事故调查模拟试卷
- 儿童营养需求与饮食指南
- 2025年场(厂)内专用机动车辆维修人员考试试卷(汽车维修行业品牌知名度提升策略研究)
- 2025年劳动保障协理员(初级)考试试卷:劳动保障基础知识与社会保障法规应用案例分析集
- 2025年风力发电项目提案报告范文
- 2025年电子商务师(中级)职业技能鉴定试卷:电子商务平台数据分析与客户行为预测试题
- 农村家庭农场的经营管理协议
- 2025年消防工程师考试题库-消防设施设备选型与防火分区试题
- 大货车司机聘用协议
- 2025年辅导员招聘考试题库:校园文化建设案例分析与评估试题
- 四川省宜宾市翠屏区中学2022-2023学年数学八年级第二学期期末检测试题含解析
- 应急值守专题培训课件
- 2020-2021成都石室联合中学蜀华分校小学数学小升初模拟试卷附答案
- 某冶金机械厂供配电系统设计
- 《在中亚细亚草原上》赏析 课件
- 城市轨道交通供电技术442页完整版教学课件汇总全书电子教案
- Q/GDW248-2008输变电工程建设标准强制性条文实施管理规程第3部分:变电站建筑工程施工教程文件
- 小学生综合素质评价方案与评价表
- 隧道施工安全技术教育培训记录(共19页)
- 多维度-多归因因果量表(MMCS)
- 《原子物理学》(褚圣麟)第四章碱金属原子和电子自旋
评论
0/150
提交评论