Error message here!

Hide Error message here!

忘记密码?

Error message here!

请输入正确邮箱

Hide Error message here!

密码丢失?请输入您的电子邮件地址。您将收到一个重设密码链接。

Error message here!

返回登录

Close

AES详解(Java实现)

蒙丿鑫 2019-01-19 00:01:00 阅读数:211 评论数:0 点赞数:0 收藏数:0

GitHub

AES

高级数据加密标准(Advanced Encryption Standard),简称AES,由美国政府于1997年开始公开征集的新的数据加密标准算法。经过三轮筛选,美国政府最终于2000年10月2日正式宣布选中密码学家Joan Daemen和Vincent Rijmen提出的RINJDAEL算法作为AES。

RINJDAEL算法之所以能够最终被选为AES的原因是其安全、性能好、效率高、实用、灵活。

RINJDAEL算法是一个数据块长度和密钥长度都可变的分组加密算法,其数据块长度和密钥长度都可独立地选定为大于等于128位且小于等于256位的32位的任意倍数。而美国颁布AES时却规定数据块的长度为128位,密钥的长度可分别选择为128位、192位或256位。

RINJDAEL算法仍然采用分组密码的一种通用结构:对轮函数实施迭代的结构。只是轮函数结构采用的是代替/置换的网络结构(SP结构)。

数学基础

AES算法中的许多运算是按字节和4字节的字来定义的。把一个字节看成是在有限域GF(28)上的一个元素,把一个4字节的字看成是系数取自GF(28),并且次数小于4次的多项式。

GF(28)上的基础运算

一个由比特位b7b6b5b4b3b2b1b0组成的字节B可表示成系数为0或1的二进制多项式:b7x7+b6x6+b5x5+b4x4+b3x3+b2x2+b1x+b0。例如,字节B=10011011与二进制多项式b(x)=x7+x4+x3+x+1相对应。

(1)在GF(28)上的加法

在GF(28)上的加法定义为二进制多项式的加法,其系数模2相加。

e.m.

(x7+x4+x3+x+1)+(x6+x5+x3+x2+x+1)=x7+x6+x5+x4+x2

(2)在GF(28)上的乘法

在GF(28)上的乘法定义为二进制多项式的乘积,如果乘积次数大于7次则模一个次数为8的不可约二进制多项式。

e.m.对于不可约多项式m(x)=x8+x4+x3+x+1,

(x6+x4+x2+x+1)(x7+x+1)                                               

=(x13+x11+x9+x8+x6+x5+x4+x3+1)(mod x8+x4+x3+x+1)

=x7+x6+1                                                                            

(3)在GF(28)上的乘法逆

在GF(28)中,二进制多项式b(x)的乘法逆为满足a(x)b(x)=1的二进制多项式a(x),并记为

a(x)=b-1(x)。其中,'00'的乘法逆为其本身。

可以使用扩展欧几里得算法求得乘法逆,也可以直接将'00'~'FF'这128中情况全部试代求得乘法逆。

e.m.对于不可约多项式m(x)=x8+x4+x3+x+1,因为

x6+x2+x+1=(x8+x4+x3+x+1)+(x6+x4+x2+x+1)

x4=(x6+x4+x2+x+1)+(x6+x2+x+1)=(x8+x4+x3+x+1)+(x2+1)(x6+x4+x2+x+1)

x2+x+1=(x6+x2+x+1)+x2·x4=(x2+1)(x8+x4+x3+x+1)+x4(x6+x4+x2+x+1)

x=x4+(x2+x)(x2+x+1)=x6+x2+x+1=(x4+x+1)(x8+x4+x3+x+1)+(x6+x5+x2+1)(x6+x4+x2+x+1)

1=(x2+x+1)+(x+1)x=(x5+x4)(x8+x4+x3+x+1)+(x7+x5+x4+x3+x2+x+1)(x6+x4+x2+x+1)

        所以

(x6+x4+x2+x+1)(x7+x5+x4+x3+x2+x+1)=1

        即

(x6+x4+x2+x+1)-1=x7+x5+x4+x3+x2+x+1

(4)在GF(28)上的倍乘

在GF(28)中,倍乘函数 xtime(b(x))定义为x·b(x) (mod m(x))。即把字节B左移一位,若结果次数大于7次,则加上不可约多项式m(x)。

e.m.对于不可约多项式m(x)=x8+x4+x3+x+1,

x(x6+x4+x2+x+1)=x7+x5+x3+x2+x

x(x7+x5+x3+x2+x)=(x8+x6+x4+x3+x2)+(x8+x4+x3+x+1)=x6+x2+x+1

GF(28)上的多项式运算

有限域GF(28)上的多项式是系数取自GF(28)域元素的多项式。这样,一个4字节的字与一个次数小于4次的GF(28)上的多项式相对应。例如,字c='03010102'与多项式c(x)='03'x3+'01'x2+'01'x+'02'相对应。

(1)GF(28)上的多项式的加法

GF(28)上的多项式的加法定义为相应项系数相加。所以,在域GF(28)上的两个4字节的字相加也就是按位异或。

e.m.

('03'x3+'01'x2+'01'x+'02')+('0B'x3+'0D'x2+'09'x+'0E')='08'x3+'0C'x2+'08'x+'0C'

(2)GF(28)上的多项式的乘法

GF(28)上的多项式a(x)=a3x3+a2x2+a1x+a0和b(x)=b3x3+b2x2+b1x+b0相乘,如果乘积次数超过4次,则模x4+1。即对于c(x)=a(x)b(x)=c3x3+c2x2+c1x+c0,

c0=a0b0⊕a3b1⊕a2b2⊕a1b3

c1=a1b0⊕a0b1⊕a3b2⊕a2b3

c2=a2b0⊕a1b1⊕a0b2⊕a3b3

c3=a3b0⊕a2b1⊕a1b2⊕a0b3

(3)GF(28)上的多项式的倍乘

GF(28)上的多项式b(x)=b3x3+b2x2+b1x+b0的倍乘x·b(x)=b2x3+b1x2+b0x+b3。即多项式的系数循环左移一位。

AES参数

数据块字数Nb

在AES算法中,加解密要经过多次数据变换操作,每一次变换操作都会产生一个中间结果,这个结果称为状态。把状态表示为一个4行Nb列的二维字节数组,其中Nb为数据块长度除以32。因为状态数组有4行,所以状态数组的每一列便为一个4字节的字。

例如,对于长度为128的数据块B15B14...B1B0,Nb=128÷32=4,即该数据块可以表示为状态数组

AES算法中规定数据块长度为128位,即Nb=128÷32=4。

密钥字数Nk

类似地,密钥也可以表示为4行Nk列的二维字节数组,其中Nk为密钥长度除以32。同样地,密钥数组的每一列为一个4字节的字。

例如,对于长度为128的密钥K15K14...K1K0,Nk=128÷32=4,即该密钥可以表示为密钥数组

AES算法中规定密钥长度为128位、192位或256位,即Nk取值为4、6或8。

迭代轮数Nr

AES算法的迭代轮数Nr由Nb和Nk共同决定:

AES规定Nb=4,所以对应Nk取值4、6、8,Nr取值分别为10、12、14,即在Nb=4的情况下,Nr=Nk+6。

不可约多项式m(x)

在AES算法中,不可约多项式建议为:m(x)=x8+x4+x3+x+1,其系数的十六进制表示为m='11B'。

SP结构

AES的轮函数由以下3层组成:

1.非线性层:进行非线性S盒变换,由16个S盒并置而成,起混淆的作用;

2.线性混合层:进行行移位变换和列混合变换以确保多轮之上的高度扩散;

3.密钥加层:进行轮密钥加变换,将轮密钥简单地异或到中间状态上。

AES算法细节

(1)S盒变换

S盒变换是按字节进行的代替变换,是作用在状态中每个字节上的一种非线性字节变换。

加密过程

加密过程中的S盒变换按以下2步进行:

(1)把字节的值用它的乘法逆来代替;

(2)进行如下的仿射变换:

xi'=xi⊕xi+4⊕xi+5⊕xi+6⊕xi+7

y7y6y5y4y3y2y1y0=(x7'x6'x5'x4'x3'x2'x1'x0')⊕(01100011)

 加密过程的S盒表如下:

解密过程

解密过程中的S盒变换按以下2步进行:

(1)进行如下的仿射变换:

xi'=xi+2⊕xi+5⊕xi+7

y7y6y5y4y3y2y1y0=(x7'x6'x5'x4'x3'x2'x1'x0')⊕(00000101)

(2)把字节的值用它的乘法逆来代替。

解密过程的S盒表如下:

 

(2)行移位变换

行移位变换是对状态的行进行循环移位变换。移位值C1、C2、C3与Nb有关:

AES规定Nb=4,所以C1=1,C2=2,C3=3。

加密过程

加密过程中的行移位变换,状态的第0行不移位,第1行循环左移C1字节,第2行循环左移C2字节,第3行循环左移C3字节。

解密过程

解密过程中的行移位变换,状态的第0行不移位,第1行循环左移Nb-C1字节,第2行循环左移Nb-C2字节,第3行循环左移Nb-C3字节。

(3)列混合变换

列混合变换是对状态的列进行混合变换。

加密过程

加密过程中的列混合变换,把状态中的每一列看作GF(28)上的多项式,并与固定多项式c(x)='03'x3+'01'x2+'01'x+'02'相乘。

解密过程

解密过程中的列混合变换,把状态中的每一列看作GF(28)上的多项式,并与固定多项式c(x)='0B'x3+'0D'x2+'09'x+'0E'相乘。

(4)轮密钥加变换

轮密钥加变换是利用轮密钥对状态进行模2相加的变换。轮密钥长度等于数据块长度。在这个操作中,轮密钥被简单地异或到状态中去。

(5)轮密钥产生算法

轮密钥根据轮密钥产生算法由主密钥产生得到。轮密钥产生分2步进行:密钥扩展和轮密钥选择,且遵循以下原则:

1.轮密钥的比特总数为数据块长度与轮数加1的,即Nb(Nr+1)。

2.首先将用户密钥扩展为一个扩展密钥。

3.再从扩展密钥中选出轮密钥:第1个轮密钥由扩展密钥中的前Nb个字组成,第2个轮密钥由接下来的Nb个字组成,以此类推。

加密过程

加密过程的轮密钥产生分以下2步进行:

1.密钥扩展:用1个字元素的一维数组W[Nb(Nr+1)]存储扩展密钥。把主密钥放在数组W最开始的Nk个字中,其他的字由它前面的字经过处理(处理过程参照代码部分)后得到。分Nk≤6和Nk>6两种情况进行密钥扩展,两种情况的密钥扩展策略稍有不同。

2.轮密钥选择:轮密钥i由轮密钥缓冲区W[Nb/*i]到W[Nb/*(i+1)-1]的字组成。

解密过程

解密过程的轮密钥产生分以下2步进行:

1.加密过程的轮密钥产生。

2.把解密过程的列混合变换应用到除第一个和最后一个轮密钥之外的所有轮密钥上。

AES算法结构

无论是加密过程还是解密过程,都由以下部分组成:

1.一个初始轮密钥加。

2.Nr-1轮的标准轮函数(包括S盒变换、行移位、列混合、轮密钥加)。

3.最后一轮的非标准轮函数(只包括S盒变换、行移位、轮密钥加,不需要列混合)。

AES的安全性

AES的安全涉及策略是宽轨迹策略。宽轨迹策略是针对差分攻击和先行攻击提出来的。它的最大优点是可以给出算法的最佳差分特征的概率以及最佳线性逼近的偏差界,由此可以分析算法的抵抗差分攻击和线性攻击的能力。从而确保密码算法具有所需要的抵抗差分攻击和线性攻击的能力,确保密码算法的安全。

(1)抗攻击能力

AES的主要密码部件S盒和列混合都设计得相当好。其列混合的一个重要密码学指标分支数达到了最佳值,其S盒在非线性度、自相关性、差分均匀性、代数免疫性等主要密码学指标方面都达到相当好的水平。

然而,AES中的列混合的扩散度不够,密钥扩展的非线性不够,而且缺少抵抗侧信道分析的设计。这些不足之处给密码分析提供了可乘之机。

(2)弱密钥

AES的加解密算法采用不同的密钥扩展算法,而且都使用了非线性的S盒变换,并且在扩展产生每一轮密钥中使用不同的轮函数。这些措施使得AES不存在弱密钥和半弱密钥,也就是说,在AES加解密算法中,对密钥的选择没有除长度外的任何限制。

(3)适应性

AES的密钥长度可变,因此能够适应不同的安全应用环境。即使今后计算能力和攻击能力提高了,只要及时提高密钥的长度,便可获得满意的安全,因此密码的安全使用寿命长。

Java实现

word类

1 public classword {2 byte[] word;3 4 public word(byte[] b) {5 word = new byte[4];6 for (int i = 0; i < 4; i++)7 word[i] =b[i];8 }9 10 publicword(word w) {11 word = new byte[4];12 for (int i = 0; i < 4; i++)13 word[i] =w.word[i];14 }15 16 @Override17 publicString toString() {18 String str = "";19 for (byteb : word)20 str += Integer.toHexString((b & 0xff) + 0x100).substring(1);21 returnstr;22 }23 24 //*/* 25 /* 在GF(2^8)上的多项式加法26 /*@parama27 /*@paramb28 /*@return 29 /*/ 30 staticword add(word a, word b) {31 word c = new word(new byte[4]);32 for (int i = 0; i < 4; i++)33 c.word[i] =add(a.word[i], b.word[i]);34 returnc;35 }36 37 //*/* 38 /* 在GF(2^8)上的多项式乘法39 /*@parama40 /*@paramb41 /*@return 42 /*/ 43 staticword multiply(word a, word b) {44 word c = new word(new byte[4]);45 c.word[0] =add(46 add(47 add(48 multiply(a.word[0], b.word[0]), multiply(a.word[3], b.word[1])),49 multiply(a.word[2], b.word[2])),50 multiply(a.word[1], b.word[3]));51 c.word[1] =add(52 add(53 add(54 multiply(a.word[1], b.word[0]), multiply(a.word[0], b.word[1])),55 multiply(a.word[3], b.word[2])),56 multiply(a.word[2], b.word[3]));57 c.word[2] =add(58 add(59 add(60 multiply(a.word[2], b.word[0]), multiply(a.word[1], b.word[1])),61 multiply(a.word[0], b.word[2])),62 multiply(a.word[3], b.word[3]));63 c.word[3] =add(64 add(65 add(66 multiply(a.word[3], b.word[0]), multiply(a.word[2], b.word[1])),67 multiply(a.word[1], b.word[2])),68 multiply(a.word[0], b.word[3]));69 returnc;70 }71 72 //*/* 73 /* 在GF(2^8)上的多项式倍乘74 /*@parama75 /*@return 76 /*/ 77 staticword xtime(word a) {78 word b = new word(new byte[4]);79 for (int i = 0; i < 4; i++)80 b.word[i] = a.word[(i + 1) % 4];81 returnb;82 }83 //*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/ 84 static int m = 0x11b; //m=100011011 85 86 //*/* 87 /* 在GF(2^8)上的加法88 /*@parama89 /*@paramb90 /*@return 91 /*/ 92 static byte add(byte a, byteb) {93 return (byte) (a ^b);94 }95 96 //*/* 97 /* 在GF(2^8)上的求模98 /*@parama99 /*@paramb100 /*@return 101 /*/ 102 static byte mod(int a, intb) {103 String str_a =Integer.toBinaryString(a);104 String str_b =Integer.toBinaryString(b);105 if (str_a.length() 127)147 returnmod(r, m);148 return (byte) r;149 }150 }

仿射变换

1 /// 2 / 仿射变换3 /@paramb4 /@paramsign C:加密 D:解密5 /@return 6 // 7 static byte AffineTransformation(byte b, charsign) {8 byte[] x = Integer.toBinaryString((b & 0xff) + 0x100).substring(1).getBytes();9 for (int i = 0; i < x.length; i++) x[i] -= '0';10 if (sign == 'C') {11 byte[] x_ = new byte[8];12 byte b_ = 0;13 for (int i = 0; i < 8; i++) {14 x_[i] = (byte) (x[i] ^ x[(i + 1) % 8] ^ x[(i + 2) % 8] ^ x[(i + 3) % 8] ^ x[(i + 4) % 8]);15 b_ += x_[i] / Math.pow(2, 7 -i);16 }17 return (byte) (b ^ 0x63);18 } else{19 byte[] x = new byte[8];20 byte b_ = 0;21 for (int i = 0; i < 8; i++) {22 x_[i] = (byte) (x[(i + 1) % 8] ^ x[(i + 3) % 8] ^ x[(i + 6) % 8]);23 b_ += x_[i] /* Math.pow(2, 7 -i);24 }25 return (byte) (b_ ^ 0x05);26 }27 }

轮密钥产生算法

1 /// 2 / 加密密钥扩展3 /@paramCipherKey4 /@return 5 // 6 staticword[][] KeyExpansion(word[] CipherKey) {7 word[] W = new word[Nb /* (Nr + 1)];8 //密钥扩展 9 word Temp;10 if (Nk <= 6) {11 for (int i = 0; i < Nk; i++)12 W[i] =CipherKey[i];13 for (int i = Nk; i < W.length; i++) {14 Temp = new word(W[i - 1]);15 if (i % Nk ==0)16 Temp = word.add(SubByte(Rotl(Temp)), Rcon(i /Nk));17 W[i] = word.add(W[i -Nk], Temp);18 }19 } else{20 for (int i = 0; i < Nk; i++)21 W[i] =CipherKey[i];22 for (int i = Nk; i < W.length; i++) {23 Temp = new word(W[i - 1]);24 if (i % Nk ==0)25 Temp = word.add(SubByte(Rotl(Temp)), Rcon(i /Nk));26 else if (i % Nk == 4)27 Temp =SubByte(Temp);28 W[i] = word.add(W[i -Nk], Temp);29 }30 }31 //轮密钥选择 32 word[][] RoundKey = new word[Nr + 1][Nb];33 for (int i = 0; i < Nr + 1; i++)34 for (int j = 0; j < Nb; j++)35 RoundKey[i][j] = W[Nb /* i +j];36 returnRoundKey;37 }

1 staticword SubByte(word a) {2 word w = newword(a);3 for (int i = 0; i < 4; i++) {4 //乘法逆代替 5 w.word[i] =word.inverse(w.word[i]);6 //仿射变换 7 w.word[i] = AffineTransformation(w.word[i], 'C');8 }9 returnw;10 }11 12 staticword Rotl(word a) {13 word w = newword(a);14 byte b = w.word[0];15 for (int i = 0; i < 3; i++)16 w.word[i] = w.word[i + 1];17 w.word[3] =b;18 returnw;19 }20 21 static word Rcon(intn) {22 word Rcon = new word(new byte[4]);23 byte RC = 1;24 for (int i = 1; i < n; i++)25 RC =word.xtime(RC);26 Rcon.word[0] =RC;27 returnRcon;28 }1 /// 2 / 解密密钥扩展3 /@paramCipherKey4 /@return 5 // 6 staticword[][] InvKeyExpansion(word[] CipherKey) {7 word[][] InvRoundKey =KeyExpansion(CipherKey);8 for (int i = 1; i < Nr; i++)9 InvRoundKey[i] =InvMixColumn(InvRoundKey[i]);10 returnInvRoundKey;11 }

S盒变换

1 /// 2 / S盒变换3 /@paramstate4 /@return 5 // 6 staticword[] ByteSub(word[] state) {7 for (int i = 0; i < Nb; i++)8 for (int j = 0; j < 4; j++) {9 //乘法逆代替 10 state[i].word[j] =word.inverse(state[i].word[j]);11 //仿射变换 12 state[i].word[j] = AffineTransformation(state[i].word[j], 'C');13 }14 returnstate;15 }

1 /// 2 / S盒逆变换3 /@paramstate4 /@return 5 // 6 staticword[] InvByteSub(word[] state) {7 for (int i = 0; i < Nb; i++)8 for (int j = 0; j < 4; j++) {9 //仿射变换 10 state[i].word[j] = AffineTransformation(state[i].word[j], 'D');11 //乘法逆代替 12 state[i].word[j] =word.inverse(state[i].word[j]);13 }14 returnstate;15 }

行移位变换

1 /// 2 / 行移位变换3 /@paramstate4 /@return 5 // 6 staticword[] ShiftRow(word[] state) {7 byte[][] b = new byte[4][Nb];8 for (int j = 0; j < Nb; j++)9 for (int i = 0; i < 4; i++)10 b[i][j] =state[j].word[i];11 for (int i = 1; i < 4; i++)12 for (int k = 0; k < i; k++) {13 byte t = b[i][0];14 for (int j = 0; j < Nb - 1; j++)15 b[i][j] = b[i][j + 1];16 b[i][Nb - 1] =t;17 }18 for (int j = 0; j < Nb; j++)19 for (int i = 0; i < 4; i++)20 state[j].word[i] =b[i][j];21 returnstate;22 }

1 /// 2 / 行移位逆变换3 /@paramstate4 /@return 5 // 6 staticword[] InvShiftRow(word[] state) {7 byte[][] b = new byte[4][Nb];8 for (int j = 0; j < Nb; j++)9 for (int i = 0; i < 4; i++)10 b[i][j] =state[j].word[i];11 for (int i = 1; i < 4; i++)12 for (int k = 0; k < Nb - i; k++) {13 byte t = b[i][0];14 for (int j = 0; j < Nb - 1; j++)15 b[i][j] = b[i][j + 1];16 b[i][Nb - 1] =t;17 }18 for (int j = 0; j < Nb; j++)19 for (int i = 0; i < 4; i++)20 state[j].word[i] =b[i][j];21 returnstate;22 }

列混合变换

1 /// 2 / 列混合变换3 /@paramstate4 /@return 5 // 6 staticword[] MixColumn(word[] state) {7 byte[] b = {(byte) 0x02, (byte) 0x01, (byte) 0x01, (byte) 0x03};8 word a = newword(b);9 for (int i = 0; i < Nb; i++)10 state[i] =word.multiply(a, state[i]);11 returnstate;12 }

1 /// 2 / 列混合逆变换3 /@paramstate4 /@return 5 // 6 staticword[] InvMixColumn(word[] state) {7 byte[] b = {(byte) 0x0E, (byte) 0x09, (byte) 0x0D, (byte) 0x0B};8 word a = newword(b);9 for (int i = 0; i < Nb; i++)10 state[i] =word.multiply(a, state[i]);11 returnstate;12 }

轮密钥加变换

1 /// 2 / 轮密钥加变换3 /@paramstate4 /@paramkey5 /@return 6 /*/ 7 staticword[] AddRoundKey(word[] state, word[] key) {8 for (int i = 0; i < Nb; i++)9 state[i] =word.add(state[i], key[i]);10 returnstate;11 }

加解密过程

1 /// 2 / 加密3 /@paramplaintext 4个字长度的明文4 /@paramCipherKey 4、6或8个字长度的密钥5 /@return 6 /*/ 7 public staticword[] encrypt(word[] plaintext, word[] CipherKey) {8 Nb = 4;9 Nk =CipherKey.length;10 Nr = Nk + 6;11 //加密密钥扩展 12 RoundKey =KeyExpansion(CipherKey);13 word[] ciphertext = newword[plaintext.length];14 for (int i = 0; i < plaintext.length; i++)15 ciphertext[i] = newword(plaintext[i]);16 //初始轮密钥加 17 ciphertext = AddRoundKey(ciphertext, RoundKey[0]);18 //轮函数 19 for (int i = 1; i < Nr + 1; i++) {20 //S盒变换 21 ciphertext =ByteSub(ciphertext);22 //行移位 23 ciphertext =ShiftRow(ciphertext);24 //列混合 25 if (i != Nr) ciphertext =MixColumn(ciphertext);26 //轮密钥加 27 ciphertext =AddRoundKey(ciphertext, RoundKey[i]);28 }29 returnciphertext;30 }

1 /// 2 / 解密3 /@paramciphertext 4个字长度的密文4 /@paramCipherKey 4、6或8个字长度的密钥5 /@return 6 /*/ 7 public staticword[] decrypt(word[] ciphertext, word[] CipherKey) {8 Nb = 4;9 Nk =CipherKey.length;10 Nr = Nk + 6;11 //解密密钥扩展 12 InvRoundKey =InvKeyExpansion(CipherKey);13 word[] plaintext = newword[ciphertext.length];14 for (int i = 0; i < ciphertext.length; i++)15 plaintext[i] = newword(ciphertext[i]);16 //初始轮密钥加 17 plaintext =AddRoundKey(plaintext, InvRoundKey[Nr]);18 //轮函数 19 for (int i = Nr - 1; i >= 0; i--) {20 //S盒变换 21 plaintext =InvByteSub(plaintext);22 //行移位 23 plaintext =InvShiftRow(plaintext);24 //列混合 25 if (i != 0) plaintext =InvMixColumn(plaintext);26 //轮密钥加 27 plaintext =AddRoundKey(plaintext, InvRoundKey[i]);28 }29 returnplaintext;30 }

测试

测试数据

明文:0001000101a198afda78173486153566

密钥:00012001710198aeda79171460153594

运行结果

参考文献

张焕国,唐明.密码学引论(第三版).武汉大学出版社,2015年

版权声明
本文为[蒙丿鑫]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/mx-lqk/p/10285379.html

编程之旅,人生之路,不止于编程,还有诗和远方。
阅代码原理,看框架知识,学企业实践;
赏诗词,读日记,踏人生之路,观世界之行;

支付宝红包,每日可领