目录
1⃣️前言
des加密解密代码编写属实不易,克服很多了bug,如果想要代码的请先点赞关注一波!!
2⃣️加密解密思路
其实B站很多学习视频都有讲怎么加密的,我这里就不再赘述。
解密思路就是和加密稍微有点不一样,加密的时候有L,R的运算,看下面这张图的思维导图部分,解密的时候就是反过来,把R当成L,L当成R,然后密钥内容不变,密钥使用顺序相反,加密的时候就是Key1到Key16依次使用,解密就是Key16到Key1依次使用
3⃣️Des.java代码(加密解密的代码)
package 实验2.des加密;
import java.security.Key;
import java.util.*;
import static java.lang.Integer.toBinaryString;
import static java.lang.Integer.valueOf;
public class Des {
/**
* 密文
*
*/
private LinkedList<Integer> cipher;
/**
* P盒置换所用矩阵
*
*/
private int[] P_Box = 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
};
/**
* S盒压缩
* s[i][j][k]
* 第i个二维数组
* 第j行,第k列
*/
private static int[][][] S_Box = new int[][][]{
// S1
{
{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}
},
};
/**
* E 扩展置换表
*/
private int[] extension = {
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
};
/**
* 生成密钥所用移位表
*/
private int[] shiftBit = {
1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
};
/**
* 初始置换表
*/
private final int[] initMatrix = {
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 final int[] finalMatrix = {
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
};
/**
* 要加密的数据
*/
private int[] data = {
0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0,
0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1,
0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1,
0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0
};
/**
* 密钥
*/
private int[] key = {
0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0,
0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1,
1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0,
1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1
};
// private int[] key = {
// 0,0,1,1, 0,0,0,1,
// 0,0,1,1, 0,0,1,0,
// 0,0,1,1, 0,0,1,1,
// 0,0,1,1, 0,1,0,0,
// 0,0,1,1, 0,1,0,1,
// 0,0,1,1, 0,1,1,0,
// 0,0,1,1, 0,1,1,1,
// 0,0,1,1, 1,0,0,0
// };
/**
* key置换生成C0,D0矩阵,只有56个元素,剔除了8位校验位
* 转换成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, 5, 28, 20, 12, 4
};
/**
* PC1生成的乱序数据
*/
private int[] res_PC1;
/**
* 后续生成密钥的矩阵
* <p>
* 转换成为48位密钥
*/
private int[] PC2 = {
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
};
/**
* 初始置换之后的结果
*/
private int[] permutation;
private LinkedList<Integer> pertArray;//permutation的ArrayList形式
private LinkedList<Integer> Ri;//Ri的表示
private LinkedList<Integer> Li;//Li的表示
private LinkedHashMap<Integer, LinkedList<Integer>> kMap;//存储了16个密钥
private LinkedList<Integer> plainText;//明文
{
permutation = new int[64];
pertArray = new LinkedList<>();
Li = new LinkedList<>();//L0
Ri = new LinkedList<>();//R0
res_PC1 = new int[PC1.length];
kMap = new LinkedHashMap<>();
}
private void arrayToArrayList() {
for (var item : permutation) {
pertArray.add(item);
}
for (int i = 0; i < pertArray.size() >> 1; i++) {//0~31,<32
Li.add(pertArray.get(i));//Li初始化
Ri.add(pertArray.get(i + 32));//Ri初始化
}
}
public Des() {
generateSubKey();
InitialPermutation();
code();
printCipher();
decode();
printPlainText();
}
/**
* 假定L就是64位的数据
* @param L
*/
public Des(LinkedList<StringBuilder> L,int[] newKey){
generateSubKey();
this.data=new int[64];
this.key=newKey;
for (int i = 0; i < L.size(); i++) {
StringBuilder binaryString=new StringBuilder(L.get(i));
for (int j = 0; j < binaryString.length(); j++) {
data[i*8+j]=binaryString.charAt(j)-'0';
}
}
InitialPermutation();
code();
printCipher();
decode();
printPlainText();
}
/**
* 初始置换
*/
private void InitialPermutation() {
printKey();
for (int i = 0; i < permutation.length; i++) {
permutation[i] = data[initMatrix[i] - 1];//求置换后的数据
}
System.out.println("IP置换前");
print(permutation,8 );
}
/**
* 终止置换
*/
private LinkedList<Integer> FinalPermutation(LinkedList<Integer> list) {
LinkedList<Integer> res=new LinkedList<>();
for (var item : finalMatrix)
{
res.addLast(list.get(item-1));
}
System.out.println("IP^-1后");
print(res, 8);
return res;
}
/**
* 显示密文
*/
public void code() {
arrayToArrayList();//分组
LinkedList<Integer> L,R;
L=Li;
R=Ri;
for (int i = 1; i <= 16; i++) {
LinkedList<Integer> tmp=R;
R=xor(L, ff(R, i));//F函数处理R和第i个密钥,处理返回结果res,res和L异或
L=tmp;
}
R.addAll(L);//L和R合并再次IP逆置换
cipher = FinalPermutation(R);
}
/**
* 生成16个密钥,存储在kMap中
*
*/
private void generateSubKey() {
LinkedList<Integer> C0 = new LinkedList<>();
LinkedList<Integer> D0 = new LinkedList<>();
for (int i = 0; i < PC1.length; i++) {
res_PC1[i] = key[PC1[i] - 1];//数字代表了第几位,所以要-1才能用下标访问
}
/**
* 完成对C0,D0的初始化
*
*
*/
for (int i = 0; i < 28; i++) {
C0.add(res_PC1[i]);
D0.add(res_PC1[i + 28]);
}
/**
* 完成对密钥Ki对逐个加密,一个要生成16个密钥
*
*/
for (int i = 1; i <= 16; i++) {
shiftKRound(C0, shiftBit[i - 1]);//shiftBit是从0开始,计数i是从1开始,所以要-1
shiftKRound(D0, shiftBit[i - 1]);
LinkedList<Integer> kth_Key = new LinkedList<>();
LinkedList<Integer> cd = new LinkedList<>(C0);
cd.addAll(D0);//相当于C0和D0合并了
for (var item : PC2) {
kth_Key.addLast(cd.get(item - 1));
}
kMap.put(i, kth_Key);//i存储密钥Ki
}
}
/**
* 循环左移K次,在生成密钥时使用的函数
*
* @param list
* @param k
*/
private void shiftKRound(LinkedList<Integer> list, int k) {
for (int i = 0; i < k; i++) {
list.add(list.poll());
}
}
/**
* F函数
* 输入的是第i个密钥
*/
private LinkedList<Integer> ff(LinkedList<Integer> a, int i) {
LinkedList<Integer> list = e_transform(a);
list = xor(list, kMap.get(i));//得到异或的结果
list=ss(list);//list指向了被压缩之后第i数据,第i-1就是第k个S盒,k从0~7
list=p_transform(list);
// print(a);
return list;
}
/**
* e扩展置换,32->48
*/
private LinkedList<Integer> e_transform(LinkedList<Integer> a) {
LinkedList<Integer> copy = new LinkedList<>();
for (var item : extension) {
copy.add(a.get(item - 1));
}
System.out.println("E扩展之后");
print(copy, 8);
return copy;
}
/**
* F函数中的异或XOR
* 48 bits -> 48 bits
*/
private LinkedList<Integer> xor(LinkedList<Integer> list, LinkedList<Integer> key) {
LinkedList<Integer> res = new LinkedList<>();
Iterator<Integer> it1 = list.iterator();
Iterator<Integer> it2 = key.iterator();
while (it1.hasNext()) {
Integer i1 = it1.next();
Integer i2 = it2.next();
res.addLast(i1 ^ i2);
}
System.out.println("xor之后");
print(res, 8);
return res;
}
/**
* S盒压缩处理
*
* @param list 是异或完了之后的数据
* @param k 第k个S盒,0<=k<=7
*/
private LinkedList<Integer> ss(LinkedList<Integer> list) {
LinkedList<Integer> compress_ans = new LinkedList<>();
for (int i = 0, k = 0; i < 48 && k < 8; i += 6, ++k) {
Integer i1 = list.get(i), i2 = list.get(i + 1), i3 = list.get(i + 2), i4 = list.get(i + 3), i5 = list.get(i + 4), i6 = list.get(i + 5);
/**
* @row 一个S盒中的行
* @col 一个S盒中的列
*
*/
Integer row = valueOf(i1 + "" + i6, 2);
Integer col = valueOf(i2 + "" + i3 + "" + i4 + "" + i5, 2);
StringBuilder s = new StringBuilder(toBinaryString(S_Box[k][row][col]));
/**
* 防止不足4位的情况发生,所以要把缺少的0补上
*/
while (s.length() < 4) {
s.insert(0, '0');
}
for (int it = 0; it < s.length(); it++) {
compress_ans.addLast(s.charAt(it) - '0');
}
}
System.out.println("S盒变换之后");
print(compress_ans, 8);
return compress_ans;
}
/**
* F函数中的P置换
*/
private LinkedList<Integer> p_transform(LinkedList<Integer> list) {
LinkedList<Integer> res = new LinkedList<>();
for (var item : P_Box)
{
res.addLast(list.get(item - 1));
}
System.out.println("P盒置换");
print(res, 8);
return res;
}
/**
* 解密
*/
public void decode() {
for (int i = 0; i < permutation.length; i++) {
permutation[i] = cipher.get(initMatrix[i] - 1);
}
pertArray = new LinkedList<>();
Li = new LinkedList<>();//L0
Ri = new LinkedList<>();//R0
//不需要重新计算密钥,故不重新new一个LinkedHashMap
arrayToArrayList();
LinkedList<Integer> L=Ri,R=Li;
for (int i = 16; i >= 1; i--) {
LinkedList<Integer> tmp=L;
L=xor(ff(L, i),R);
R=tmp;
}
L.addAll(R);
plainText=FinalPermutation(L);
}
private void printKey() {
for (var item : kMap.entrySet()) {
System.out.printf("第%2d个密钥:", item.getKey());
System.out.print(item.getValue().toString());
System.out.println(",密钥长度:" + item.getValue().size());
}
}
public void printPlainText(){
System.out.println("明文:\n");
int count=0;
for (var item : plainText)
{
System.out.printf("%3d",item);
count++;
if (count==16){
count=0;
System.out.println();
}
}
System.out.println();
}
public void printCipher(){
System.out.println("密文:\n");
int count=0;
for (var item : cipher)
{
System.out.printf("%3d",item);
count++;
if (count==16){
count=0;
System.out.println();
}
}
System.out.println();
}
private static ArrayList<Integer> arrayToArrayList(int[] a) {
ArrayList<Integer> res = new ArrayList<>();
for (var item : a) {
res.add(item);
}
return res;
}
public static void main(String[] args) {
new Des();
}
public LinkedList<Integer> getCipher() {
return cipher;
}
public LinkedList<Integer> getPlainText() {
return plainText;
}
private void print(Collection<?> c,int col){
int i=0,count=0;
for (var item : c)
{
count++;
System.out.print(item+" ");
if (count==col){
count=0;
System.out.println();
}
}
System.out.println("Query OK");
}
private void print(int[] a,int col){
int i=0,count=0;
for (var item : a)
{
count++;
System.out.print(item+" ");
if (count==col){
count=0;
System.out.println();
}
}
System.out.println("Query OK");
}
}
4⃣️Demo.java(图形界面代码)
package 实验2.des加密;
import javax.swing.*;
import java.awt.*;
import java.util.LinkedList;
import static java.lang.Integer.*;
import static java.awt.BorderLayout.*;
public class Demo extends JFrame {
private JLabel inputChL,cipherL,plainTextL,keyL,rightReserve;
private JButton lockjb,unlockjb,clearjb;
private JTextArea inputChArea,cipherTextArea,plainTextArea;
private JTextField keyF;
private JPanel leftP, southP,downP;
private Font kaishu;
private LinkedList<Des> list;
{
downP=new JPanel();
rightReserve=new JLabel("@HWG© All Right Reserved ");
list=new LinkedList<>();
kaishu=new Font(Font.DIALOG_INPUT ,Font.BOLD,12);
keyL=new JLabel("8位密钥");
inputChL=new JLabel("请输入字符");
cipherL=new JLabel("密文");
plainTextL=new JLabel("明文");
lockjb=new JButton("加密