基于Java的三重DES算法实现

代码里面都带有详细的注释,首先是三重DES的加密接口,每一步都是细分,步骤特别清晰(Des1.java):

package com.zmn.main;

/**
 * @author zhuangmingnan
 * DES的接口
 */
public interface Des1 {
	
	// 需要注意的是CFB、OFB模式下是将分组密码转换成流密码,所以没有填充字节的行为,每次只加密一个字符即8个字节
	// ECB、CBC模式如果明文长度l%8 != 0 ,那么系统默认会在最后一个分组补齐64bit,补齐方法是补0
	static final int ECB_MODE = 0;			// 电码本ECB
	static final int CBC_MODE = 1;			// 密码分组链接模式(CBC)
	static final int CFB_MODE = 2;			// 密码反馈模式(CFB)
	static final int OFB_MODE = 3;			// 输出反馈模式(OFB)
	
	// 三重DES加密,指定工作模式,工作在CBC,CFB,OFB三种模式下就需要设置Vi的值
	String TripleDES_Encrypt_GivenMode(String message, String key1, String key2,int mode, String Vi);
	// 三重DES解密,指定工作模式,工作在CBC,CFB,OFB三种模式下就需要设置Vi的值
	String TripleDES_deciphering_GivenMode(String message, String key1, String key2,int mode, String Vi);
	// 将二进制表示的String字符串转成byte[]数组
	String BinaryString2String(String str);
	
// 注释掉的内容均为3DES的实现类的内部调用的私有方法声明,不暴露给用户使用,只提供三重des的加密解密和通用的转化方法给用户
/*	
	// 接收8个字符的字符串,返回64个字符的该字符串表示  
	String get64bitMessage(String message8Character);
	// setp1: 初始置换IP 接收64比特的明文数据,返回初始置换IP后的64比特数据
	String initialPermutate(String byte64Message);	
	// 选择扩展运算E,输入32bit数据,返回48bit的数据
	String selectiveExtensions(String byte32Message);	
	// 密钥编排算法,输入64bit密钥,产生16组48bit子密钥,下标0-15
	String[] produceSubSecretKey(String secret64Key);
	// 循环左移step位,位数不限
	String LS(String message, int step);		
	// 异或运算, 两个操作数位数必须相同
	String exorOperation(String binaryOper1, String binaryOper2);	
	// 选择压缩运算S 输入48bit数据,输出32bit数据
	String selectiveCompressionS(String message48);
	// 置换运算P
	String substituteOperationP(String message32);
	// 交换左右32比特
	String changeLR(String message64);		
	// 初始逆置换IP-1
	String initialInversePermutation(String message64);
	// 在密钥的控制下进行16轮迭代
	String iterate16Round(String byte64Message, String[] secretKey);		
	// F(轮函数)
	String roundFunctionF(String message32, String Currentkey);	
	// DES加密
	String encrypt(String message, String key);
	// DES解密
	String deciphering(String message, String key);	
	// 三重DES加密
	String TripleDES_Encrypt(String message, String key1, String key2);
	// 三重DES解密
	String TripleDES_deciphering(String message, String key1, String key2);
*/
}

接下来是对于上面接口的实现,上面接口中注释的方法都在Des1Impl.java中实现,对外只提供加密、解密和公共的转换方法:

package com.zmn.main;

import com.zmn.table.Table;
import com.zmn.test.TestMethod;

public class Des1Impl implements Des1 {
	
	/* 接收8个字符的字符串,返回64个字符的该字符串表示  */
	private String get64bitMessage(String message8Character) {
		StringBuffer sb = new StringBuffer();
		for(char c : message8Character.toCharArray()){
			String binaryMessage = Integer.toBinaryString(c);
			int length = binaryMessage.length();
			while(length < 8){
				sb.append("0");
				length ++;
			}
			sb.append(binaryMessage);
		}
		return sb.toString();
	}
	
	/* 初始置换IP */
	private String initialPermutate(String byte64Message) {
		char[] charArray = byte64Message.toCharArray();
		for(int i = 0; i < byte64Message.length(); i++){
			charArray[i] = byte64Message.charAt(Table.initialPermutationIP[i] - 1);
		}
		return new String(charArray);
	}
	
	// 选择扩展运算E,输入32bit数据,返回48bit的数据
	private String selectiveExtensions(String byte32Message) {
		StringBuffer sb = new StringBuffer();
		for(int i = 0; i < 48; i ++){
			sb.append(byte32Message.charAt(Table.selectiveExtensionsE[i] - 1));
		}
		return sb.toString();
	}
	
	// 密钥编排算法,输入64bit密钥,产生16组48bit子密钥K,下标0-15
	private String[] produceSubSecretKey(String secret64Key) {
		StringBuffer sb = new StringBuffer();
		for(int i = 0; i < Table.substitutionSelectionPC1.length; i++){
			sb.append(secret64Key.charAt(Table.substitutionSelectionPC1[i] - 1));
		}
		String CD = sb.toString();						// 密钥选择算法1(PC-1)之后产生的CD
		String C = CD.substring(0, CD.length() / 2);	// 左半部分
		String D = CD.substring(CD.length() / 2);		// 右半部分
		
		String[] K = new String[16];						// 16组子密钥,K0-K15
		
		sb.delete(0, sb.length());							// 清空数据,复用sb对象
		
		for(int i = 0; i < 16; i++){
			int moveStep = 2;
			if(i == 1 - 1 || i == 2 - 1 || i == 9 - 1 || i == 16 -1)
				moveStep = 1;
			C = LS(C,moveStep);
			D = LS(D,moveStep);
			CD = C + D;
			
			for(int j = 0; j < Table.substitutionSelectionPC2.length; j++){
				sb.append( CD.charAt( Table.substitutionSelectionPC2[j] - 1 ) );
			}
			
			K[i] = sb.toString();
			sb.delete(0, sb.length());						// 清空数据,复用sb对象
		}
		return K;
	}
	
	// 循环左移step位,位数不限
	private String LS(String message, int step) {
		StringBuffer sb = new StringBuffer();
		for(int i = 0; i < message.length(); i++){
			sb.append(  message.charAt( (i+step)%message.length() )  );
		}
		return sb.toString();
	}
	
	// 异或运算, 两个操作数位数必须相同,返回的数是二进制表示
	private String exorOperation(String binaryOper1, String binaryOper2) {
		StringBuffer sb = new StringBuffer();
		for(int i = 0; i < binaryOper1.length(); i++){
			sb.append( ( (binaryOper1.charAt(i) - '0') + ( binaryOper2.charAt(i) - '0') ) % 2 );			// 异或的操作等同于模2加
		}
		return sb.toString();
	}
	
	// 选择压缩运算S 输入48bit数据,输出32bit数据
	private String selectiveCompressionS(String message48) {
		StringBuffer sb = new StringBuffer();
		String temp = null;
		int row = 0;
		int col = 0;
		for(int i = 0; i < Table.SBox.length; i++){
			row = (message48.charAt(i * 6) - '0')*2 + (message48.charAt(i * 6 + 5) - '0');
			col = (message48.charAt(i * 6 + 1) - '0')*8 + (message48.charAt(i * 6 + 2) - '0')*4 
					+ (message48.charAt(i * 6 + 3) - '0')*2 + (message48.charAt(i * 6 + 4) - '0');
			temp = Integer.toBinaryString(Table.SBox[i][row*16+col]);
			while(temp.length() < 4){
				temp = "0"+temp;
			}
			sb.append(temp);						// 将从S盒取得的数字转换成四位二进制数,后存入sb对象
		}
		return sb.toString();
	}
	
	// 置换运算P
	private String substituteOperationP(String message32) {
		StringBuffer sb = new StringBuffer();
		for(int i = 0; i < Table.substitutionP.length; i++){
			sb.append( message32.charAt(Table.substitutionP[i]-1) );
		}
		return sb.toString();
	}
	
	// 交换左右32比特
	private String changeLR(String message64) {
		StringBuffer sb = new StringBuffer();
		sb.append( message64.substring(message64.length()/2) );
		sb.append( message64.substring(0, message64.length()/2) );
		return sb.toString();
	}
	
	// 初始逆置换IP-1
	private String initialInversePermutation(String message64) {
		StringBuffer sb = new StringBuffer();
		for(int i = 0; i < Table.initialInversePermutationIP.length; i ++){
			sb.append( message64.charAt(Table.initialInversePermutationIP[i]-1) );
		}
		return sb.toString();
	}

	// 在密钥控制下16轮迭代 
	private String iterate16Round(String byte64Message, String[] secretKey) {
		String left32Before = byte64Message.substring(0, byte64Message.length()/2);
		String right32Before = byte64Message.substring(byte64Message.length()/2);
		String left32 = left32Before;
		String right32 = right32Before;
		
		for(int i = 0; i < 16; i++){
			right32 = exorOperation(left32Before, roundFunctionF(right32Before, secretKey[i]));
			left32 = right32Before;
			left32Before = left32;
			right32Before = right32;
		}
		
		return left32 + right32;
	}
	
	// F·轮函数 
	private String roundFunctionF(String message32, String Currentkey) {
		String outputMessage = selectiveExtensions(message32);							// 选择扩展运算E
		outputMessage = exorOperation(outputMessage, Currentkey);						// 选择扩展运算E输出的48bit数据和当前子密钥异或
		outputMessage = selectiveCompressionS(outputMessage);							// 选择压缩运算S
		outputMessage = substituteOperationP(outputMessage);							// 置换运算P
		return outputMessage;
	}
	
	// DES加密
	private String encrypt(String message, String key) {
		String message64 = null;
		StringBuffer sb = new StringBuffer();
		int i = 0;
		String key64 = get64bitMessage(key);
		String[] subKey = produceSubSecretKey(key64);
		
		for(i = 0; (i+7) < message.length(); i+=8){
			message64 = get64bitMessage( message.substring(i, i+8) );
			message64 = initialPermutate(message64);
			message64 = iterate16Round(message64, subKey);
			message64 = changeLR(message64);
			message64 = initialInversePermutation(message64);
			
			sb.append(message64);
		}
		if(i == message.length())
			return BinaryString2String(sb.toString());
		
		String messageLT8Character = message.substring(i);
		for(i = (8 - (message.length() - i) ); i > 0; i--){
			messageLT8Character += "0";
		}
		
		message64 = get64bitMessage( messageLT8Character );
		message64 = initialPermutate(message64);
		message64 = iterate16Round(message64, subKey);
		message64 = changeLR(message64);
		message64 = initialInversePermutation(message64);
		sb.append(message64);
		
		return BinaryString2String(sb.toString());
	}
	
	// DES解密
	private String deciphering(String message, String key) {
		String message64 = null;
		StringBuffer sb = new StringBuffer();
		int i = 0;
		String key64 = get64bitMessage(key);
		String[] subKey = produceSubSecretKey(key64);
		for(i = 0; i < subKey.length/2; i++){
			String temp = subKey[i];
			subKey[i] = subKey[subKey.length - i - 1];
			subKey[subKey.length - i - 1] = temp;
		}
		
		for(i = 0; (i+7) < message.length(); i+=8){
			message64 = get64bitMessage( message.substring(i, i+8) );
			message64 = initialPermutate(message64);
			message64 = iterate16Round(message64, subKey);
			message64 = changeLR(message64);
			message64 = initialInversePermutation(message64);
			
			sb.append(message64);
		}
		if(i == message.length())
			return BinaryString2String(sb.toString());
		TestMethod.printEvery8BitSplitBySpace(sb.toString());
		String messageLT8Character = message.substring(i);
		for(i = (8 - (message.length() - i) ); i > 0; i--){
			messageLT8Character += "0";
		}
		
		message64 = get64bitMessage( messageLT8Character );
		message64 = initialPermutate(message64);
		message64 = iterate16Round(message64, subKey);
		message64 = changeLR(message64);
		message64 = initialInversePermutation(message64);
		sb.append(message64);
		
		return BinaryString2String(sb.toString());
	}
	
	// 三重DES加密
	private String TripleDES_Encrypt(String message, String key1, String key2) {
		String temp = encrypt(message, key1);
		temp = deciphering(temp, key2);
		temp = encrypt(temp, key1);
		return temp;
	}
	
	// 三重DES解密
	private String TripleDES_deciphering(String message, String key1, String key2) {
		String temp = deciphering(message, key1);
		temp = encrypt(temp, key2);
		temp = deciphering(temp, key1);
		return temp;
	}
	
	// 将二进制表示的String字符串转成对应的String字符,将8位二进制转成1位字符
	@Override
	public String BinaryString2String(String str) {
		String binary8String = null;
		StringBuffer sb = new StringBuffer();
		int asciiNumber = 0;
		for(int i = 0; i < str.length()/8 || (str.length() == 8 && i == 0); i++){
			binary8String = str.substring(i*8, i*8+8);
			asciiNumber = 0;
			for(int j = 0; j < binary8String.length(); j++){
				asciiNumber += (binary8String.charAt(j)-'0')*Math.pow(2, (7-j));
			}
			sb.append((char)asciiNumber);
		}
		return sb.toString();
	}
	
	// 三重DES加密,指定工作模式
	@Override
	public String TripleDES_Encrypt_GivenMode(String message, String key1, String key2,int mode, String Vi) {
		StringBuffer sb = new StringBuffer();
		String messageLeft = null;
		String beforeRoundC = Vi;
		String bit8Message = null;
		String beforeRound64BitMessage = null;
		String temp = null;
		String beforeRoundOutput8Bit = null;
		int i = 0;
		
		switch(mode){
		case ECB_MODE:
			return TripleDES_Encrypt(message, key1, key2);
		case CBC_MODE:
			if(Vi == null)
				return "Vi is NULL";
			
			for(i = 0; i < message.length() / 8; i++){
				String message8Character = message.substring(i*8, i*8+8);
				message8Character =	BinaryString2String(exorOperation(get64bitMessage(message8Character), get64bitMessage(beforeRoundC)));
				String outputEncryptMessage = TripleDES_Encrypt(message8Character, key1, key2);
				sb.append( outputEncryptMessage );
				beforeRoundC = outputEncryptMessage;
			}
			if(message.length() % 8 != 0){
				messageLeft = message.substring(i*8);
				int needAddLength = 8 - (message.length() % 8);
				
				while(needAddLength-- > 0)
					messageLeft += '0';
				messageLeft =	BinaryString2String(exorOperation(get64bitMessage(messageLeft), get64bitMessage(beforeRoundC)));
				sb.append( TripleDES_Encrypt(messageLeft, key1, key2) );
			}
			return sb.toString();
		case CFB_MODE:
			if(beforeRoundC == null)
				return "Vi is NULL";
			
			beforeRound64BitMessage = get64bitMessage(Vi);
			bit8Message = get64bitMessage(TripleDES_Encrypt(BinaryString2String(beforeRound64BitMessage), key1, key2)).substring(0, 8);
			temp = Integer.toBinaryString(message.charAt(0));
			while(temp.length() < 8)
				temp = '0' + temp ;
			beforeRoundC = BinaryString2String(exorOperation(temp, bit8Message));
			sb.append(beforeRoundC);
			
			for(i = 1; i < message.length(); i++){
				beforeRound64BitMessage = LS(beforeRound64BitMessage, 8).substring(0, 64-8);
				temp = Integer.toBinaryString(beforeRoundC.charAt(0));
				while(temp.length() < 8)
					temp = '0' + temp ;
				beforeRound64BitMessage += temp;
				bit8Message = get64bitMessage( TripleDES_Encrypt(BinaryString2String(beforeRound64BitMessage), key1, key2) ).substring(0, 8);
				temp = Integer.toBinaryString(message.charAt(i));
				while(temp.length() < 8)
					temp = '0' + temp;
				beforeRoundC = BinaryString2String(exorOperation(temp, bit8Message));
				sb.append(beforeRoundC);
			}
			return sb.toString();
		case OFB_MODE:
			if(beforeRoundC == null)
				return "Vi is NULL";
			
			beforeRound64BitMessage = get64bitMessage(Vi);
			bit8Message = get64bitMessage(TripleDES_Encrypt(BinaryString2String(beforeRound64BitMessage), key1, key2)).substring(0, 8);
			temp = Integer.toBinaryString(message.charAt(0));
			while(temp.length() < 8)
				temp = '0' + temp ;
			beforeRoundOutput8Bit = bit8Message;
			sb.append( BinaryString2String(exorOperation(temp, bit8Message)) );
			
			for(i = 1; i < message.length(); i++){
				beforeRound64BitMessage = LS(beforeRound64BitMessage, 8).substring(0, 64-8);
				beforeRound64BitMessage += beforeRoundOutput8Bit;
				
				bit8Message = get64bitMessage( TripleDES_Encrypt(BinaryString2String(beforeRound64BitMessage), key1, key2) ).substring(0, 8);
				
				temp = Integer.toBinaryString(message.charAt(i));
				while(temp.length() < 8)
					temp = '0' + temp;
				beforeRoundOutput8Bit = bit8Message ;
				
				sb.append(BinaryString2String(exorOperation(temp, bit8Message)));
			}
			return sb.toString();
		}// case statement end===
		return null;
	}
	
	// 三重DES解密,指定工作模式
	@Override
	public String TripleDES_deciphering_GivenMode(String message, String key1, String key2,int mode, String Vi) {
		StringBuffer sb = new StringBuffer();
		String messageLeft = null;
		String beforeRoundC = Vi;
		String bit8Message = null;
		String beforeRound64BitMessage = null;
		String beforeRoundOutput8Bit = null;
		String temp = null;
		int i = 0;
		
		switch(mode){
		case ECB_MODE:
			return TripleDES_deciphering(message, key1, key2);
		case CBC_MODE:
			if(beforeRoundC == null)
				return "Vi is NULL";
			
			for(i = 0; i < message.length() / 8; i++){
				String message8Character = message.substring(i*8, i*8+8);
				String outputDecipheringMessage = TripleDES_deciphering(message8Character, key1, key2);
				message8Character =	BinaryString2String(exorOperation(get64bitMessage(outputDecipheringMessage), get64bitMessage(beforeRoundC)));
				beforeRoundC = message.substring(i*8, i*8+8);
				sb.append(message8Character);
			}
			if(message.length() % 8 != 0){
				messageLeft = message.substring(i*8);
				int needAddLength = 8 - (message.length() % 8);
				
				while(needAddLength-- > 0)
					messageLeft += '0';
				messageLeft =	BinaryString2String(exorOperation(get64bitMessage(messageLeft), get64bitMessage(beforeRoundC)));
				sb.append( TripleDES_deciphering(messageLeft, key1, key2) );
			}
			return sb.toString();
		case CFB_MODE:
			if(beforeRoundC == null)
				return "Vi is NULL";
			
			beforeRound64BitMessage = get64bitMessage(Vi);
			bit8Message = get64bitMessage(TripleDES_Encrypt(BinaryString2String(beforeRound64BitMessage), key1, key2)).substring(0, 8);
			temp = Integer.toBinaryString(message.charAt(0));
			while(temp.length() < 8)
				temp = '0' + temp ;
			beforeRoundC = message.charAt(0)+"";
			sb.append( BinaryString2String(exorOperation(temp, bit8Message)) );
			
			for(i = 1; i < message.length(); i++){
				beforeRound64BitMessage = LS(beforeRound64BitMessage, 8).substring(0, 64-8);
				temp = Integer.toBinaryString(beforeRoundC.charAt(0));
				while(temp.length() < 8)
					temp = '0' + temp ;
				beforeRound64BitMessage += temp;
				bit8Message = get64bitMessage( TripleDES_Encrypt(BinaryString2String(beforeRound64BitMessage), key1, key2) ).substring(0, 8);
				temp = Integer.toBinaryString(message.charAt(i));
				while(temp.length() < 8)
					temp = '0' + temp;
				beforeRoundC = message.charAt(i)+"";
				sb.append( BinaryString2String(exorOperation(temp, bit8Message)));
			}
			return sb.toString();
		case OFB_MODE:
			if(beforeRoundC == null)
				return "Vi is NULL";
			
			beforeRound64BitMessage = get64bitMessage(Vi);
			bit8Message = get64bitMessage(TripleDES_Encrypt(BinaryString2String(beforeRound64BitMessage), key1, key2)).substring(0, 8);
			temp = Integer.toBinaryString(message.charAt(0));
			while(temp.length() < 8)
				temp = '0' + temp ;
			beforeRoundOutput8Bit = bit8Message;
			sb.append( BinaryString2String(exorOperation(temp, bit8Message)) );
			
			for(i = 1; i < message.length(); i++){
				beforeRound64BitMessage = LS(beforeRound64BitMessage, 8).substring(0, 64-8);
				beforeRound64BitMessage += beforeRoundOutput8Bit;
				
				bit8Message = get64bitMessage( TripleDES_Encrypt(BinaryString2String(beforeRound64BitMessage), key1, key2) ).substring(0, 8);
				
				temp = Integer.toBinaryString(message.charAt(i));
				while(temp.length() < 8)
					temp = '0' + temp;
				beforeRoundOutput8Bit = bit8Message ;
				
				sb.append(BinaryString2String(exorOperation(temp, bit8Message)));
			}
			return sb.toString();
		}
		return null;
	}

}

为了方便调试调用,这里用JavaSwing提供了一个简单的友好的用户图形化界面,方便使用,初始选择加密类型的界面类(GraphicsUserInterface.java)

package com.zmn.main;

import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;

public class GraphicsUserInterface extends JFrame{
	
	private static final long serialVersionUID = 8999747999368337069L;
	static int screenWidth = Toolkit.getDefaultToolkit().getScreenSize().width;
	static int screenHeight = Toolkit.getDefaultToolkit().getScreenSize().height;
	static int frmWidth = 300;
	static int frmHeight = 200;
	

	
	public GraphicsUserInterface(){
        JTextField jtf ,message;
        JButton encryptStringBtn, encryptFileBtn;
		setLayout(null);
		
		jtf = new JTextField("请选择加密类型:");
		jtf.setBounds(20, 10, 140, 20);
		jtf.setEditable(false);
		jtf.setBorder(null);
		
		encryptStringBtn = new JButton("加密字符串");
		encryptStringBtn.setBounds(frmWidth/2 - 70, 40, 140, 30);
		encryptStringBtn.addActionListener(new ButtonClickListen());

		encryptFileBtn = new JButton("加密文件");
		encryptFileBtn.setBounds(frmWidth/2 - 70, 80, 140, 30);
        encryptFileBtn.addActionListener(new ButtonClickListen());

        message = new JTextField("加密文件仅支持文本类型!");
        message.setBounds(frmWidth/2 - 70, 120, 140, 20);
        message.setEditable(false);
        message.setBorder(null);

		add(jtf);
		add(encryptStringBtn);
		add(encryptFileBtn);
		add(message);
	}
	
	public static void main(String[] args) {
		GraphicsUserInterface jfrm = new GraphicsUserInterface();
		jfrm.setTitle("三重DES加密软件");
		
		jfrm.setBounds(screenWidth/2 - frmWidth/2 , screenHeight/2 - frmHeight/2, frmWidth, frmHeight);
		
		jfrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		jfrm.setVisible(true);
		
	}

}
class ButtonClickListen implements ActionListener{

    @Override
    public void actionPerformed(ActionEvent e) {
      switch (((JButton)e.getSource()).getText()){
          case "加密字符串":
                StringEncrptFrame stringEncrptFrame = new StringEncrptFrame();
                stringEncrptFrame.setVisible(true);
              break;
          case "加密文件":
              FileEncrptFrame fileEncrptFrame = new FileEncrptFrame();
              fileEncrptFrame.setVisible(true);
              break;
      }
    }
}

接下来分别是对两种加密类型的界面实现和加密实现:

(字符串加密界面)StringEncrptFrame.java

package com.zmn.main;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;

public class StringEncrptFrame extends JFrame{
    private int currentHeight = 10;                                                         // 绝对布局高度控制变量,每次添加一行组件之后该变量要增加添加最大组件的高度+10(两行的间隔)

    private JTextArea EmessageArea,DmessageArea;
    private JTextField key1Input, key2Input, ViInput;
    private JComboBox<String> workModeCbx;
    private JButton encryptBtn, decipheringBtn;
    private Des1 des = new Des1Impl();              // 加密解密用到的对象

    public StringEncrptFrame(){
        int screenWidth = Toolkit.getDefaultToolkit().getScreenSize().width;            // 屏幕宽度
        int screenHeight = Toolkit.getDefaultToolkit().getScreenSize().height;          // 屏幕高度
        int frmWidth = 400;                                                             // 窗口宽度
        int frmHeight = 450;                                                            // 窗口高度

        setBounds((screenWidth - frmWidth)/2, (screenHeight - frmHeight)/2, frmWidth, frmHeight);
        setTitle("字符串加密");
        setLayout(null);
        // 初始化各个组件,初始化界面
        initElement();
        //添加动态监听事件
        addElementListener();

    }

    // 初始化各个组件,初始化界面
    private void initElement(){
        JTextField EmessageField,DmessageField, key1Field, key2Field, workModeField, ViField;

        EmessageField = new JTextField("密文:");
        DmessageField = new JTextField("明文:");
        key1Field = new JTextField("密钥1(8字符):");
        key2Field = new JTextField("密钥2(8字符):");
        ViField = new JTextField("初始向量Vi:");
        workModeField = new JTextField("工作模式:");

        EmessageArea = new JTextArea("input Emessage Here", 5, 30);
        DmessageArea = new JTextArea("input Dmessage here", 5,30);

        key1Input = new JTextField();
        key2Input = new JTextField();
        ViInput = new JTextField();

        encryptBtn = new JButton("加密");
        decipheringBtn = new JButton("解密");

        workModeCbx = new JComboBox<>();
        workModeCbx.addItem("ECB");
        workModeCbx.addItem("CBC");
        workModeCbx.addItem("CFB");
        workModeCbx.addItem("OFB");

        DmessageField.setEditable(false);
        DmessageField.setBorder(null);
        DmessageField.setBounds(20,currentHeight,80,30);

        DmessageArea.setBounds(100,currentHeight,8*30, 30*10);
        DmessageArea.setLineWrap(true);                                 // 自动换行
        DmessageArea.setWrapStyleWord(true);                            // 断行不断字
        JScrollPane dmessageAreaScroll = new JScrollPane(DmessageArea);
        dmessageAreaScroll.setBounds(100,currentHeight,8*30, 30*3);
        dmessageAreaScroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
        currentHeight += dmessageAreaScroll.getHeight()+10;

        key1Field.setEditable(false);
        key1Field.setBorder(null);
        key1Field.setBounds(5,currentHeight,90,30);

        key1Input.setBounds(100,currentHeight,240,30);
        currentHeight += key1Input.getHeight()+10;

        key2Field.setEditable(false);
        key2Field.setBorder(null);
        key2Field.setBounds(5,currentHeight,90,30);

        key2Input.setBounds(100,currentHeight,240,30);
        currentHeight += key2Input.getHeight()+10;

        ViField.setEditable(false);
        ViField.setBorder(null);
        ViField.setBounds(5,currentHeight,80,30);
        ViField.setEditable(false);

        ViInput.setBounds(100,currentHeight,240,30);
        ViInput.setEditable(false);
        currentHeight += ViInput.getHeight()+10;

        EmessageField.setEditable(false);
        EmessageField.setBorder(null);
        EmessageField.setBounds(20,currentHeight,80,30);

        EmessageArea.setBounds(100,currentHeight,8*30, 30*10);
        EmessageArea.setLineWrap(true);                                 // 自动换行
        EmessageArea.setWrapStyleWord(true);                            // 断行不断字
        JScrollPane emessageAreaScroll = new JScrollPane(EmessageArea);
        emessageAreaScroll.setBounds(100,currentHeight,8*30, 30*3);
        emessageAreaScroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
        currentHeight += emessageAreaScroll.getHeight()+10;

        workModeField.setEditable(false);
        workModeField.setBorder(null);
        workModeField.setBounds(20,currentHeight,80,30);

        workModeCbx.setBounds(150,currentHeight,100,30);
        currentHeight += workModeCbx.getHeight()+10;

        encryptBtn.setBounds(100,currentHeight,80,30);

        decipheringBtn.setBounds(210,currentHeight,80,30);
        currentHeight += decipheringBtn.getHeight()+10;

        add(DmessageField);add(dmessageAreaScroll);
        add(key1Field);add(key1Input);
        add(key2Field);add(key2Input);
        add(ViField);add(ViInput);
        add(EmessageField);add(emessageAreaScroll);
        add(workModeField); add(workModeCbx);
        add(encryptBtn);add(decipheringBtn);
    }
    // 增加组件的事件监听者
    private void addElementListener(){
        encryptBtn.addActionListener(new BtnActionListener());
        decipheringBtn.addActionListener(new BtnActionListener());
        workModeCbx.addItemListener(new comBoxChangeListener());
    }

    // 加密/解密 按钮事件监听者类
    class BtnActionListener implements ActionListener{
        @Override
        public void actionPerformed(ActionEvent e) {
            String Emessage = EmessageArea.getText();
            String Dmessage = DmessageArea.getText();
            String key1 = key1Input.getText();
            String key2 = key1Input.getText();
            // 电码本ECB  ECB_MODE = 0;
            // 密码分组链接模式(CBC) CBC_MODE = 1;
            // 密码反馈模式(CFB) CFB_MODE = 2;
            // 输出反馈模式(OFB) OFB_MODE = 3;
            int mode = workModeCbx.getSelectedIndex();
            String Vi = ViInput.getText();

            if(e.getSource() == encryptBtn){
                if(!judgeInputNotNull(0, mode))
                    return ;
                System.out.println("Dmessage:" + Dmessage);
                Emessage = des.TripleDES_Encrypt_GivenMode(Dmessage, key1, key2, mode, Vi);
                EmessageArea.setText(Emessage);
                System.out.println("Emessage:" + Emessage);
            }else if(e.getSource() == decipheringBtn){
                if(!judgeInputNotNull(1, mode))
                    return ;
                System.out.println("Emessage:" + Emessage);
                Dmessage = des.TripleDES_deciphering_GivenMode(Emessage, key1, key2, mode, Vi);
                DmessageArea.setText(Dmessage);
                System.out.println("Dmessage:" + Dmessage);
            }
        }
    }

    // 下拉列表事件监听者类
    class comBoxChangeListener implements ItemListener{

        @Override
        public void itemStateChanged(ItemEvent e) {
            if(e.getSource() == workModeCbx && e.getStateChange() == ItemEvent.SELECTED){
               if(workModeCbx.getSelectedIndex() > 1){
                   ViInput.setEditable(true);
               }else{
                   ViInput.setEditable(false);
               }
            }
        }
    }

    /**
     * 判断加密/解密中,对应的信息是否不为空/正确,给出友好的用户提示信息
     * @param EorD  加密还是解密,0表示加密,1表示解密
     * @param mode  工作模式,由此来判断是否需要Vi作为初始向量 0表示ECB,1表示CBC,2表示CFB,3表示OFB
     * @return  boolean 验证通过返回true,不通过返回false
     */
    private boolean judgeInputNotNull(int EorD, int mode){
        if(EorD == 0)                               // 加密还是解密,0表示加密,1表示解密
            //明文数据没有输入
            if("".equals(DmessageArea.getText()) || DmessageArea.getText() == null){
                JOptionPane.showMessageDialog(null, "请输入明文数据!", "字段空缺",JOptionPane.INFORMATION_MESSAGE);
                return false;
            }
            else
                //密文数据没有输入
                if("".equals(EmessageArea.getText()) || EmessageArea.getText() == null){
                    JOptionPane.showMessageDialog(null, "请输入密文数据!", "字段空缺",JOptionPane.INFORMATION_MESSAGE);
                    return false;
                }
        //key1没有输入
        if("".equals(key1Input.getText()) || key1Input.getText() == null) {
            JOptionPane.showMessageDialog(null, "请输入key1数据!", "字段空缺", JOptionPane.INFORMATION_MESSAGE);
            return false;
        }
        else
            // key1的长度要求是8个字符,此处子密钥要求64bit
            if(key1Input.getText().length() != 8) {
                JOptionPane.showMessageDialog(null, "key1必须是8个字符!", "字段格式错误", JOptionPane.INFORMATION_MESSAGE);
                return false;
            }

        //key2没有输入
        if("".equals(key2Input.getText()) || key2Input.getText() == null){
            JOptionPane.showMessageDialog(null, "请输入key2数据!", "字段空缺", JOptionPane.INFORMATION_MESSAGE);
            return false;
        }
        else
            // key1的长度要求是8个字符,此处子密钥要求64bit
            if(key2Input.getText().length() != 8) {
                JOptionPane.showMessageDialog(null, "key2必须是8个字符!", "字段格式错误", JOptionPane.INFORMATION_MESSAGE);
                return false;
            }
        if(mode >= Des1.CFB_MODE)                  // CFB和OFB都需要Vi作为初始向量
            // Vi没有输入
            if("".equals(ViInput.getText()) || ViInput.getText() == null){
                JOptionPane.showMessageDialog(null, "请输入Vi数据!", "字段空缺", JOptionPane.INFORMATION_MESSAGE);
                return false;
            }
            else
                // Vi的长度要求是8个字符,此处初始向量要求64bit
                if(ViInput.getText().length() != 8) {
                    JOptionPane.showMessageDialog(null, "Vi必须是8个字符!", "字段格式错误", JOptionPane.INFORMATION_MESSAGE);
                    return false;
                }
        return true;
    }
}

(文本文件加密界面)FileEncrptFrame.java

package com.zmn.main;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileEncrptFrame extends JFrame{
    private int currentHeight = 10;                                                         // 绝对布局高度控制变量,每次添加一行组件之后该变量要增加添加最大组件的高度+10(两行的间隔)

    private JTextArea EmessageArea,DmessageArea;
    private JTextField key1Input, key2Input, ViInput;
    private JComboBox<String> workModeCbx;
    private JButton encryptBtn, decipheringBtn;
    private Des1 des = new Des1Impl();              // 加密解密用到的对象

    public FileEncrptFrame(){
        int screenWidth = Toolkit.getDefaultToolkit().getScreenSize().width;            // 屏幕宽度
        int screenHeight = Toolkit.getDefaultToolkit().getScreenSize().height;          // 屏幕高度
        int frmWidth = 400;                                                             // 窗口宽度
        int frmHeight = 450;                                                            // 窗口高度

        setBounds((screenWidth - frmWidth)/2, (screenHeight - frmHeight)/2, frmWidth, frmHeight);
        setTitle("字符串加密");
        setLayout(null);
        // 初始化各个组件,初始化界面
        initElement();
        //添加动态监听事件
        addElementListener();

    }

    // 初始化各个组件,初始化界面
    private void initElement(){
        JTextField EmessageField,DmessageField, key1Field, key2Field, workModeField, ViField;

        EmessageField = new JTextField("密文文件路径:");
        DmessageField = new JTextField("明文文件路径:");
        key1Field = new JTextField("密钥1(8字符):");
        key2Field = new JTextField("密钥2(8字符):");
        ViField = new JTextField("初始向量Vi:");
        workModeField = new JTextField("工作模式:");

        EmessageArea = new JTextArea("input Emessage Here", 5, 30);
        DmessageArea = new JTextArea("input Dmessage here", 5,30);

        key1Input = new JTextField();
        key2Input = new JTextField();
        ViInput = new JTextField();

        encryptBtn = new JButton("加密");
        decipheringBtn = new JButton("解密");

        workModeCbx = new JComboBox<>();
        workModeCbx.addItem("ECB");
        workModeCbx.addItem("CBC");
        workModeCbx.addItem("CFB");
        workModeCbx.addItem("OFB");

        DmessageField.setEditable(false);
        DmessageField.setBorder(null);
        DmessageField.setBounds(10,currentHeight,90,30);

        DmessageArea.setBounds(100,currentHeight,8*30, 30*10);
        DmessageArea.setLineWrap(true);                                 // 自动换行
        DmessageArea.setWrapStyleWord(true);                            // 断行不断字
        JScrollPane dmessageAreaScroll = new JScrollPane(DmessageArea);
        dmessageAreaScroll.setBounds(100,currentHeight,8*30, 30*3);
        dmessageAreaScroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
        currentHeight += dmessageAreaScroll.getHeight()+10;

        key1Field.setEditable(false);
        key1Field.setBorder(null);
        key1Field.setBounds(5,currentHeight,90,30);

        key1Input.setBounds(100,currentHeight,240,30);
        currentHeight += key1Input.getHeight()+10;

        key2Field.setEditable(false);
        key2Field.setBorder(null);
        key2Field.setBounds(5,currentHeight,90,30);

        key2Input.setBounds(100,currentHeight,240,30);
        currentHeight += key2Input.getHeight()+10;

        ViField.setEditable(false);
        ViField.setBorder(null);
        ViField.setBounds(5,currentHeight,80,30);
        ViField.setEditable(false);

        ViInput.setBounds(100,currentHeight,240,30);
        ViInput.setEditable(false);
        currentHeight += ViInput.getHeight()+10;

        EmessageField.setEditable(false);
        EmessageField.setBorder(null);
        EmessageField.setBounds(10,currentHeight,90,30);

        EmessageArea.setBounds(100,currentHeight,8*30, 30*10);
        EmessageArea.setLineWrap(true);                                 // 自动换行
        EmessageArea.setWrapStyleWord(true);                            // 断行不断字
        JScrollPane emessageAreaScroll = new JScrollPane(EmessageArea);
        emessageAreaScroll.setBounds(100,currentHeight,8*30, 30*3);
        emessageAreaScroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
        currentHeight += emessageAreaScroll.getHeight()+10;

        workModeField.setEditable(false);
        workModeField.setBorder(null);
        workModeField.setBounds(20,currentHeight,80,30);

        workModeCbx.setBounds(150,currentHeight,100,30);
        currentHeight += workModeCbx.getHeight()+10;

        encryptBtn.setBounds(100,currentHeight,80,30);

        decipheringBtn.setBounds(210,currentHeight,80,30);
        currentHeight += decipheringBtn.getHeight()+10;

        add(DmessageField);add(dmessageAreaScroll);
        add(key1Field);add(key1Input);
        add(key2Field);add(key2Input);
        add(ViField);add(ViInput);
        add(EmessageField);add(emessageAreaScroll);
        add(workModeField); add(workModeCbx);
        add(encryptBtn);add(decipheringBtn);
    }
    // 增加组件的事件监听者
    private void addElementListener(){
        encryptBtn.addActionListener(new FileEncrptFrame.BtnActionListener());
        decipheringBtn.addActionListener(new FileEncrptFrame.BtnActionListener());
        workModeCbx.addItemListener(new FileEncrptFrame.comBoxChangeListener());
    }

    // 加密/解密 按钮事件监听者类
    class BtnActionListener implements ActionListener{
        @Override
        public void actionPerformed(ActionEvent e) {
            String Emessage = EmessageArea.getText();
            String Dmessage = DmessageArea.getText();
            String key1 = key1Input.getText();
            String key2 = key1Input.getText();
            // 电码本ECB  ECB_MODE = 0;
            // 密码分组链接模式(CBC) CBC_MODE = 1;
            // 密码反馈模式(CFB) CFB_MODE = 2;
            // 输出反馈模式(OFB) OFB_MODE = 3;
            int mode = workModeCbx.getSelectedIndex();
            String Vi = ViInput.getText();
            FileInputStream fin = null;
            FileOutputStream fout = null;
            byte[] b = null;

            if(e.getSource() == encryptBtn){
                if(!judgeInputNotNull(0, mode))
                    return ;
                System.out.println("DmessageLocation:" + Dmessage);
                try {
                    fin = new FileInputStream(Dmessage);
                    fout = new FileOutputStream(Emessage);
                    while (fin.available() > 0) {
                        if (fin.available() > 1024)
                            b = new byte[1024];
                        else
                            b = new byte[fin.available()];

                        fin.read(b);
                        fout.write(des.TripleDES_Encrypt_GivenMode(new String(b), key1, key2, mode, Vi).getBytes());
                    }
                    fin.close();
                    fout.close();
                }catch(IOException e1){
                    JOptionPane.showMessageDialog(null, "加密失败,仅支持文本类型文件加密!", "加密失败", JOptionPane.ERROR_MESSAGE);
                    //e1.printStackTrace();
                    System.out.println(e1.getMessage());
                }
                JOptionPane.showMessageDialog(null, "加密成功!", "成功", JOptionPane.PLAIN_MESSAGE);
                System.out.println("EmessageLocation:" + Emessage);
            }else if(e.getSource() == decipheringBtn){
                if(!judgeInputNotNull(1, mode))
                    return ;
                System.out.println("EmessageLocation:" + Emessage);
                try {
                    fin = new FileInputStream(Emessage);
                    fout = new FileOutputStream(Dmessage);

                    while (fin.available() > 0) {
                        if (fin.available() > 1024)
                            b = new byte[1024];
                        else
                            b = new byte[fin.available()];

                        fin.read(b);
                        fout.write(des.TripleDES_deciphering_GivenMode(new String(b), key1, key2, mode, Vi).getBytes());
                    }
                    fin.close();
                    fout.close();
                }catch(IOException e1){
                    JOptionPane.showMessageDialog(null, "解密失败,仅支持文本类型文件加密!", "解密失败", JOptionPane.ERROR_MESSAGE);
                   // e1.printStackTrace();
                    System.out.println(e1.getMessage());
                }
                JOptionPane.showMessageDialog(null, "解密成功!", "成功", JOptionPane.PLAIN_MESSAGE);
                System.out.println("DmessageLocation:" + Dmessage);
            }
        }
    }

    // 下拉列表事件监听者类
    class comBoxChangeListener implements ItemListener{

        @Override
        public void itemStateChanged(ItemEvent e) {
            if(e.getSource() == workModeCbx && e.getStateChange() == ItemEvent.SELECTED){
                if(workModeCbx.getSelectedIndex() > 1){
                    ViInput.setEditable(true);
                }else{
                    ViInput.setEditable(false);
                }
            }
        }
    }

    /**
     * 判断加密/解密中,对应的信息是否不为空/正确,给出友好的用户提示信息
     * @param EorD  加密还是解密,0表示加密,1表示解密
     * @param mode  工作模式,由此来判断是否需要Vi作为初始向量 0表示ECB,1表示CBC,2表示CFB,3表示OFB
     * @return  boolean 验证通过返回true,不通过返回false
     */
    private boolean judgeInputNotNull(int EorD, int mode){
        if(EorD == 0)                               // 加密还是解密,0表示加密,1表示解密
            //明文数据没有输入
            if("".equals(DmessageArea.getText()) || DmessageArea.getText() == null){
                JOptionPane.showMessageDialog(null, "请输入明文数据!", "字段空缺",JOptionPane.INFORMATION_MESSAGE);
                return false;
            }else{
                File file = new File(DmessageArea.getText());
                if(!file.exists()){
                    JOptionPane.showMessageDialog(null, "明文文件不存在!", "文件未找到",JOptionPane.INFORMATION_MESSAGE);
                    return false;
                }
            }
        else
            //密文数据没有输入
            if("".equals(EmessageArea.getText()) || EmessageArea.getText() == null){
                JOptionPane.showMessageDialog(null, "请输入密文数据!", "字段空缺",JOptionPane.INFORMATION_MESSAGE);
                return false;
            }else{
                File file = new File(EmessageArea.getText());
                if(!file.exists()){
                    JOptionPane.showMessageDialog(null, "密文文件不存在!", "文件未找到",JOptionPane.INFORMATION_MESSAGE);
                    return false;
                }
            }
        //key1没有输入
        if("".equals(key1Input.getText()) || key1Input.getText() == null) {
            JOptionPane.showMessageDialog(null, "请输入key1数据!", "字段空缺", JOptionPane.INFORMATION_MESSAGE);
            return false;
        }
        else
            // key1的长度要求是8个字符,此处子密钥要求64bit
            if(key1Input.getText().length() != 8) {
                JOptionPane.showMessageDialog(null, "key1必须是8个字符!", "字段格式错误", JOptionPane.INFORMATION_MESSAGE);
                return false;
            }

        //key2没有输入
        if("".equals(key2Input.getText()) || key2Input.getText() == null){
            JOptionPane.showMessageDialog(null, "请输入key2数据!", "字段空缺", JOptionPane.INFORMATION_MESSAGE);
            return false;
        }
        else
            // key1的长度要求是8个字符,此处子密钥要求64bit
            if(key2Input.getText().length() != 8) {
                JOptionPane.showMessageDialog(null, "key2必须是8个字符!", "字段格式错误", JOptionPane.INFORMATION_MESSAGE);
                return false;
            }
        if(mode >= Des1.CFB_MODE)                  // CFB和OFB都需要Vi作为初始向量
            // Vi没有输入
            if("".equals(ViInput.getText()) || ViInput.getText() == null){
                JOptionPane.showMessageDialog(null, "请输入Vi数据!", "字段空缺", JOptionPane.INFORMATION_MESSAGE);
                return false;
            }
            else
                // Vi的长度要求是8个字符,此处初始向量要求64bit
                if(ViInput.getText().length() != 8) {
                    JOptionPane.showMessageDialog(null, "Vi必须是8个字符!", "字段格式错误", JOptionPane.INFORMATION_MESSAGE);
                    return false;
                }
        return true;
    }
}

测试工具类(方便调试中间的每一步过程,这里也提供了一个测试工具类,将二进制数据每8bit隔开)TestMetod.java

package com.zmn.test;

/**
 * @author zhuangmingnan
 * 测试工具类
 */
public class TestMethod {
	/* 每8个比特用空白符分割,易于测试 */
	public static void printEvery8BitSplitBySpace(String byteMessage){
		char[] c = byteMessage.toCharArray();
		for(int i = 0; i < byteMessage.length() / 8; i++){
			for(int j = 0 ; j < 8; j ++){
				System.out.print(c[ i * 8 + j]);
			}
			System.out.print(" ");
		}
		System.out.println();
	}
	
}

最后附上DES实现中用到的各种置换表和压缩、拓展表Table.java

package com.zmn.table;

public class Table {
	//初始置换IP表,下标从0-63共64位
	public static int[] initialPermutationIP =
	{
		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
	};

	//初始逆置换IP表,下标从0-63共64位
	public static int[] initialInversePermutationIP = {
		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
	};

	//选择扩展E表,下标从0-47共48位
	public static int[] selectiveExtensionsE = {
		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
	};

	//置换选择PC-1
	public static int[] substitutionSelectionPC1 = {
		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
	};

	//置换选择PC-2
	public static int[] substitutionSelectionPC2 = {
		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
	};
	//S盒
	public static int[][] SBox = {
	{	
		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
	},{
		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
	},{
		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,13,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
	},{
		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
	}, {
		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
	},{
		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
	},{
		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,12,8,1,4,10,7,9,5,0,15,14,2,3,12
	}, {
		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表
	public static int[] substitutionP = {
		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
	};
}

最后附上简单的界面效果图:

212951_SPtI_3481840.png

初始界面

213059_sS2s_3481840.png

加密界面

该实现通过测试能实现基本的加密解密,获取二进制是通过Integer.toBinaryString()方法对字符串逐一生成二进制字符串后连接成64bit数据。

EBC、CBC模式下如果明文长度不是8字符的倍数会在明文后面自动补0以达到需要的分组长度。

该加密解密实现目前只实现字符串的加密解密、文本文件的加密解密,如果对其他类型(特别是二进制类型加密解密会抛出异常,暂未解决)

欢迎大家交流探讨,共同学习!

转载于:https://my.oschina.net/u/3481840/blog/912848

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值