2021.3.29
信息安全课上要求算一个DES的一个流程。
实在不想用手算,于是用Java语言实现了分解功能,特此记录。
算法步骤参考博客:
点击此处
上面博客的图可以说是非常清晰了。
package entrypt_homework;
public class DES {
//起始置换表 长度8X8
public int[] innitial = 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
};
//扩展置换表E 长度6X8
public int[] expandTbE = 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
};
//生成子密钥 pc1表 长度7X8
public int[] pc1 = 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
};
//生成子秘钥 pc2表 长度6X8
public int[] pc2 = 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
};
//生成子秘钥 循环左移轮次表 长度 16
public int[] leftRoundTable = new int[]{
1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1
};
//S1盒
public int[][] s1 = 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盒
public int[][] s2 = new int[][]{
{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盒
public int[][] s3 = new int[][]{
{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盒
public int[][] s4 = new int[][]{
{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盒
public int[][] s5 = new int[][]{
{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盒
public int[][] s6 = new int[][]{
{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
public int[][] s7 = new int[][]{
{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
public int[][] s8 = new int[][]{
{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}
};
//P盒 长度为32
public int[] pbox = 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
};
//逆置置换表
public int[] end = 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
};
/**
* 起始置换,根据置换表,将明文进行置换,记得置换表的数字要减1
* @param plainText
* @return
*/
public String innitialPermutation(String plainText){
char[] plainTextCh = plainText.toCharArray();
char[] permutation = new char[64];
for(int i = 0; i<64 ;i++){
permutation[i] = plainTextCh[innitial[i]-1];
}
String initPlaintext = String.valueOf(permutation);
return initPlaintext;
}
/**
* DES加密,生成子密钥,返回第X轮次的子秘钥。<br/> 因为字符串都是从0开始,所以pc里面的数字都要减1
* @param key 秘钥的字符串
* @param round 生成子秘钥的轮次
* @return
*/
public String roundKeyGenerate(String key,int round){
char[] keyCh = key.toCharArray();
char[] generateOne = new char[56];
for(int i = 0;i<56;i++){
generateOne[i] = keyCh[pc1[i]-1];
}
key = String.valueOf(generateOne);
String c0 = key.substring(0,28);
String d0 = key.substring(28,56);
int bitCount = leftRoundTable[round];
c0 = c0.substring(0+bitCount,28) + c0.substring(0,bitCount);
d0 = d0.substring(0+bitCount,28) + d0.substring(0, bitCount);
String subKey = c0+d0;
char[] subKeyCh = subKey.toCharArray();
char[] generateTwo = new char[48];
for(int i = 0;i<48;i++){
generateTwo[i] = subKeyCh[pc2[i]-1];
}
subKey = String.valueOf(generateTwo);
return subKey;
}
/**
* 扩展置换E,同样的,记得置换表里面的数字-1
* @param Ri 传入Ri
* @return
*/
public String expandChange(String Ri){
char[] RiCh = Ri.toCharArray();
char[] exRiCh = new char[48];
for(int i =0; i<48;i++){
exRiCh[i] = RiCh[expandTbE[i]-1];
}
String ERi = String.valueOf(exRiCh);
return ERi;
}
/**
* ERi 和 Ki 进行异或运算
* @param ERi
* @param Ki
* @return
*/
public String xorCul(String ERi,String Ki){
char[] ERiCh = ERi.toCharArray();
char[] KiCh = Ki.toCharArray();
char[] resCh = new char[48];
for(int i = 0; i<48; i++){
if(ERiCh[i] == KiCh[i]){
resCh[i] = '0';
}else{
resCh[i] = '1';
}
}
String result = String.valueOf(resCh);
return result;
}
/**
* S盒运算,48位得到对照表得到32位
* @param oxrRes 异或运算得到的结果
* @return
*/
public String sboxCul(String oxrRes){
String s1Str = oxrRes.substring(0,6);
String s2Str = oxrRes.substring(6,12);
String s3Str = oxrRes.substring(12,18);
String s4Str = oxrRes.substring(18,24);
String s5Str = oxrRes.substring(24,30);
String s6Str = oxrRes.substring(30,36);
String s7Str = oxrRes.substring(36,42);
String s8Str = oxrRes.substring(42,48);
StringBuilder sb = new StringBuilder();
String column = "";
String row = "";
int colNum = 0;
int rowNum = 0;
int boxNum = 0;
String res = "";
for(int i = 0;i<8;i++){
switch (i){
case 0:
row = s1Str.substring(0,1) + s1Str.substring(5, 6);
column = s1Str.substring(1,5);
colNum = Integer.parseUnsignedInt(column, 2);
rowNum = Integer.parseUnsignedInt(row,2);
boxNum = s1[rowNum][colNum];
break;
case 1:
row = s2Str.substring(0,1) + s1Str.substring(5, 6);
column = s2Str.substring(1,5);
colNum = Integer.parseUnsignedInt(column, 2);
rowNum = Integer.parseUnsignedInt(row,2);
boxNum = s2[rowNum][colNum];
break;
case 2:
row= s3Str.substring(0,1) + s3Str.substring(5, 6);
column= s3Str.substring(1,5);
colNum = Integer.parseUnsignedInt(column, 2);
rowNum = Integer.parseUnsignedInt(row,2);
boxNum = s3[rowNum][colNum];
break;
case 3:
row = s4Str.substring(0,1) + s4Str.substring(5, 6);
column = s4Str.substring(1,5);
colNum = Integer.parseUnsignedInt(column, 2);
rowNum = Integer.parseUnsignedInt(row,2);
boxNum = s4[rowNum][colNum];
break;
case 4:
row = s5Str.substring(0,1) + s5Str.substring(5, 6);
column = s5Str.substring(1,5);
colNum = Integer.parseUnsignedInt(column, 2);
rowNum = Integer.parseUnsignedInt(row,2);
boxNum = s5[rowNum][colNum];
break;
case 5:
row = s6Str.substring(0,1) + s6Str.substring(5, 6);
column = s6Str.substring(1,5);
colNum = Integer.parseUnsignedInt(column, 2);
rowNum = Integer.parseUnsignedInt(row,2);
boxNum = s6[rowNum][colNum];
break;
case 6:
row = s7Str.substring(0,1) + s7Str.substring(5, 6);
column = s7Str.substring(1,5);
colNum = Integer.parseUnsignedInt(column, 2);
rowNum = Integer.parseUnsignedInt(row,2);
boxNum = s7[rowNum][colNum];
break;
case 7:
row = s8Str.substring(0,1) + s8Str.substring(5, 6);
column = s8Str.substring(1,5);
colNum = Integer.parseUnsignedInt(column, 2);
rowNum = Integer.parseUnsignedInt(row,2);
boxNum = s8[rowNum][colNum];
break;
}
//补0
res = Integer.toBinaryString(boxNum);
if(res.length() != 4){
for(int k = res.length(); k<4; k++){
res = "0" + res;
}
}
sb.append(res);
}
String sboxRes = sb.toString();
return sboxRes;
}
/**
* P盒转换
* @param sboxRes sbox的输出结果
* @return
*/
public String pboxCul(String sboxRes){
char[] sboxResCh = sboxRes.toCharArray();
char[] pboxResCh = new char[32];
for(int i = 0;i<32;i++){
pboxResCh[i] = sboxResCh[pbox[i]-1];
}
String pboxRes = String.valueOf(pboxResCh);
return pboxRes;
}
/**
* 迭代最后一步的异或操作,算出Ri+1
* @param pboxRes
* @param Li
* @return
*/
public String xorCul2(String pboxRes,String Li){
char[] pboxResCh = pboxRes.toCharArray();
char[] LiCh = Li.toCharArray();
char[] resCh = new char[32];
for(int i = 0; i<32; i++){
if(pboxResCh[i] == LiCh[i]){
resCh[i] = '0';
}else{
resCh[i] = '1';
}
}
String result = String.valueOf(resCh);
return result;
}
/**
* 终止转换(未实现)
* @return 返回最终结果
*/
public String endPermutation(){
String endResult = null;
return endResult;
}
//明文:00000001 00100011 01000101 01100111 10001001 10101011 11001101 11101111
//秘钥:00000001 00100011 01000101 01100111 10001001 10101011 11001101 11101111
public static void main(String[] args) {
String plainText = "0000000100100011010001010110011110001001101010111100110111101111";
String key = "0000000100100011010001010110011110001001101010111100110111101111";
DES des = new DES();
//计算初始置换
String initPlainText = des.innitialPermutation(plainText);
System.out.println("明文初始置换结果为:"+initPlainText);
//计算L0和R0
String L0 = initPlainText.substring(0,32);
String R0 = initPlainText.substring(32,64);
System.out.println("L0为:"+L0);
System.out.println("R0为:"+R0);
//E(R0)
String ER0 = des.expandChange(R0);
String k1 = des.roundKeyGenerate(key, 0);
System.out.println("E(R0)为:"+ER0);
System.out.println("k1为:"+k1);
// E(R0) 异或 k1
String xorRes1 = des.xorCul(ER0, k1);
System.out.println("E(R0) 异或 k1 结果为:"+xorRes1);
//S盒运算
String sboxRes = des.sboxCul(xorRes1);
System.out.println("S盒运算结果为:"+sboxRes);
//P盒置换
String pboxRes = des.pboxCul(sboxRes);
System.out.println("P盒置换结果为:"+pboxRes);
String R1 = des.xorCul2(pboxRes, L0);
System.out.println("R1为:"+R1);
System.out.println("L1为:"+R0);
}
}