加解密系統(包含DES、RSA等加密算法)

最近和小夥伴一起構建了一個包含仿射、流密碼RC4、流密碼LFSR+JK,DES及RSA的加解密系統。界面包括加解密算法選擇框,加密解密按鈕,加密明文信息框以及解密密文信息框。

完整代碼已經上傳到github上了,裏面的README.md有具體的操作說明教程,需要的同學可以自取,地址:https://github.com/Alexlingl/Cryptology

下面就大致介紹一下這個加解密系統的構建過程。

一、界面的設計與實現:

(一)、界面的設計:

(二)、界面的實現

1、佈局:採用邊框佈局BorderLayout。它會將界面分爲東南西北中四個部分,相應的,我們在北部添加一個Jpanel,作爲按鈕等組件的容器。在東部添加一個JPanel,作爲JScrollPane的容器,呈現待處理的具體信息。在中部添加一個JPanel,也是作爲JScrollPane的容器,不同的是它呈現的是處理後的具體信息。

2、信息框:使用JScrollPane可以實現信息過多時,可以下拉的效果,但是如果我們要在上面展示文字,還需要往上面添加一個JTextArea組件。

3、打開文件功能:調用JFileChoose來實現,點擊後會出現一個從計算機中選擇文件的界面。

4、算法下拉可選框:調用了JComboBox

5、最終的界面實現

 

二、界面監控與後臺:

(一)、“選擇文件”功能的按鈕監控與後臺邏輯實現:

1、首先我們需要給按鈕添加監聽機制

2、接着,我們需要保存獲取的文件

3、最後利用addmessageleft這個方法,把選擇的文件內容展示在待處理的信息框中

 

(二)、可選框的監聽與後臺邏輯實現:

1、首先需要給可選框添加監聽機制

2、其次我們需要記錄可選框中用戶當前所選擇的內容,這裏我定義了一個choosetype來作爲標誌。根據用戶不同的選擇來給這個變量賦值。

 

(三)、加解密按鈕的監聽與後臺邏輯實現:

1、首先還是需要給兩個按鈕添加監聽機制

2、接着我們需要判斷用戶點擊的是“加密”還是“解密”按鈕,並進行不同的處理

3、最後,我們需要根據用戶當前下拉框中選擇的算法來進行相應的處理

以仿射加密爲例來看一下具體的處理過程

首先定義一個臨時存儲數據的動態字符串數組tmp,並調用事先定義好的仿射對象的加密方法encrypt()對文本中的信息一行行地進行加密,加密結果就存放在tmp中。接着我們把tmp傳給MessageWindows對象mw中的processed_text屬性,這個就是處理後的信息。調用WriteStringToFile()方法把加密後的信息輸出到“C:\\Users\\Administrator\\Documents\\仿射密文.txt”這個文件中。最後再調用addmessageright把處理後的信息顯示到右邊的信息顯示框即可。

三、代碼:

界面類

package player3;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.ArrayList;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

 
public class MessageWindows extends JFrame implements Config{
	
	public static ArrayList<String>messageList;
	// 三塊面板,一塊是背景,兩塊是信息顯示界面 
	public JPanel jPanel1,jPanelback2,jPanelback3;
	//兩塊信息顯示界面,分別添加在JPanelback1和JPanelback2上面。直接加載JPanel上會出現大小無法調節等問題
	public JScrollPane jPanel2,jPanel3;
	//文件菜單按鈕
	public JButton mnFile;  
	// 兩個按鈕,一個是加密,一個是解密
	public JButton jButton1, jButton2; 
	//輸出臺
	public JTextArea jTextAreainput,jTextAreaoutput;
	//選擇進行加密的類型
	public int choosetype;
	//待處理的文本
	public static ArrayList<String> text = new ArrayList();
	//待處理的文本
	public static ArrayList<String> processed_text = new ArrayList();

	 
	public MessageWindows() {
		initComp();
		this.choosetype=0;
		messageList=new ArrayList();
	}
	 
	public void initComp() {
		
		this.setTitle("系統消息界面");
		//設置頂級容器的大小,setSize()只對頂級容器有效
		this.setSize(MainWindows_WIDTH,MainWindows_HIGHTH);
		//窗體關閉時結束程序
		this.setDefaultCloseOperation(3);
		//設置窗體居中
		this.setLocationRelativeTo(null);
		this.setResizable(false);
	 
		jPanel1= new JPanel();
		jPanelback2=new JPanel();
		jPanelback3=new JPanel();
		
		//下拉可選框
		String[] choose={"仿射","流密碼RC4","流密碼LFSRJK","DES","RSA"};
		JComboBox box=new JComboBox(choose);
		//三個按鈕
		mnFile= new JButton("選擇文件");
		jButton1= new JButton("加密");
		jButton2= new JButton("解密");
		 
		//設置爲邊界佈局
		this.setLayout(new BorderLayout());
		
		box.setPreferredSize(new Dimension(Button_WIDTH, Button_HIGHTH));
		mnFile.setPreferredSize(new Dimension(Button_WIDTH, Button_HIGHTH));
		jButton1.setPreferredSize(new Dimension(Button_WIDTH, Button_HIGHTH));
		jButton2.setPreferredSize(new Dimension(Button_WIDTH, Button_HIGHTH));
		 
		//在畫板面板添加組件
		jPanel1.add(mnFile);
		jPanel1.add(box);
		jPanel1.add(jButton1);
		jPanel1.add(jButton2);
		jPanel1.setPreferredSize(new Dimension(NorthPanel_WIDTH,NorthPanel_HIGHTH));
		jPanelback2.setPreferredSize(new Dimension(WestPanel_WIDTH,WestPanel_HIGHTH));
		jPanelback3.setPreferredSize(new Dimension(EastPanel_WIDTH,EastPanel_HIGHTH));
		
		//待處理的信息,將選擇的待處理文本顯示到界面上
		jTextAreainput=new JTextArea();
		jPanel2= new JScrollPane(jTextAreainput);
		jPanel2.setBackground(Color.LIGHT_GRAY);
		jPanel2.setBounds(41,34, WestPanel_WIDTH, 194);
		jPanel2.setBorder(BorderFactory.createTitledBorder("待處理的信息"));
		jPanel2.setPreferredSize(new Dimension(WestPanel_WIDTH,WestPanel_HIGHTH));
		
		//處理後的信息,將處理後的文本信息顯示到界面上
		jTextAreaoutput=new JTextArea();
		jPanel3= new JScrollPane(jTextAreaoutput);
		jPanel3.setBackground(Color.LIGHT_GRAY);
		jPanel3.setBounds(41,34, EastPanel_WIDTH, 194);
		jPanel3.setBorder(BorderFactory.createTitledBorder("加/解密後的信息"));
		jPanel3.setPreferredSize(new Dimension(EastPanel_WIDTH,EastPanel_HIGHTH));
		
		jPanelback2.add(jPanel2);
		jPanelback3.add(jPanel3);
		
		//將界面加到佈局上
		this.add(jPanel1,BorderLayout.NORTH);
		this.add(jPanelback2,BorderLayout.WEST);
		this.add(jPanelback3,BorderLayout.EAST);
		  
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		//設置界面可見
		this.setVisible(true);
		 	 
		//爲文件選擇按鈕添加監聽機制
		mnFile.addActionListener(new ActionListener() {
			 
			public void actionPerformed(ActionEvent e) {
				try {
					PlayerMain.openVideo();
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}		 
		});
		
		//爲可選框添加監聽機制
		box.addActionListener(new ButtonListener(this,box));
		//爲按鈕1,2添加監聽機制
		jButton1.addActionListener(new ButtonListener(this));
		jButton2.addActionListener(new ButtonListener(this));
	}
	 
	//將處理信息加到左邊界面的方法
	public void addmessageleft(ArrayList<String> text) throws FileNotFoundException{
		this.text = text;
		jTextAreainput.append("當前進行加/解密的文本\n");
		jTextAreainput.paintImmediately(jTextAreainput.getBounds());
		for(int i=0;i<text.size();i++){
			jTextAreainput.append(text.get(i)+"\n");
			jTextAreainput.paintImmediately(jTextAreainput.getBounds());
		}
	}

	//將處理後的信息加到右邊界面上
	public void addmessageright(ArrayList<String> processed_text) throws FileNotFoundException{
		this.processed_text = processed_text;
		jTextAreaoutput.append("當前加/解密後得到的文本\n");
		jTextAreaoutput.paintImmediately(jTextAreainput.getBounds());
		for(int i=0;i<processed_text.size();i++){
			jTextAreaoutput.append(processed_text.get(i)+"\n");
			jTextAreaoutput.paintImmediately(jTextAreaoutput.getBounds());
		}
	}
	
	//把處理後信息輸入到文本文件中
	 public void WriteStringToFile(ArrayList<String> processed_text,String filepath) throws IOException {
         OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(filepath),"UTF-8");
         for(int i=0;i<processed_text.size();i++){
        	 osw.append(processed_text.get(i)+"\n");
         }
         osw.close();
	 }
}

界面監聽類:

package player3;

//設置按鈕監聽方法ButttonLitener類
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import javax.swing.JComboBox;
import des.DESUtil;
import jklfsr.Jk;
import fangshe.Fangshe;
import rc4.Stream_cipher;
import rsa.RSA;

//實現對JPanel的監聽接口處理
public class ButtonListener implements ActionListener{
	public JComboBox box;
	public MessageWindows mw;
	public Fangshe fs=new Fangshe();
	public RSA rsa=new RSA();
	public Stream_cipher rc4=new Stream_cipher();
	public Jk jk=new Jk();
	public DESUtil des=new DESUtil();
	
	//構造方法一,只需要傳界面對象
	public ButtonListener(MessageWindows mw){
		this.mw=mw;
	}
	//構造方法二,需要傳界面對象和下拉可選框的對象
	public ButtonListener(MessageWindows mw,JComboBox box){
		this.mw=mw;
		this.box=box;
	}
	
	//在console中展示當前文本
	public void showtext(ArrayList<String>text){
		for(int i=0;i<text.size();i++){
			System.out.println(text.get(i));
		}
	}
	
	//當界面發生操作時進行處理
	public void actionPerformed(ActionEvent e) {
		//根據點擊的按鈕做出相應的處理
		if(e.getActionCommand().equals("加密")) {
			//選擇進行仿射加密
			if(mw.choosetype==0){
				ArrayList<String>tmp=new ArrayList();
				for(int i=0;i<mw.text.size();i++){
					tmp.add(fs.encrypt(mw.text.get(i)));
				}
				showtext(tmp);
				mw.processed_text=tmp;
				try {
					//將加密結果輸出到文件
					mw.WriteStringToFile(mw.processed_text, "C:\\Users\\Administrator\\Documents\\仿射密文.txt");
				} catch (IOException e2) {
					// TODO Auto-generated catch block
					e2.printStackTrace();
				}
				try {
					mw.addmessageright(mw.processed_text);
				} catch (FileNotFoundException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
			//選擇流密碼RC4進行加密
			else if(mw.choosetype==1){
				ArrayList<String>tmp=new ArrayList();
				for(int i=0;i<mw.text.size();i++){
					tmp.add(PlayerMain.toBinary(rc4.RC4_encrypt(mw.text.get(i))));	
				}
				showtext(tmp);
				try {
					mw.WriteStringToFile(tmp, "C:\\Users\\Administrator\\Documents\\RC4密文.txt");
				} catch (IOException e2) {
					// TODO Auto-generated catch block
					e2.printStackTrace();
				}
				mw.processed_text=tmp;
				try {
					mw.addmessageright(mw.processed_text);
				} catch (FileNotFoundException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
			//選擇流密碼LFSRJK進行加密
			else if(mw.choosetype==2){
				ArrayList<String>tmp=new ArrayList();
				for(int i=0;i<mw.text.size();i++){
					tmp.add(PlayerMain.toBinary(jk.JK_encrypt(mw.text.get(i))));
				}
				showtext(tmp);
				mw.processed_text=tmp;
				try {
					mw.WriteStringToFile(tmp, "C:\\Users\\Administrator\\Documents\\LFSRJK密文.txt");
				} catch (IOException e2) {
					// TODO Auto-generated catch block
					e2.printStackTrace();
				}
				try {
					mw.addmessageright(mw.processed_text);
				} catch (FileNotFoundException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
			//選擇DES進行加密
			else if(mw.choosetype==3){
				ArrayList<String>tmp=new ArrayList();
				for(int i=0;i<mw.text.size();i++){
					tmp.add(PlayerMain.convertByteToHexString(des.jdkDECENcode(mw.text.get(i))));
				}
				showtext(tmp);
				mw.processed_text=tmp;
				try {
					mw.WriteStringToFile(mw.processed_text, "C:\\Users\\Administrator\\Documents\\DES密文.txt");
				} catch (IOException e2) {
					// TODO Auto-generated catch block
					e2.printStackTrace();
				}
				try {
					mw.addmessageright(mw.processed_text);
				} catch (FileNotFoundException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}		
			//選擇進行RSA加密
			else if(mw.choosetype==4){
				ArrayList<String>tmp=new ArrayList();
				for(int i=0;i<mw.text.size();i++){
					tmp.add(PlayerMain.toBinary(rsa.encryption(mw.text.get(i))));
				}
				showtext(tmp);
				mw.processed_text=tmp;
				try {
					mw.WriteStringToFile(tmp, "C:\\Users\\Administrator\\Documents\\RSA密文.txt");
				} catch (IOException e2) {
					// TODO Auto-generated catch block
					e2.printStackTrace();
				}
				try {
					mw.addmessageright(mw.processed_text);
				} catch (FileNotFoundException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
		}
		//判斷當前點擊的按鈕是不是解密
		else if(e.getActionCommand().equals("解密")) {
			if(mw.choosetype==0){
				ArrayList<String>tmp=new ArrayList();
				for(int i=0;i<mw.text.size();i++){
					tmp.add(fs.deciphering(mw.text.get(i)));
				}
				showtext(tmp);
				mw.processed_text=tmp;
				try {
					mw.addmessageright(mw.processed_text);
				} catch (FileNotFoundException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
			//選擇RC4進行解密
			else if(mw.choosetype==1){
				ArrayList<String>tmp=new ArrayList();
				for(int i=0;i<mw.text.size();i++){
					System.out.println(mw.text.get(i));
					tmp.add(rc4.RC4_encrypt(PlayerMain.BinstrToStr(mw.text.get(i))));
				}
				showtext(tmp);
				mw.processed_text=tmp;
				try {
					mw.addmessageright(mw.processed_text);
				} catch (FileNotFoundException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				
			}
			//選擇流密碼LFSRJK進行解密
			else if(mw.choosetype==2){
				ArrayList<String>tmp=new ArrayList();
				for(int i=0;i<mw.text.size();i++){
					tmp.add(jk.JK_encrypt(PlayerMain.BinstrToStr(mw.text.get(i))));
				}
				showtext(tmp);
				mw.processed_text=tmp;
				try {
					mw.addmessageright(mw.processed_text);
				} catch (FileNotFoundException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
			//選擇DES進行解密
			else if(mw.choosetype==3){
				ArrayList<String>tmp=new ArrayList();
				for(int i=0;i<mw.text.size();i++){
					System.out.println(mw.text.get(i));
					byte[] bytetmp=PlayerMain.convertHexStringToByte(mw.text.get(i));
					tmp.add(new String(des.jdkDECDecode(bytetmp)));
				}
				showtext(tmp);
				mw.processed_text=tmp;
				try {
					mw.addmessageright(mw.processed_text);
				} catch (FileNotFoundException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}	
			//選擇RSA進行解密
			else if(mw.choosetype==4){
				//選擇進行RSA解密
				ArrayList<String>tmp=new ArrayList();
				for(int i=0;i<mw.text.size();i++){
					tmp.add(rsa.decrypt(PlayerMain.BinstrToStr(mw.text.get(i))));
				}
				showtext(tmp);
				mw.processed_text=tmp;
				try {
					mw.addmessageright(mw.processed_text);
				} catch (FileNotFoundException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
			
		}
		//"仿射","流密碼RC4","流密碼LFSRJK","DES","RSA"
		else if(box.getSelectedItem().equals("仿射")) {
			 mw.choosetype=0;
		}
		else if(box.getSelectedItem().equals("流密碼RC4")){
			 mw.choosetype=1;
		}
		else if(box.getSelectedItem().equals("流密碼LFSRJK")){
			mw.choosetype=2;
		}
		else if(box.getSelectedItem().equals("DES")) {
			 mw.choosetype=3;
		}
		else if(box.getSelectedItem().equals("RSA")){
			 mw.choosetype=4;
		}
		
	}
	
}

選擇文件類:

package player3;

import java.io.File;  
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;
  
import javax.swing.JFileChooser;   
    
  
public class PlayerMain {  
	//界面類
    static MessageWindows frame;    
    //待加解密的字符串
    public static ArrayList<String> text = new ArrayList();
    //處理後的字符串
    public static ArrayList<String> processed_text = new ArrayList();
    
    //程序的主函數入口,相當於c++的main函數
    public static void main(String[] args) {  
        //創建主程序界面運行窗體  
        frame=new MessageWindows();  
        frame.setVisible(true);   
    }  
    
    //byte數組轉十六進制字符串
    public static String convertByteToHexString(byte[] bytes) {
    	String result = "";
    	for(int i=0;i<bytes.length; i++) {
    		int temp = bytes[i]&0xff;
    		String tempHex = Integer.toHexString(temp);
    		if(tempHex.length()<2) {
    			result +="0"+tempHex;
    		}
    		else {
    			result += tempHex;
    		}
    	}
    	return result;
    }
    
    //將字符串轉爲二進制流
	public static String toBinary(String str){
	    char[] strChar=str.toCharArray();
	    String result="";
	    for(int i=0;i<strChar.length;i++){
	        result +=Integer.toBinaryString(strChar[i])+ " ";
	    }
	    return result;
	}
	
	private static int[] BinstrToIntArray(String binStr) {       
	        char[] temp=binStr.toCharArray();
	        int[] result=new int[temp.length];   
	        for(int i=0;i<temp.length;i++) {
	            result[i]=temp[i]-48;
	        }
	        return result;
	 }
	    
	 //將二進制轉換成字符
	private static char BinstrToChar(String binStr){
	         int[] temp=BinstrToIntArray(binStr);
	         int sum=0;
	         for(int i=0; i<temp.length;i++){
	             sum +=temp[temp.length-1-i]<<i;
	         }   
	         return (char)sum;
	 }
	 public static String BinstrToStr(String binStr){
	        String[] tempStr=binStr.split(" ");
	        char[] tempChar=new char[tempStr.length];
	        for(int i=0;i<tempStr.length;i++) {
	           tempChar[i]=BinstrToChar(tempStr[i]);
	        }
	        return String.valueOf(tempChar);
	 }
    
    //十六進制字符串轉爲byte數組
	public static byte[] convertHexStringToByte(String str) {
		System.out.println(str);
        if(str == null || str.trim().equals("")) {
            return new byte[0];
        }

        byte[] bytes = new byte[str.length() / 2];
        for(int i = 0; i < str.length() / 2; i++) {
            String subStr = str.substring(i * 2, i * 2 + 2);
            bytes[i] = (byte) Integer.parseInt(subStr, 16);
        }

        return bytes;
    }
      
    //打開文件  
    public static void openVideo() throws IOException {  
        JFileChooser chooser=new JFileChooser();  
        int v=chooser.showOpenDialog(null);  
        if(v==JFileChooser.APPROVE_OPTION){  
            File file=chooser.getSelectedFile(); 
    		ArrayList<String> tmp = new ArrayList();
    		Scanner sc = new Scanner(file);
    		while(sc.hasNextLine()){
    			tmp.add(sc.nextLine());
    		}
    		System.out.println("tmp="+tmp);
    		text = tmp;
            //把選擇的文件傳過去
            frame.addmessageleft(text);
        }  
    }  
}  

 

四、注意事項

(一)、編碼問題:不同加密方式產生的字符各不相同,DES等加密算法加密後生成的字符無論是utf-8還是GBK異或是unicode都沒辦法很好地表示出來。如果直接把DES加密後字符串寫到文本中,會出現亂碼的問題。於是最終我決定把加密後的信息都轉爲二進制字符串進行保存,等待需要解密時再轉爲字符串進行處理。

(二)、JScrollPane必須放在JPanel上面,如果直接放在JFrame的佈局上,會出現無法調節JScrollPane大小的問題。

(三)、外部包的導入與生成

外部包的生成:右擊要生成外部包的包,選擇Export->JAR file

外部包的導入

先把外部包粘貼到lib中

右擊要導入的包,選擇build path即可。導入成功後我們是可以在Referenced Libraries中看到相應的包的

 

這篇博客只講了整個系統的架構實現,具體的算法實現涉及的內容太多,這裏就不展開講了。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章