des加密解密代码编写属实不易,克服很多了bug,如果想要代码的请先点赞关注一波!!
其实B站很多学习视频都有讲怎么加密的,我这里就不再赘述。
解密思路就是和加密稍微有点不一样,加密的时候有L,R的运算,看下面这张图的思维导图部分,解密的时候就是反过来,把R当成L,L当成R,然后密钥内容不变,密钥使用顺序相反,加密的时候就是Key1到Key16依次使用,解密就是Key16到Key1依次使用
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"); } }
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("加密