一、DES简介
- DES算法属于分组加密算法
- 信息按照固定长度进行分组,分组长度为64位
- 混淆和扩散是它采用的两个最重要的安全特性
- 混淆是指通过密码算法使明文和密文以及密钥的关系非常复杂,无法从数学上描述或者统计。
- 扩散是指明文和密钥中的每一位信息的变动,都会影响到密文中许多位信息的变动,从而隐藏统计上的特性,增加密码的安全。
需要注意的地方是掌握DES算法的16轮加、解密流程以及子密钥的产生流程。
二、DES实现大纲
在我的另一篇博客《加密算法之对称加密–DES》已经提到过DES算法的大致过程,整个流程如下图:
为了深入理解整个流程,我们将细化讲解DES算法里十六轮迭代变化中的子密钥生成以及F函数。
三、DES算法之子密钥生成
1. 子密钥生成流程
流程图
子密钥置换选择1(把64位的密钥变为56位长)
假设原密钥为 K s = k 1 , k 2 , k 3 , . . . . . . , k 64 K_s= k_1,k_2,k_3,......,k_{64} Ks=k1,k2,k3,......,k64
DES算法的实际密钥长度为56,因为64位原密钥每8位的最后一位,即第8,16,24,32,40,48,56,64位为校验位。通过如下的置换规则,将实际的
56
56
56为位密钥选择出来并置乱:
57
49
41
33
25
17
9
1
58
50
42
34
26
18
10
2
59
51
43
35
27
19
11
3
60
52
44
36
63
55
47
39
31
23
15
7
62
54
46
38
30
22
14
6
61
53
45
37
29
21
13
5
28
20
12
4
\begin{array}{lllllll} 57 & 49 & 41 & 33 & 25 & 17 & 9 \\ 1 & 58 & 50 & 42 & 34 & 26 & 18 \\ 10 & 2 & 59 & 51 & 43 & 35 & 27 \\ 19 & 11 & 3 & 60 & 52 & 44 & 36 \\ 63 & 55 & 47 & 39 & 31 & 23 & 15 \\ 7 & 62 & 54 & 46 & 38 & 30 & 22 \\ 14 & 6 & 61 & 53 & 45 & 37 & 29 \\ 21 & 13 & 5 & 28 & 20 & 12 & 4 \end{array}
57110196371421495821155626134150593475461533425160394653282534435231384520172635442330371291827361522294
因此通过置换选择1之后,56位密钥为 K s ′ = k 1 , k 2 , k 3 . . . . . . k 56 K_{s' }= k_1,k_2,k_3......k_{56} Ks′=k1,k2,k3......k56,其中 k 1 = K s [ 57 ] , k 2 = K s [ 49 ] , k 3 = K s [ 41 ] , . . . . . . k 56 = K s [ 4 ] k_1 = K_{s[57]}, k_2 = K_{s[49]},k_3 = K_{s[41]},......k_{56} = K_{s[4]} k1=Ks[57],k2=Ks[49],k3=Ks[41],......k56=Ks[4]。
子密钥迭代变换
实际密钥 K s ′ = k 1 , k 2 , k 3 . . . . . . k 56 K_{s' }= k_1,k_2,k_3......k_{56} Ks′=k1,k2,k3......k56
(1)分组:将56位实际密钥分为Ci和Di两组
- C i = k 1 , k 2 , . . . . . . , k 28 C_i = k_1,k_2,......,k_{28} Ci=k1,k2,......,k28
- D i = k 29 , k 30 , . . . . . . k 56 D_i = k_{29},k_{30},......k_{56} Di=k29,k30,......k56
(2)循环移位(左移)
- 移位判断表:
1 1 9 1 2 1 10 2 3 2 11 2 4 2 12 2 5 2 13 2 6 2 14 2 7 2 15 2 8 2 16 1 \begin{array}{llll} 1 & 1 & 9 & 1 \\ 2 & 1 & 10 & 2 \\ 3 & 2 & 11 & 2 \\ 4 & 2 & 12 & 2 \\ 5 & 2 & 13 & 2 \\ 6 & 2 & 14 & 2 \\ 7 & 2 & 15 & 2 \\ 8 & 2 & 16 & 1 \end{array} 123456781122222291011121314151612222221
第一列和第三列代表迭代次数,第二列和第四列代表对应的循环左移位数。 - 第1,2,9,16轮迭代时循环左移一位,其余循环左移两位
- 最终得到:
- 循环左移一位: C i ′ = k 2 , k 3 , . . . . . . k 28 , k 1 ; D i ′ = K 30 , k 31 , . . . . . . k 56 , k 29 C_{i'}=k_2,k_3,......k_{28},k_1;D_{i'}=K_{30},k_{31},......k_{56},k_{29} Ci′=k2,k3,......k28,k1;Di′=K30,k31,......k56,k29
- 循环左移两位: C i ′ = k 3 , k 4 , . . . . . . k 1 , k 2 ; D i ′ = K 31 , k 32 , . . . . . . k 29 , k 30 C_{i'}=k_3,k_4,......k_1,k_2;D_{i'}=K_{31},k_{32},......k_{29},k_{30} Ci′=k3,k4,......k1,k2;Di′=K31,k32,......k29,k30
(3) 选择置换2
将第(2)步得到的
C
i
′
C_{i'}
Ci′以及
D
i
′
D_{i'}
Di′拼接起来形成56位密钥
K
s
′
′
=
[
C
i
′
,
D
i
′
]
K_{s''} = [C_{i'},D_{i'}]
Ks′′=[Ci′,Di′],
然后进行选择置换2,置换列表如下:
14
17
11
24
1
5
3
28
15
6
21
10
23
19
12
4
26
8
16
7
27
20
13
2
41
52
31
37
47
55
30
40
51
45
33
48
44
49
39
56
34
53
46
42
50
36
29
32
\begin{array}{lllllll} 14 & 17 & 11 & 24 & 1 & 5 \\ 3 & 28 & 15 & 6 & 21 & 10 \\ 23 & 19 & 12 & 4 & 26 & 8 \\ 16 & 7 & 27 & 20 & 13 & 2 \\ 41 & 52 & 31 & 37 & 47 & 55 \\ 30 & 40 & 51 & 45 & 33 & 48 \\ 44 & 49 & 39 & 56 & 34 & 53 \\ 46 & 42 & 50 & 36 & 29 & 32 \end{array}
1432316413044461728197524049421115122731513950246420374556361212613473334295108255485332
最后得到每一轮迭代所用到的48位子密钥 k i = k 1 , k 2 , k 3 , . . . . . . , k 48 k_i = k_1,k_2,k_3,......,k_{48} ki=k1,k2,k3,......,k48,其中 k 1 = K s ′ ′ [ 14 ] , k 2 = K s ′ ′ [ 17 ] , . . . . . . k 4 8 = K s ′ ′ [ 32 ] k_1 = K_{s''[14]}, k_2 = K_{s''[17]},......k_48 = K_{s''[32]} k1=Ks′′[14],k2=Ks′′[17],......k48=Ks′′[32].
四、DES算法之F函数变换
1. 圈变换
DES算法第i轮圈变换流程如下图:
根据此图可以得到迭代公式:
{ L i = R i − 1 R i = L i − 1 ⨁ f ( R i − 1 , K i ) , i = 1 , 2 , , , , 16 \left\{\begin{matrix} L_i=R_{i-1}\\R_i=L_{i-1}\bigoplus f(R_{i-1},K_i),i=1,2,,,,16 \end{matrix}\right. {Li=Ri−1Ri=Li−1⨁f(Ri−1,Ki),i=1,2,,,,16
并且可以很清晰的看到每一轮迭代所进行的操作,接下来将详细讲一下F函数中的操作
2. F函数
F函数梗概
E扩展置换
- 将输入的32比特 R i R_i Ri每4比特为一组,共分为8块;
- 分别将第 m − 1 m-1 m−1块的最右比特和第 m + 1 m+1 m+1块的最左比特添到第 m m m块的左边和右边,形成输出的第 m m m个 6 6 6比特块.
- 形如:
- 理解:将1-32位看成一个环,因此第1位前是第32位,第4位后是第5位…
异或加密
- 将前一步得到的 48 48 48位经过扩展序列与每一轮的密钥 k i k_i ki进行按位异或
S盒变换
-
目的:将 48 48 48位序列压缩为$32v位序列
-
过程详解:
- 每 6 6 6位输入记为 B 1 , B 2 , B 3 , B 4 , B 5 , B 6 B1,B2,B3,B4,B5,B6 B1,B2,B3,B4,B5,B6
- B 1 B 6 B1B6 B1B6作为 S S S盒的行号, B 2 B 3 B 4 B 5 B2B3B4B5 B2B3B4B5作为 S S S盒的列号
-
S S S盒内容
-
举例
P置换
经过
S
S
S盒变换的序列最后进行P置换,方式类似于之前的置换方式。
五、Java编程实现
public class DES_Key {
public static void main(String[] args) {
//Scanner input = new Scanner(System.in);
// System.out.println("请输入十六进制明文:");
// String plaintxt = input.next();
// Integer tmpInt = Integer.valueOf(plaintxt,16);
// String binary_plain = Integer.toBinaryString(tmpInt);
// System.out.println(binary_plain);
// System.out.println("请输入十六进制明文密钥:");
// String Key = input.next();
String Key = "1234567890ABCDFE";
String binary_Key = hexString2binaryString(Key);
System.out.print("binary_Key:");
//0001 0010 0011 0100 0101 0110 0111 1000 1001 0000 1010 1011 1100 1101 1111 1110
System.out.println(binary_Key);
ArrayList<char[]> resultKi = new ArrayList<char[]>();//存放16个Ki
GenerateKey(binary_Key,resultKi);
Iterator<char[]> it = resultKi.iterator();
int KiIndex = 0;
while(it.hasNext()){
char []temp = (char[]) it.next();
System.out.print("第"+(KiIndex+1)+"轮密钥:");
System.out.println(temp);
KiIndex++;
}
String Plain = "1111111111111110";
String binary_Plain = hexString2binaryString(Plain);
System.out.print("binary_Plain:");
System.out.println(binary_Plain);
char[] DESEncrypt = EncryptCircleTrans(binary_Plain, resultKi);
System.out.print("DES加密结果:");
System.out.println(DESEncrypt);
char[] DESDecrypt = DecryptCircleTrans(ToString(DESEncrypt), resultKi);
System.out.print("DES解密结果:");
System.out.println(DESDecrypt);
}
//辅助函数:将char转为String
public static String ToString(char[]a){
String b = "";
for(int i=0;i<a.length;i++){
b += a[i];
}
return b;
}
//char数组转为int
public static int[] trsnChar2Int(char[] CharArr){
int [] resultArr = new int[CharArr.length];
for(int i=0;i<CharArr.length;i++){
resultArr[i] = CharArr[i]-'0';
}
return resultArr;
}
//十六进制转2进制字符串
public static String hexString2binaryString(String hexString)
{
if (hexString == null)
return null;
String bString = "", tmp;
for (int i = 0; i < hexString.length(); i++)
{
tmp = "0000"
+ Integer.toBinaryString(Integer.parseInt(hexString
.substring(i, i + 1), 16));
bString += tmp.substring(tmp.length() - 4);
}
return bString;
}
//密钥选择置换PC_1 (64-56)
public static char[] KeyPermutation1(String Key){
char [] key = Key.toCharArray();//Get 64bits key array
//System.out.println(key);
char [] resultKey = new char[56];
int PC_1[] = new int[]{57,49,41,33,25,17,9,1,58,50,42,34,26,18,
10,2,59,51,43,35,27,19,11,3,60,52,44,36,
63,55,47,39,31,23,15,7,62,54,46,38,30,22,
14,6,61,53,45,37,29,21,13,5,28,20,12,4};
for(int i=0;i<resultKey.length;i++){
resultKey[i] = key[PC_1[i]-1];
}
return resultKey;
}
//CD选择置换PC_2 (56-48)
public static char[] KeyPermutation2(char[] CD){
char [] cd = CD;//Get 56bits CD array
//System.out.println(cd.length);
char [] resultCd = new char[48];
int PC_2[] = new int[]{14,17,11,24,1,5,3,28,15,6,21,10,
23,19,12,4,26,8,16,7,27,20,13,2,
41,52,31,37,47,55,30,40,51,45,33,48,
44,49,39,56,34,53,46,42,50,36,29,32};
for(int i=0;i<48;i++){
resultCd[i] = cd[PC_2[i]-1];
}
return resultCd;
}
//循环生成密钥Ki
public static char[] CircleGenKey(char[]C,char[]D,int flag){
char [] Ci = C;
char [] Di = D;
if(flag == 0 || flag == 1 || flag == 8 || flag == 15 ){
//循环左移1
for(int i=0;i<28;i++){
C[i] = Ci[(i+1)%28];
D[i] = Di[(i+1)%28];
}
if(flag == 15)
C[27] = '0';
}
else{//循环左移2
char temp0 = C[0];
char temp00 = D[0];
for(int i=0;i<28;i++){
C[i] = C[(i+1)%28];
D[i] = D[(i+1)%28];
}
C[27]=temp0;
D[27]=temp00;
char temp1=C[0];
char temp11=D[0];
for(int i=0;i<28;i++){
C[i] = C[(i+1)%28];
D[i] = D[(i+1)%28];
}
C[27]=temp1;
D[27]=temp11;
}
//System.out.println(C);
//System.out.println(D);
char [] ResultKey = new char[56];
for(int i=0;i<28;i++){
ResultKey[i]= C[i];
}
for(int j=28;j<56;j++){
ResultKey[j]= D[j-28];
}
char[] ResultKi = KeyPermutation2(ResultKey);
return ResultKi;//ki
}
//生成密钥16轮Ki
public static void GenerateKey(String Key,ArrayList<char[]> resultKi){
char [] keySeed = KeyPermutation1(Key);//Get 56bits key that after OptPermutation PC_1
char [] LeftC0 = new char[28];
for(int i=0;i<LeftC0.length;i++){
LeftC0[i] = keySeed[i];
}
char [] RightD0 = new char[28];
for(int j=0;j<RightD0.length;j++){
RightD0[j] = keySeed[j+28];
}
char [] LeftC = LeftC0;
char [] RightD = RightD0;
for(int i=0;i<16;i++){
char[] temp = CircleGenKey(LeftC,RightD,i);
resultKi.add(temp);
//System.out.println(temp);
}
}
//将原明文进行IP置换
public static char[] InitialPermutation(char[] plaintxt)
{
char plain[] = plaintxt;
int[] IP = new int[]{58,50,42,34,26,18,10,2,60,52,44,36,28,20,12,4,
62,54,46,38,30,22,14,6,64,56,48,40,32,24,16,8,
57,49,41,33,25,17,9,1,59,51,43,35,27,19,11,3,
61,53,45,37,29,21,13,5,63,55,47,39,31,23,15,7};
char[]result = new char[64];
for(int i=0; i< plaintxt.length; i++){
result[i]= plain[IP[i]-1];
}
return result ;
}
//IP 逆置换
public static char[] ReverseInitialPermutation(char[]afterCircle)
{
char[] afterCircleTmp = afterCircle;
char[] resultReverseIP = new char[64];
int [] IPReverse = new int[]{
40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31,
38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61, 29,
36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27,
34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41, 9, 49, 17, 57, 25
};
for(int i=0;i<resultReverseIP.length;i++){
resultReverseIP[i] = afterCircleTmp[IPReverse[i]-1];
}
return resultReverseIP;
}
//异或操作
public static char[] XorAandB(char[]A,char[]B){
char[]tmpA = A;
char[]tmpB = B;
int []OperateA = trsnChar2Int(tmpA);
int []OperateB = trsnChar2Int(tmpB);
if(OperateA.length != OperateB.length){
return null;
}
char[] XorResult = new char[OperateA.length];
for(int i=0;i<OperateA.length;i++){
int temp = OperateA[i]^OperateB[i];
XorResult[i] = (char) ('0'+temp);
}
return XorResult;
}
//E 扩展
public static char[] FunctionExtension(char[] Ri){
char[] tempRi = Ri;
char[] resultRi = new char[48];
int[] Extension = new int[]{32,1,2,3,4,5,4,5,6,7,8,9,8,9,10,11,12,13,
12,13,14,15,16,17,16,17,18,19,20,21,20,21,22,23,24,25,
24,25,26,27,28,29,28,29,30,31,32,1};
for(int i=0;i<48;i++){
resultRi[i] = tempRi[Extension[i]-1];
}
return resultRi;
}
//加密函数f 置换函数P
public static char[] FunctionPermutation(char[] Sout ){
char[] tempSout = Sout;
char[] resultPout = new char[32];
int [] Permutation = new int[]{16,7,20,21,29,12,28,17,1,15,23,26,5,18,31,10,
2,8,24,14,32,27,3,9,19,13,30,6,22,11,4,25};
for(int i=0;i<32;i++){
resultPout[i] = tempSout[Permutation[i]-1];
}
return resultPout;
}
//加密函数f S盒变换
public static char[] SBoxTrans(char[] E_nor_Ki){
int [][][] Sbox = new int[][][]{
{{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7},
{0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},
{4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},
{15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}},
// S2
{{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10},
{3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},
{0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},
{13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}},
// S3
{{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8},
{13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},
{13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},
{1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}},
// S4
{{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15},
{13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},
{10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},
{ 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}},
// S5
{{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9},
{14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},
{ 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},
{11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}},
// S6
{{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11},
{10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},
{9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},
{4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}},
// S7
{{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1},
{13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},
{1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},
{6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}},
// S8
{{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7},
{1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},
{7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},
{2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}}};
char outBox[] = new char[32];
for(int i=0;i<8;i++){
char[] temp6in = new char[6];
for(int i1=0;i1<6;i1++){
temp6in[i1] = E_nor_Ki[i*6+i1];
}
//System.out.println(temp6in);
int [] tem6in_int = trsnChar2Int(temp6in);
int row = tem6in_int[0]*2+tem6in_int[5];
int column = tem6in_int[1]*8+tem6in_int[2]*4+tem6in_int[3]*2+tem6in_int[4];
int soutInt = Sbox[i][row][column];
String HexSoutmp = Integer.toHexString(soutInt);
char[] binarySoutChar = hexString2binaryString(HexSoutmp).toCharArray();
int [] binarySoutInt = trsnChar2Int(binarySoutChar);
for(int j=0;j<4;j++){
outBox[i*4+j] = (char) ('0'+binarySoutInt[j]);
}
}
return outBox;
}
//F函数
public static char[] EcryptFunction(char[]Ri_1,char[]Ki){
char []tmpRi_1 = Ri_1;
char []tmpKi = Ki;
char[] ExtensionR = FunctionExtension(tmpRi_1);//获得Ri经过E扩展后的数组32-48
//Ri'与Ki异或操作
char [] resultXorAandB = XorAandB(tmpKi,ExtensionR);
char[]resultSBoxTrans = SBoxTrans(resultXorAandB);
char[] FunctionResult = FunctionPermutation(resultSBoxTrans);
return FunctionResult;
}
//DES 16轮加密圈变换
public static char[] EncryptCircleTrans(String IPtxt,ArrayList<char[]> listKi){
char[] IPtxt_tmp = IPtxt.toCharArray();
char []resultOfIP = InitialPermutation(IPtxt_tmp);//明文IP初始置换
char[] afterIPRi = new char[32];
char[] afterIPLi = new char[32];
for(int i=0;i<32;i++){//获得初始L0和R0
afterIPLi[i] = resultOfIP[i];
afterIPRi[i] = resultOfIP[i+32];
}
char[] resultRi = afterIPRi;
char[] resultLi = afterIPLi;
for(int i=0;i<16;i++){//循环16次
char[]resultRitmp = resultRi;
char[]resultLitmp = resultLi;
resultLi = resultRitmp;//Li = Ri-1
char[] FOut = EcryptFunction(resultRitmp,listKi.get(i));
resultRi = XorAandB(resultLitmp,FOut);
}
char[] finalCircleResult = new char[64];
for(int i=0;i<32;i++){
finalCircleResult[i] = resultLi[i];
finalCircleResult[32+i] = resultRi[i];
}
char[] resultEncrypted = ReverseInitialPermutation(finalCircleResult);
return resultEncrypted;
}
//DES 16轮解密圈变换
public static char[] DecryptCircleTrans(String Encrypted,ArrayList<char[]> listKi){
char[] IEncrypted_tmp = Encrypted.toCharArray();
char []resultOfIP = InitialPermutation(IEncrypted_tmp);//密文IP-1逆置换
char[] afterIPRi = new char[32];
char[] afterIPLi = new char[32];
for(int i=0;i<32;i++){//获得初始L16和R16
afterIPLi[i] = resultOfIP[i];
afterIPRi[i] = resultOfIP[i+32];
}
char[] resultRi = afterIPRi;
char[] resultLi = afterIPLi;
for(int i=15;i>=0;i--){//循环16次
char[]resultRitmp = resultRi;
char[]resultLitmp = resultLi;
resultRi = resultLitmp;//Ri-1 = Li
char[] FOut = EcryptFunction(resultLitmp,listKi.get(i));
resultLi = XorAandB(resultRitmp,FOut);
}
char[] finalCircleResult = new char[64];
for(int i=0;i<32;i++){
finalCircleResult[i] = resultLi[i];
finalCircleResult[32+i] = resultRi[i];
}
char[] resultDecrypted = ReverseInitialPermutation(finalCircleResult);
return resultDecrypted;
}