DES加密算法(对称)
首先来讲,DES加密算法大多数是使用C语言编写的,java有本身的jar包可以调用,本文是利用java模拟C语言函数过程实现的,通俗易懂,仅适宜初学者学习。建议初学者自己模拟编写一遍。
作为一种加密算法。DES加密算法具有很高的安全性,所谓对称就是,加密和解密所使用的的密钥是相同的。入口的参数有三个:data加密解密的数据,key,加密解密使用的密钥,mode(工作模式)。
工作流程图如下:
DES作为一种公开的加密算法,他有公开的置换,代替表,所以利用现代的科技通过穷举也可以完成破解。
明文:0110001101101111011011010111000001110101011101000110010101110010
密钥:0001001100110100010101110111100110011011101111001101111111110001
通过64位char或byte数组来分组模拟。封装可以使用字符串来转为byte流。
本文最末有代码,建议联合代码学习
步骤1:初始置换
//初始置换表IP
private int IP[] ={
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};
初始置换表共64位,每一位代表的数字含义是,将原有密钥中该位置的数字放在现有位置,解释一下,例如第一个数是58,那么也就是取原有密钥的第58位来放在第1位,作为置换后的结果。
m‘=’1111111110111000011101100101011100000000111111110000011010000011
private void permute()// 将M经过IP置换后为m'也就是m2
{
m = M.toCharArray();//置换前
//64位byte模拟转化为String输入,再转化为char数组模拟
m2 = new char[64];//置换后存入
for (int i = 0; i < 64; i++)
{
m2[i] = m[IP[i] - 1];
//取IP数组中的第i个数字,-1是因为数组下标起始为0
}
L0 = Arrays.copyOf(m2, 32);
R0 = Arrays.copyOfRange(m2, 32, 64);
}
将置换后结果分成左右两组L0(前32位),R0(后32位),由于字体大小所以看着可能位数不同但实际是相同的。
L0(32位)= 11111111101110000111011001010111
R0(32位)= 00000000111111110000011010000011
步骤2:生成子密钥
DES加密共执行16次迭代,每次迭代过程的数据长度为48位,因此需要16个48位的子密钥来进行加密。
PC1表为8行7列的表,密钥K经该表置换为56位的数据k’也就是k2,因为密钥的第8,16,24,32,40,48,56,64位为奇偶校验位,所以K的长度实际为56。
private int PC1[] = {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,05,28,20,12,4};
置换函数如下:
private void permuteK()//置换密钥k为k2
{
k = K.toCharArray();//置换前
k2 = new char[56];//用来存储置换后的K
LK = new char[28];//密钥的左组
RK = new char[28];//密钥的右组
for(int i=0;i<56;i++)
{
k2[i] = k[PC1[i]-1];
}
LK = Arrays.copyOf(k2, 28);
RK = Arrays.copyOfRange(k2, 28, 56);
}
接下来是很关键的一个函数,这里我把他命名为shift函数,这个函数的作用就是进行16轮(位移运算+合并置换)进而生成16个48位子密钥
给出移动位数表,含有16个数字,每个数字代表的含义为原有LK和RK同时<<该数字,同样因为是利用char数组存取,所以我们利用字符串拼接的方式进行位移。
private int len []={ 1,1,2,2,2,2,2,2,1,2, 2, 2, 2, 2, 2, 1};
给出置换表PC2
private int PC2[]={14,17,11,24,01,05,
3,28,15,6,21,10,
23,19,12,4,26,8,
16,7,27,20,13,02,
41,52,31,37,47,55,
30,40,51,45,33,48,
44,49,39,56,34,53,
46,42,50,36,29,32};
shift函数
private void shift()
{
String buf="";//用来暂时存取数组
subkey=new char[16][48];//用来存储16个48位子密钥
for(int i=0;i<16;i++)//16轮循环
{
int num=len[i];
if(num==1)//左移长度为1
{
buf = new String(LK,num,28-num);//取LK的第num位到末尾,28-num指的是长度
buf+=LK[0];//将LK的第1位放在字符串的最后
LK=buf.toCharArray();//将模拟位移后的结果赋给LK
buf = new String(RK,num,28-num);
buf+=RK[0];
RK=buf.toCharArray();//RK原理同上
}
else//左移长度为2
{
buf = new String(LK,num,28-num);
buf+=LK[0];buf+=LK[1];//前两位加在字符串的最后
LK=buf.toCharArray();
buf = new String(RK,num,28-num);
buf+=RK[0];buf+=RK[1];
RK=buf.toCharArray();
}
k=(new String(LK)+new String(RK)).toCharArray();//将左右组合并
for(int j=0;j<48;j++)
{
subkey[i][j]=k[PC2[j]-1];
//将置换后的每一位结果存入二维子密钥数组中,置换原理和之前相同,
//当前位的数字为(PC2置换表中该位置的值作为k数组下标)的值
}
}
}
经过16次的位移置换后,16个子密钥已经完成
步骤3:迭代过程
Li和Ri为第i次迭代结果的左半部分和右半部分
每轮的子密钥为subkey[i]。
给出扩展置换表E、八个不同的代替盒以及置换盒P
private int[] E={32,01,02,03,04,05,
04,05,06,07,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,01};
private int Sbox1 [][]={{14,04,13,01,02,15,11,8,03,10,06,12,05,9,0,07},
{00,15,07,04,14,02,13,01,10,06,12,11,9,05,03,8},
{04,01,14,8,13,06,02,11,15,12,9,07,03,10,05,00},
{15,12,8,02,04,9,01,07,05,11,03,14,10,00,06,13}};
private int Sbox2 [][]={{15,01,8,14,06,11,03,04,9,07,02,13,12,00,05,10},
{03,13,04,07,15,02,8,14,12,0,01,10,06,9,11,05},
{00,14,07,11,10,04,13,01,05,8,12,06,9,03,02,15},
{13,8,10,01,03,15,04,02,11,06,07,12,00,05,14,9}};
private int Sbox3 [][]={{10,00,9,14,06,03,15,05,01,13,12,07,11,04,02,8},
{13,07,00,9,03,04,06,10,02,8,05,14,12,11,15,01},
{13,06,04,9,8,15,03,00,11,01,02,12,05,10,14,07},
{01,10,13,00,06,9,8,07,04,15,14,03,11,05,02,12}};
private int Sbox4 [][]={{07,13,14,03,00,06,9,10,01,02,8,05,11,12,04,15},
{13,8,11,05,06,15,00,03,04,07,02,12,01,10,14,9},
{10,06,9,00,12,11,07,13,15,01,03,14,05,02,8,04},
{03,15,00,06,10,01,13,8,9,04,05,11,12,07,02,14}};
private int Sbox5 [][]={{02,12,04,01,07,10,11,06,8,05,03,15,13,00,14,9},
{14,11,02,12,04,07,13,01,05,00,15,10,03,9,8,06},
{04,02,01,11,10,13,07,8,15,9,12,05,06,03,00,14},
{11,8,12,07,01,14,02,13,06,15,00,9,10,04,05,03}};
private int Sbox6 [][]={{12,01,10,15,9,02,06,8,00,13,03,04,14,07,05,11},
{10,15,04,02,07,12,9,05,06,01,13,14,00,11,03,8},
{9,14,15,05,02,8,12,03,07,00,04,10,01,13,11,06},
{04,03,02,12,9,05,15,10,11,14,01,07,06,00,8,13}};
private int Sbox7 [][]={{04,11,02,14,15,00,8,13,03,12,9,07,05,10,06,01},
{13,00,11,07,04,9,01,10,14,03,05,12,02,15,8,06},
{01,04,11,13,12,03,07,14,10,15,06,8,00,05,9,02},
{06,11,13,8,01,04,10,07,9,05,00,15,14,02,03,12}};
private int Sbox8 [][]={{13,02,8,04,06,15,11,01,10,9,03,14,05,00,12,07},
{01,15,13,8,10,03,07,04,12,05,06,11,00,14,9,02},
{07,11,04,01,9,12,14,02,00,06,10,13,15,03,05,8},
{02,01,14,07,04,10,8,13,15,12,9,00,03,05,06,11}};
private int []P={16,07,20,21,29,12,28,17,01,15,23,26,05,18,31,10,
02,8,24,14,32,27,03,9,19,13,30,06,22,11,04,25};
接下来是最关键的也是最核心的部分F函数,首先利用扩展置换表E,每一轮都是对右半部分进行操作,经扩展我们会得到一个48位的Extend与每一轮给定的subkey进行异或运算,然后利用S盒代替,给出的8个S盒是为了缩减原有48位的结果,每个S盒操作6位结果,也就是说第一个盒对1 ~ 6位进行操作,第二个盒对7 ~ 12位进行操作…以此类推。S盒操作过程为将取到的六位的第一位和最后一位组合成二进制数的十进制值作为行,取到的六位的中间四位数组合成二进制数的十进制值作为列。假设S盒取到的六位为:101010,那么取第一位和最后一位为10,此二进制数的十进制值为2,也就是第二行,取中间四位为0101,此二进制数的十进制值为5,那么我就取S盒中的第二行第五列的值转成二进制代替这里的六位结果,S盒中的数字均不超过16,所以转换后的结果为一个最多为四位的二进制数。这里注意要补齐四位
然后将结果与P盒置换。置换完成与Li部分进行异或得出Ri+1,Li变成Ri。
private void F(int n)
{
Extend =new char[48];
for(int i=0;i<48;i++)
{
Extend[i]=R0[E[i]-1];
}
//由于存储方式是char数组,所以异或运算利用for循环代替
for(int i=0;i<48;i++)
{
if(Extend[i]==subkey[n][i])
{
Extend[i]='0';
}
else
{
Extend[i]='1';
}
}
//S盒代替
String in="",ans="";
for(int i=1;i<=48;i++)
{
in+=Extend[i-1];
if(i%6==0&&i/6==1)
{
String row=""+in.charAt(0)+in.charAt(5);
String line=in.substring(1,5);
ans+=String.format("%04d",Integer.parseInt(Integer.toBinaryString(Sbox1[Integer.parseInt(row, 2)][Integer.parseInt(line,2)])));
in="";
}
if(i%6==0&&i/6==2)
{
String row=""+in.charAt(0)+in.charAt(5);
String line=in.substring(1,5);
ans+=String.format("%04d",Integer.parseInt(Integer.toBinaryString(Sbox2[Integer.parseInt(row, 2)][Integer.parseInt(line,2)])));
in="";
}
if(i%6==0&&i/6==3)
{
String row=""+in.charAt(0)+in.charAt(5);
String line=in.substring(1,5);
ans+=String.format("%04d",Integer.parseInt(Integer.toBinaryString(Sbox3[Integer.parseInt(row, 2)][Integer.parseInt(line,2)])));
in="";
}
if(i%6==0&&i/6==4)
{
String row=""+in.charAt(0)+in.charAt(5);
String line=in.substring(1,5);
ans+=String.format("%04d",Integer.parseInt(Integer.toBinaryString(Sbox4[Integer.parseInt(row, 2)][Integer.parseInt(line,2)])));
in="";
}
if(i%6==0&&i/6==5)
{
String row=""+in.charAt(0)+in.charAt(5);
String line=in.substring(1,5);
ans+=String.format("%04d",Integer.parseInt(Integer.toBinaryString(Sbox5[Integer.parseInt(row, 2)][Integer.parseInt(line,2)])));
in="";
}
if(i%6==0&&i/6==6)
{
String row=""+in.charAt(0)+in.charAt(5);
String line=in.substring(1,5);
ans+=String.format("%04d",Integer.parseInt(Integer.toBinaryString(Sbox6[Integer.parseInt(row, 2)][Integer.parseInt(line,2)])));
in="";
}
if(i%6==0&&i/6==7)
{
String row=""+in.charAt(0)+in.charAt(5);
String line=in.substring(1,5);
ans+=String.format("%04d",Integer.parseInt(Integer.toBinaryString(Sbox7[Integer.parseInt(row, 2)][Integer.parseInt(line,2)])));
in="";
}
if(i%6==0&&i/6==8)
{
String row=""+in.charAt(0)+in.charAt(5);
String line=in.substring(1,5);
ans+=String.format("%04d",Integer.parseInt(Integer.toBinaryString(Sbox8[Integer.parseInt(row, 2)][Integer.parseInt(line,2)])));
in="";
}
}
char mid[]=new char[32];//利用mid作为中间存取参数交换L,R以及置换P
//P盒置换,利用mid存放结果
for(int i=0;i<32;i++)
{
mid[i]=ans.charAt(P[i]-1);
}
//将结果mid和L0异或得出R1存入mid
for(int i=0;i<32;i++)
{
if(mid[i]==L0[i])
{
mid[i]='0';
}
else
{
mid[i]='1';
}
}
L0=Arrays.copyOf(R0, 32);//Li+1赋值
R0=Arrays.copyOf(mid, 32);//Ri+1赋值
if(n==15)//由于起始下标为0,所以n==15时,完成16轮迭代
{
return ;
}
else F(n+1);//递归调用共计16次
}
步骤4:逆置换
给出逆置换规则表
private int [] reIP={40,8,48,16,56,24,64,32,
39,07,47,15,55,23,63,31,
38,06,46,14,54,22,62,30,
37,05,45,13,53,21,61,29,
36,04,44,12,52,20,60,28,
35,03,43,11,51,19,59,27,
34,02,42,10,50,18,58,26,
33,01,41,9,49,17,57,25};
将左半部分和右半部分的合并,然后进行置换。
划重点:这里很重要,之前的L15和R15在最后一轮进行交换过,所以当你取左半部分时,实际上是你的R数组,同理右半部分是你的L数组,
逆置换函数如下
private void inverse()
{
String ciphertext="";
for(int i=0;i<64;i++)
{
if(reIP[i]<=32)
{
ciphertext+=""+R0[reIP[i]-1];
}
else
{
ciphertext+=""+L0[reIP[i]-33];
}
}
System.out.println(ciphertext);
}
输入明文为:0110001101101111011011010111000001110101011101000110010101110010
密 钥K为:0001001100110100010101110111100110011011101111001101111111110001
输出密文为0101100000001000001100000000101111001101110101100001100001101000
调用类
import java.util.Scanner;
public class DES无jar包实现
{
public static void main(String[] args)
{
//明文0110001101101111011011010111000001110101011101000110010101110010
//密钥0001001100110100010101110111100110011011101111001101111111110001
Scanner s=new Scanner(System.in);
System.out.print("输入明文为:");
String M = s.nextLine();
System.out.print("密 钥 K为:");
String K=s.nextLine();
DESencrypt des=new DESencrypt(M,K,"encrypt");
System.out.println("输出密文为"+des.text());
//密文0101100000001000001100000000101111001101110101100001100001101000
}
}
实现类
import java.util.Arrays;
public class DESencrypt
{
/*
* DES加密算法 1.所需内容:明文(64位)、密钥K(64位)、IP置换表、PC-1表、PC-2表、扩展置换表E、S-盒1~8、置换表P、逆置换表reIP
* 2.步骤:(1)初始置换(2)生成子密钥(3)迭代过程(4)逆置换
* 3.原理:采取对称加密(加密解密密钥相同)、分组密码(分为两组固定长度)的方式。
*
* by SmallHedgehog
*/
private String M;//明文或者密文
private String K;
//64位密钥
private String mode;//模式
private char m[];// 置换前
private char m2[];// 置换后
private char L0[];
private char R0[];
private char k[];// 置换前存储位置
private char k2 [];// 置换后存储位置
private char LK [] ;
private char RK [] ;
private char subkey[][];//16个子密钥
private char Extend [];
public DESencrypt(String M,String K,String mode)
{
this.M=M;
this.K=K;
this.mode=mode;
}
public String text()
{
if(mode.equals("encrypt"))
{
permute();
permuteK();
shift();
F(0);
return inverse();
}
return "";
}
/*
* 第一步,初始置换。
* 分割为L0(32位)和R0(32位)
*/
// 在该表中值得注意的是,java语言对于开头是0的整数,被解释为8进制,因此08和09是不合法的
private int IP[] ={
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};
private void permute()// 将M经过IP置换后为m'也就是m2
{
m = M.toCharArray();
m2 = new char[64];
for (int i = 0; i < 64; i++)
{
m2[i] =m[IP[i] - 1];
}
L0 = Arrays.copyOf(m2, 32);
R0 = Arrays.copyOfRange(m2, 32, 64);
}
/*
*第二步,生成子密钥。
*DES加密共执行16次迭代,每次迭代过程的数据长度为48位,
*因此需要16个48位的子密钥来进行加密。
*/
//PC1表为8行7列的表,密钥K经该表置换为56位数据k'也就是k2
//因为密钥的第8,16,24,32,40,48,56,64位为奇偶校验位,所以K的真实长度为56
private int PC1[] = {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,05,28,20,12,4};
private void permuteK()//置换密钥k为k2
{
k = K.toCharArray();
k2 =new char[56];
LK = new char[28];
RK = new char[28];
for(int i=0;i<56;i++)
{
k2[i]=k[PC1[i]-1];
}
LK =Arrays.copyOf(k2, 28);
RK =Arrays.copyOfRange(k2, 28, 56);
}
private int PC2[]={14,17,11,24,01,05,
3,28,15,6,21,10,
23,19,12,4,26,8,
16,7,27,20,13,02,
41,52,31,37,47,55,
30,40,51,45,33,48,
44,49,39,56,34,53,
46,42,50,36,29,32};
//移动位数表,轮次 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
private int len []={ 1,1,2,2,2,2,2,2,1,2, 2, 2, 2, 2, 2, 1};
private void shift()
{
String buf="";
subkey=new char[16][48];
for(int i=0;i<16;i++)
{
int num=len[i];
if(num==1)
{
buf = new String(LK,num,28-num);
buf+=LK[0];
LK=buf.toCharArray();
buf = new String(RK,num,28-num);
buf+=RK[0];
RK=buf.toCharArray();
}
else
{
buf = new String(LK,num,28-num);
buf+=LK[0];buf+=LK[1];
LK=buf.toCharArray();
buf = new String(RK,num,28-num);
buf+=RK[0];buf+=RK[1];
RK=buf.toCharArray();
}
k=(new String(LK)+new String(RK)).toCharArray();
for(int j=0;j<48;j++)
{
subkey[i][j]=k[PC2[j]-1];
}
}
}
/*
* 第三步,迭代过程。
* ()内的数字代表下标
* 分别设置L(i)和R(i)为第i次迭代结果的左半部分和右半部分
* 每轮的子密钥为subkey[i]
* 运算规则为L(i)-R(i-1)
*/
//扩展置换表E
private int[] E={32,01,02,03,04,05,
04,05,06,07,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,01};
//8个不同的代替盒
private int Sbox1 [][]={{14,04,13,01,02,15,11,8,03,10,06,12,05,9,0,07},
{00,15,07,04,14,02,13,01,10,06,12,11,9,05,03,8},
{04,01,14,8,13,06,02,11,15,12,9,07,03,10,05,00},
{15,12,8,02,04,9,01,07,05,11,03,14,10,00,06,13}};
private int Sbox2 [][]={{15,01,8,14,06,11,03,04,9,07,02,13,12,00,05,10},
{03,13,04,07,15,02,8,14,12,0,01,10,06,9,11,05},
{00,14,07,11,10,04,13,01,05,8,12,06,9,03,02,15},
{13,8,10,01,03,15,04,02,11,06,07,12,00,05,14,9}};
private int Sbox3 [][]={{10,00,9,14,06,03,15,05,01,13,12,07,11,04,02,8},
{13,07,00,9,03,04,06,10,02,8,05,14,12,11,15,01},
{13,06,04,9,8,15,03,00,11,01,02,12,05,10,14,07},
{01,10,13,00,06,9,8,07,04,15,14,03,11,05,02,12}};
private int Sbox4 [][]={{07,13,14,03,00,06,9,10,01,02,8,05,11,12,04,15},
{13,8,11,05,06,15,00,03,04,07,02,12,01,10,14,9},
{10,06,9,00,12,11,07,13,15,01,03,14,05,02,8,04},
{03,15,00,06,10,01,13,8,9,04,05,11,12,07,02,14}};
private int Sbox5 [][]={{02,12,04,01,07,10,11,06,8,05,03,15,13,00,14,9},
{14,11,02,12,04,07,13,01,05,00,15,10,03,9,8,06},
{04,02,01,11,10,13,07,8,15,9,12,05,06,03,00,14},
{11,8,12,07,01,14,02,13,06,15,00,9,10,04,05,03}};
private int Sbox6 [][]={{12,01,10,15,9,02,06,8,00,13,03,04,14,07,05,11},
{10,15,04,02,07,12,9,05,06,01,13,14,00,11,03,8},
{9,14,15,05,02,8,12,03,07,00,04,10,01,13,11,06},
{04,03,02,12,9,05,15,10,11,14,01,07,06,00,8,13}};
private int Sbox7 [][]={{04,11,02,14,15,00,8,13,03,12,9,07,05,10,06,01},
{13,00,11,07,04,9,01,10,14,03,05,12,02,15,8,06},
{01,04,11,13,12,03,07,14,10,15,06,8,00,05,9,02},
{06,11,13,8,01,04,10,07,9,05,00,15,14,02,03,12}};
private int Sbox8 [][]={{13,02,8,04,06,15,11,01,10,9,03,14,05,00,12,07},
{01,15,13,8,10,03,07,04,12,05,06,11,00,14,9,02},
{07,11,04,01,9,12,14,02,00,06,10,13,15,03,05,8},
{02,01,14,07,04,10,8,13,15,12,9,00,03,05,06,11}};
private int []P={16,07,20,21,29,12,28,17,01,15,23,26,05,18,31,10,
02,8,24,14,32,27,03,9,19,13,30,06,22,11,04,25};
private void F(int n)
{
Extend =new char[48];
for(int i=0;i<48;i++)
{
Extend[i]=R0[E[i]-1];
}
//由于存储方式是char数组,所以异或运算利用for循环代替
for(int i=0;i<48;i++)
{
if(Extend[i]==subkey[n][i])
{
Extend[i]='0';
}
else
{
Extend[i]='1';
}
}
//S盒代替
String in="",ans="";
for(int i=1;i<=48;i++)
{
in+=Extend[i-1];
if(i%6==0&&i/6==1)
{
String row=""+in.charAt(0)+in.charAt(5);
String line=in.substring(1,5);
ans+=String.format("%04d",Integer.parseInt(Integer.toBinaryString(Sbox1[Integer.parseInt(row, 2)][Integer.parseInt(line,2)])));
in="";
}
if(i%6==0&&i/6==2)
{
String row=""+in.charAt(0)+in.charAt(5);
String line=in.substring(1,5);
ans+=String.format("%04d",Integer.parseInt(Integer.toBinaryString(Sbox2[Integer.parseInt(row, 2)][Integer.parseInt(line,2)])));
in="";
}
if(i%6==0&&i/6==3)
{
String row=""+in.charAt(0)+in.charAt(5);
String line=in.substring(1,5);
ans+=String.format("%04d",Integer.parseInt(Integer.toBinaryString(Sbox3[Integer.parseInt(row, 2)][Integer.parseInt(line,2)])));
in="";
}
if(i%6==0&&i/6==4)
{
String row=""+in.charAt(0)+in.charAt(5);
String line=in.substring(1,5);
ans+=String.format("%04d",Integer.parseInt(Integer.toBinaryString(Sbox4[Integer.parseInt(row, 2)][Integer.parseInt(line,2)])));
in="";
}
if(i%6==0&&i/6==5)
{
String row=""+in.charAt(0)+in.charAt(5);
String line=in.substring(1,5);
ans+=String.format("%04d",Integer.parseInt(Integer.toBinaryString(Sbox5[Integer.parseInt(row, 2)][Integer.parseInt(line,2)])));
in="";
}
if(i%6==0&&i/6==6)
{
String row=""+in.charAt(0)+in.charAt(5);
String line=in.substring(1,5);
ans+=String.format("%04d",Integer.parseInt(Integer.toBinaryString(Sbox6[Integer.parseInt(row, 2)][Integer.parseInt(line,2)])));
in="";
}
if(i%6==0&&i/6==7)
{
String row=""+in.charAt(0)+in.charAt(5);
String line=in.substring(1,5);
ans+=String.format("%04d",Integer.parseInt(Integer.toBinaryString(Sbox7[Integer.parseInt(row, 2)][Integer.parseInt(line,2)])));
in="";
}
if(i%6==0&&i/6==8)
{
String row=""+in.charAt(0)+in.charAt(5);
String line=in.substring(1,5);
ans+=String.format("%04d",Integer.parseInt(Integer.toBinaryString(Sbox8[Integer.parseInt(row, 2)][Integer.parseInt(line,2)])));
in="";
}
}
char mid[]=new char[32];//利用mid作为中间存取参数交换L,R以及置换P
//P盒置换,利用mid存放结果
for(int i=0;i<32;i++)
{
mid[i]=ans.charAt(P[i]-1);
}
//将结果mid和L0异或得出R1存入mid
for(int i=0;i<32;i++)
{
if(mid[i]==L0[i])
{
mid[i]='0';
}
else
{
mid[i]='1';
}
}
L0=Arrays.copyOf(R0, 32);
R0=Arrays.copyOf(mid, 32);
if(n==15)//由于起始下标为0,所以n==15时,完成16轮迭代
{
return ;
}
else F(n+1);//递归调用共计16次
}
/*
*第四步,逆置换。
*给定逆置换规则表,输出密文
*/
private int [] reIP={40,8,48,16,56,24,64,32,
39,07,47,15,55,23,63,31,
38,06,46,14,54,22,62,30,
37,05,45,13,53,21,61,29,
36,04,44,12,52,20,60,28,
35,03,43,11,51,19,59,27,
34,02,42,10,50,18,58,26,
33,01,41,9,49,17,57,25};
private String inverse()
{
String ciphertext="";
for(int i=0;i<64;i++)
{
if(reIP[i]<=32)
{
ciphertext+=""+R0[reIP[i]-1];
}
else
{
ciphertext+=""+L0[reIP[i]-33];
}
}
return ciphertext;
}
}