DES加密算法的java实现

来源:互联网 发布:java实现蒲福风级 编辑:程序博客网 时间:2024/05/22 21:57

最近老师留的作业是DES加密算法的实现,作业要求是:输入自己的学号(纯数字),输入4位二进制密钥(重复16次形成64位密钥)。自己用javaGUI写了一个,如下:


工程结构如上图所示:

Hex_to_Binary.java 数据进制转换

IP_Change.java 进行置换运算

LS.java 对数据进行LS移位运算

ModAdd.java 对数据进行模二加法处理

S_box.java 对数据进行S盒处理

DES_Biao.java 主程序在这个函数中

_____________________________________________________________

Hex_to_Binary.java

package Data;public class Hex_to_Binary {// 检测x的string输入是否符合规范,使x只能输入纯数字文本public boolean x_string_test(String test) {byte[] bt;int temp;// 中转变量int logo = -1;// 标志,如果-1,则表示string是一个数串.如果0,则表示不符合规范bt = test.getBytes();// 将string转化成byte数组if ((bt.length > 16) || (bt.length == 0)) {return false;}for (int i = 0; i < bt.length; i++) {temp = bt[i] - 48;// int范围大于byte,所以可以直接赋值,-48可以使数字类型字符变成int型if (temp < 0 || temp > 9)// temp不符合规范表示,string出现了非数字字符{logo = 0;break;// 若发现非数字出现,那么立刻中断查询}}if (logo == -1) {return true;} else {return false;}}// 将一个string转化成64位int数组输出public void hex_to_bianry_64(String test, int x_64[]) {byte[] bt;bt = test.getBytes();int[] it = new int[bt.length];int len, i, j;for (i = bt.length - 1, j = 64; i >= 0; i--) {it[i] = bt[i] - 48;j = j - 4;len = j;switch (it[i]) {case 0:x_64[len] = 0;x_64[len + 1] = 0;x_64[len + 2] = 0;x_64[len + 3] = 0;break;case 1:x_64[len] = 0;x_64[len + 1] = 0;x_64[len + 2] = 0;x_64[len + 3] = 1;break;case 2:x_64[len] = 0;x_64[len + 1] = 0;x_64[len + 2] = 1;x_64[len + 3] = 0;break;case 3:x_64[len] = 0;x_64[len + 1] = 0;x_64[len + 2] = 1;x_64[len + 3] = 1;break;case 4:x_64[len] = 0;x_64[len + 1] = 1;x_64[len + 2] = 0;x_64[len + 3] = 0;break;case 5:x_64[len] = 0;x_64[len + 1] = 1;x_64[len + 2] = 0;x_64[len + 3] = 1;break;case 6:x_64[len] = 0;x_64[len + 1] = 1;x_64[len + 2] = 1;x_64[len + 3] = 0;break;case 7:x_64[len] = 0;x_64[len + 1] = 1;x_64[len + 2] = 1;x_64[len + 3] = 1;break;case 8:x_64[len] = 1;x_64[len + 1] = 0;x_64[len + 2] = 0;x_64[len + 3] = 0;break;case 9:x_64[len] = 1;x_64[len + 1] = 0;x_64[len + 2] = 0;x_64[len + 3] = 1;break;}}for (i = 0; i < j; i++) {x_64[i] = 0;}}// 检测密钥4位是否符合输入规范,要求为0/1的四位数字public boolean k0_test(String test) {int logo = -1;// -1表示符合规范,0表示不符合规范int temp;// 中转变量byte[] bt = test.getBytes();if (bt.length != 4) {return false;}for (int i = 0; i < 4; i++) {temp = bt[i] - 48;if ((temp != 0)) {if (temp != 1) {return false;}}}if (logo == -1) {return true;} else {return false;}}// 将四位二进制密钥转化成64位k0public void k_4_to_64(String test, int k0[]) {byte[] bt;bt = test.getBytes();for (int i = 0; i < 64;) {k0[i] = bt[0] - 48;k0[i + 1] = bt[1] - 48;k0[i + 2] = bt[2] - 48;k0[i + 3] = bt[3] - 48;i = i + 4;}}public void decimal_to_binary(int a, int temp[]) {for (int i = 3; i >= 0; i--) {temp[i] = a % 2;a = a / 2;}}}
IP_Change.java

package Data;public class IP_Change {private int[] IP_0 = 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 };private int[] IP_1 = 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 };private int[] IP_k = 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 };private int[] IP_knew = 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, };private int[] IP_E = 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, };private int[] IP_Final = 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, };// 对64位明文进行初始置换public void IP_first(int x0[], int x1[]) {for (int i = 0; i < 64; i++) {x1[i] = x0[IP_0[i] - 1];}}// 对经过了S盒处理的f(Ri-1,Ki)进行置换操作,从32位的FRKnew置换成32位的Rnewpublic void IP_F(int FRKnew[], int Rnew[]) {for (int i = 0; i < 32; i++) {Rnew[i] = FRKnew[IP_E[i] - 1];}}// 对密钥k0进行PC-1置换,将64位k0置换成56位的PC-1public void IP_k(int k0[], int kpc[]) {for (int i = 0; i < 56; i++) {kpc[i] = k0[IP_k[i] - 1];}}// 用28位的C和D,进行ip置换产生48位的新子密钥public void IP_newk(int C[], int D[], int kn_48[]) {int[] temp = new int[56];// 将C和D数组合成为一个数组,方便计算for (int i = 0; i < 28; i++) {temp[i] = C[i];}for (int i = 28; i < 56; i++) {temp[i] = D[i - 28];}for (int i = 0; i < 48; i++) {kn_48[i] = temp[IP_knew[i] - 1];}}// 位选择函数E,将32长度的R扩展成48位的Republic void ER(int R[], int Re[]) {for (int i = 0; i < 48; i++) {Re[i] = R[IP_E[i] - 1];}}// 最终置换,fx是置换前的数据,XF是置换后的数据public void FIP(int fx[], int XF[]) {for (int i = 0; i < 64; i++) {XF[i] = fx[IP_Final[i] - 1];}}}


LS.java

package Data;public class LS {//C和D都是28位长度的int数组public void LS_CD(int times,int C[],int D[]) {//1,2,9,16则进行一位左移if((times==1)||(times==2)||(times==9)||(times==16)){int temp1 = C[0];int temp2 = D[0];for(int i=0;i<27;i++){C[i]=C[i+1];D[i]=D[i+1];}C[27]=temp1;D[27]=temp1;}//其他均为左移两位else{int temp1 = C[0];int temp2 = D[0];for(int i=0;i<27;i++){C[i]=C[i+1];D[i]=D[i+1];}C[27]=temp1;D[27]=temp1;//执行两次左移一位运算temp1 = C[0];temp2 = D[0];for(int i=0;i<27;i++){C[i]=C[i+1];D[i]=D[i+1];}C[27]=temp1;D[27]=temp1;}}}


ModAdd.java

package Data;public class ModAdd {// 将扩展后的48位R和产生的48位子密钥K进行模2加法public void Mod2(int Re[], int kn_48[], int F_R_K[]) {int temp;for (int i = 0; i < 48; i++) {temp = Re[i] + kn_48[i];switch (temp) {case 0:F_R_K[i] = 0;break;case 1:F_R_K[i] = 1;break;case 2:F_R_K[i] = 0;break;}}}// 将32位的L和32位的Rnew进行模二想加public void Mod2_L_F(int Rnew[], int L[], int LF[]) {int temp;for (int i = 0; i < 32; i++) {temp = L[i] + Rnew[i];switch (temp) {case 0:LF[i] = 0;break;case 1:LF[i] = 1;break;case 2:LF[i] = 0;break;}}}}

S_box.java

package Data;public class S_box {private int[] temp = new int[4];private 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 } };private 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 } };private 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 } };private 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 } };private 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 } };private 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 } };private 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 } };private 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 } };private int[][][] S = new int[][][] { S1, S2, S3, S4, S5, S6, S7, S8 };// 将48位的FRK进行S盒变换,产生32位的FRKnew,每六位为一组进行S盒变换public void SortFRK(int FRK[], int FRKnew[]) {int a;// 记录三维数组的行列int b;for (int i = 0; i < 8; i++) {// 将二进制数转化成十进制a = FRK[6 * i + 0] * 2 + FRK[6 * i + 5] * 1;b = FRK[6 * i + 1] * 8 + FRK[6 * i + 2] * 4 + FRK[6 * i + 3] * 2+ FRK[6 * i + 4] * 1;// 转化S盒中的数字变成四位八进制的new Hex_to_Binary().decimal_to_binary(S[i][a][b], temp);// 赋值FRKnew[i * 4 + 0] = temp[0];FRKnew[i * 4 + 1] = temp[1];FRKnew[i * 4 + 2] = temp[2];FRKnew[i * 4 + 3] = temp[3];}}}

DES_Biao.java

package DES_MainFrame;import java.awt.Color;import java.awt.Font;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import javax.swing.*;import Data.Hex_to_Binary;import Data.IP_Change;import Data.LS;import Data.ModAdd;import Data.S_box;public class DES_Biao {private static JFrame f;private static JLabel l1;private static JLabel l2;private static JLabel l3;private static JLabel l4;private static JTextField x_field;private static JTextField k0_field;private static JLabel x_64_label;private static JLabel k0_64_label;private static JButton start;private static JTextArea res_area;private static Font font = new Font("Dialog", 0, 20);private static Font area_font = new Font("Dialog", 0, 15);private static JScrollPane jres;private static String x0;private static String k0;private static String x0_temp = "";private static String k0_temp = "";private static String xn_temp = "";private static String kn_56_temp = "";private static String kn_48_temp = "";// 放置48位子密钥的stringprivate static int[] x0_64 = new int[64];// 初始64位明文private static int[] k0_64 = new int[64];// 初始64位密钥private static int[] xn_64 = new int[64];// 经过初始置换的64位明文private static int[] kn_56 = new int[56];// 为了产生其他密钥而置换的56位kpcprivate static int[] kn_48 = new int[48];// 计算使用的48位子密钥private static int[] FRK = new int[48];// 48位的RE和48位的子密钥kn_48进行模2加法运算private static String FRKs = "";private static int[] FRKnew = new int[32];// s盒子转化后的32位f结果private static String FRKnews = "";private static int[] Rnew = new int[32];// FRKnew置换后的数据private static String Rnews = "";private static int[] fx = new int[64];// 最后逆置换前的64位存储private static String fxs = "";private static int[] XF = new int[64];private static String XFs = "";// 最终密文private static int[] LF = new int[32];// L和F进行计算private static String LFs = "";private static int[] L = new int[32];private static String Ls = "";private static int[] R = new int[32];private static String Rs = "";private static int[] Re = new int[48];private static String Res = "";private static int[] C = new int[28];private static String Cs = "";private static int[] D = new int[28];private static String Ds = "";public static void main(String[] args) {NewFrame();AddListener();}public static String TString(int b[]) {String a = "";for (int i = 0; i < b.length; i++) {a = a + b[i];}return a;}public static void NewFrame() {f = new JFrame();l1 = new JLabel("明文(请输入学号为例):");l1.setFont(font);l1.setBounds(10, 10, 200, 30);x_field = new JTextField(60);x_field.setBounds(220, 10, 150, 30);x_field.setFont(font);l2 = new JLabel("密钥(四位二进制密钥):");l2.setBounds(380, 10, 200, 30);l2.setFont(font);k0_field = new JTextField(60);k0_field.setBounds(590, 10, 150, 30);k0_field.setFont(font);l3 = new JLabel("64位明文:");l3.setFont(font);l3.setBounds(10, 50, 90, 30);x_64_label = new JLabel("");x_64_label.setFont(font);x_64_label.setText("");x_64_label.setBounds(100, 50, 800, 30);l4 = new JLabel("64位K0:");l4.setFont(font);l4.setBounds(15, 85, 90, 30);k0_64_label = new JLabel("");k0_64_label.setFont(font);k0_64_label.setText("");k0_64_label.setBounds(100, 85, 800, 30);start = new JButton();start.setText("DES");start.setFont(font);start.setBounds(750, 10, 80, 30);res_area = new JTextArea(35, 80);res_area.setLineWrap(true);res_area.setFont(area_font);res_area.setEditable(false);jres = new JScrollPane(res_area);jres.setBounds(15, 130, 800, 500);f.add(l1);f.add(l2);f.add(l3);f.add(l4);f.add(x_field);f.add(k0_field);f.add(x_64_label);f.add(k0_64_label);f.add(start);f.add(jres);f.getContentPane().add(jres);f.setBounds(30, 30, 850, 685);f.setLayout(null);f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);}public static void AddListener() {start.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {boolean test1, test2;// 获取两个文本框的数据x0 = x_field.getText().toString();k0 = k0_field.getText().toString();// 检测输入是否符合规范test1 = new Hex_to_Binary().x_string_test(x0);test2 = new Hex_to_Binary().k0_test(k0);if ((test1 == false) || (test2 == false)) {JOptionPane.showMessageDialog(null, "输入有误!");} else {// 将x0的内容由string转化成64位数组,保存在x0_64// 将k0的内容由string转化成64位数组,保存在k0_64new Hex_to_Binary().hex_to_bianry_64(x0, x0_64);new Hex_to_Binary().k_4_to_64(k0, k0_64);// 将明文进行第一次置换即x0_64转化成xn_64new IP_Change().IP_first(x0_64, xn_64);// 制成string用来显示在界面上x0_temp = TString(x0_64);k0_temp = TString(k0_64);xn_temp = TString(xn_64);// 显示64位明文和密钥x_64_label.setText(x0_temp);k0_64_label.setText(k0_temp);// DES算法显示开始res_area.setText("START:");res_area.append("\n" + "初始IP置换:" + xn_temp);// 为L和R进行第一次赋值for (int i = 0; i < 32; i++) {L[i] = xn_64[i];}for (int i = 32; i < 64; i++) {R[i - 32] = xn_64[i];}Ls = TString(L);Rs = TString(R);res_area.append("\n" + "L:" + Ls);res_area.append("\n" + "R:" + Rs); // 准备C和D数组// 置换k0,并且准备c和d数组,显示他们new IP_Change().IP_k(k0_64, kn_56);kn_56_temp = TString(kn_56);res_area.append("\n" + "K-PC-1:" + kn_56_temp);for (int i = 0; i < 28; i++) {C[i] = kn_56[i];}for (int i = 28; i < 56; i++) {D[i - 28] = kn_56[i];}Cs = TString(C);Ds = TString(D);res_area.append("\n" + "C:" + Cs);res_area.append("\n" + "D:" + Ds);// 开始进行16次循环for (int i = 1; i <= 16; i++) {res_area.append("\n" + "\n" + "*****************第" + i+ "次**********************************");// 将C和D数组进行LS左移运算new LS().LS_CD(i, C, D);Cs = TString(C);Ds = TString(D);res_area.append("\n" + "LS." + i + ".C:" + Cs);res_area.append("\n" + "LS." + i + ".D:" + Ds);// 生成新的子密钥k 48位的new IP_Change().IP_newk(C, D, kn_48);kn_48_temp = TString(kn_48);res_area.append("\n" + "K." + i + ":" + kn_48_temp);// 对R进行扩展,使其从32位扩展到48位new IP_Change().ER(R, Re);Res = TString(Re);res_area.append("\n" + "E." + i + ".R:" + Res);// Re和kn_48进行模2加法运算,产生的结果放置在FRK中new ModAdd().Mod2(Re, kn_48, FRK);FRKs = TString(FRK);res_area.append("\n" + " Mod2(RE." + "K" + "):" + FRKs);// 进行S盒运算new S_box().SortFRK(FRK, FRKnew);FRKnews = TString(FRKnew);res_area.append("\n" + "S盒转化(RE." + "K): " + FRKnews);// 将FRKnew再进行P置换函数操作,生成f(Ri-1,Ki)new IP_Change().IP_F(FRKnew, Rnew);Rnews = TString(Rnew);res_area.append("\n" + "P置换函数后:" + Rnews);// 将L和Rnew进行模二相加new ModAdd().Mod2_L_F(Rnew, L, LF);LFs = TString(LF);res_area.append("\n" + " L与R模二加:  " + LFs);// 让L等于前一个Rfor (int j = 0; j < 32; j++) {L[j] = R[j];}// 让新的R等于LFfor (int t = 0; t < 32; t++) {R[t] = LF[t];}}// R在左侧L在右侧生成finalx,64位for (int u = 0; u < 32; u++) {fx[u] = R[u];}System.out.println("herae");for (int k = 32; k < 64; k++) {fx[k] = L[k - 32];}fxs = TString(fx);res_area.setForeground(Color.RED);res_area.append("\n"+ "\n"+ "\n"+ "*****************最终结果********************************");res_area.append("\n" + "RL数据:" + fxs);// 进行最终置换new IP_Change().FIP(fx, XF);XFs = TString(XF);res_area.append("\n" + "最终密文为:" + XFs+"\n");}}});}}

以上就是DES算法的实现,其中少了奇偶校验位检测的功能,也少了解密的功能,但是加密功能经测试已经实现,上传给大家参考分享一下。