DES算法的Java實現(ECB模式)

一、算法原理概述

參考自老師的PPT

加密過程

1541244158363

1541244631502

初始置換IP

1541244740744

迭代T

1541245001052

Feistel輪函數

1541245200505

子祕鑰生成

1541245413226

逆置換IP-1

1541245475171

解密過程

1541244245356

二、總體結構

class DES{
    //構造函數
	public DES(StringBuffer text, StringBuffer key, int mode) throws Exception {}
	//PKCS5填充處理明文
	public StringBuffer dealText(final StringBuffer origin) {}
	//初始置換IP
	public void start() {
		//把明文或者密文轉換成二進制字符串
		//分組加密或解密
        IP(...);
	}
	//IP置換
	public void IP(final String plaintextBinary) {
		//通過IP置換明文
        //把置換後的明文分爲左右兩塊
        iterationT(...);
	}
	//迭代T
	public void iterationT(StringBuffer L, StringBuffer R) {
		//得到子祕鑰
        getSbuKey(...);
		//16次迭代
        	feistel(...);
		//左右交換
		//逆置換
        //生成字符串明文或密文
        //END!
	}
	//Feistel輪函數
	public StringBuffer feistel(final StringBuffer R, final StringBuffer subKey ) {
		//E擴展
		//異或運算
		//S-Box
		//P置換
	}
	//子祕鑰生成
	public StringBuffer[] getSubKey() {
		//把key轉換爲二進制
		//PC1置換
	    // LS循環16輪生成子密鑰
            // 把左右兩塊合併
            // PC2置換
            // 根據PC2壓縮C0D0,得到子密鑰
	}
    //主函數
    public static void main(String[] args){start();}
}

三、模塊分解

PKCS5填充處理明文

public StringBuffer dealText(final StringBuffer origin) {
		StringBuffer textBinary = new StringBuffer();
		//使用PKCS#5/PKCS7填充
		int max = group*8;
		int padding = max - origin.length();
        for (int i = 0; i < max; ++i) {
        	StringBuffer charBinary;
        	if(i >= origin.length()) {
        		charBinary = new StringBuffer(Integer.toBinaryString(padding));
        	}else
        		charBinary = new StringBuffer(Integer.toBinaryString(origin.charAt(i)));
            while (charBinary.length() < 8) {
            	charBinary.insert(0, 0);
            }
            textBinary.append(charBinary);
        }
        return textBinary;
	}

字符串轉二進制

	public StringBuffer string2Binary(final StringBuffer origin) {
		StringBuffer textBinary = new StringBuffer();
        for (int i = 0; i < origin.length(); ++i) {
        	StringBuffer charBinary = new StringBuffer(Integer.toBinaryString(origin.charAt(i)));
            while (charBinary.length() < 8) {
            	charBinary.insert(0, 0);
            }
            textBinary.append(charBinary);
        }
        return textBinary;
	}

IP置換

	public void IP(final String plaintextBinary) {
		//通過IP置換明文
        StringBuffer substitutePlaintext = new StringBuffer(); // 存儲置換後的明文
        for (int i = 0; i < 64; ++i) {
            substitutePlaintext.append(plaintextBinary.charAt(IP[i] - 1));
        }
        //把置換後的明文分爲左右兩塊
        StringBuffer L = new StringBuffer(substitutePlaintext.substring(0, 32));
        StringBuffer R = new StringBuffer(substitutePlaintext.substring(32));
        iterationT(L, R);
	}

Feistel輪函數

	public StringBuffer feistel(final StringBuffer R, final StringBuffer subKey ) {
		//E擴展
		StringBuffer RExtent = new StringBuffer(); // 存儲擴展後的右邊
        for (int i = 0; i < 48; ++i) {
            RExtent.append(R.charAt(E[i] - 1));
        }
		//異或運算
        for (int i = 0; i < 48; ++i) {
            RExtent.replace(i, i + 1, (RExtent.charAt(i) == subKey.charAt(i)) ? "0" :"1");
        }
		//S-Box
        StringBuffer SBoxString = new StringBuffer();
        for(int i = 0; i < 8; ++i) {
        	String SBoxInput = RExtent.substring(i * 6, (i + 1) * 6);
        	int row = Integer.parseInt(Character.toString(SBoxInput.charAt(0)) + SBoxInput.charAt(5), 2);
            int column = Integer.parseInt(SBoxInput.substring(1, 5), 2);
            
            StringBuffer SBoxOutput = new StringBuffer(Integer.toBinaryString(SBox[i][row * 16 + column]));
            while (SBoxOutput.length() < 4) {
                SBoxOutput.insert(0, 0);
            }
            SBoxString.append(SBoxOutput);
        }
		//P置換
        StringBuffer substituteSBoxString= new StringBuffer(); // 存儲置換後的R
        for (int i = 0; i < 32; ++i) {
        	substituteSBoxString.append(SBoxString.charAt(P[i] - 1));
        }
        return substituteSBoxString;
	}
	

子密鑰生成

//子祕鑰生成
public StringBuffer[] getSubKey() {
	//把key轉換爲二進制
	StringBuffer keyBinary = string2Binary(key);
	
	StringBuffer[] subKey = new StringBuffer[16]; // 存儲子密鑰
	//PC1置換
	StringBuffer C0 = new StringBuffer(); // 存儲密鑰左塊
    StringBuffer D0 = new StringBuffer(); // 存儲密鑰右塊
    for (int i = 0; i < 28; ++i) {
        C0.append(keyBinary.charAt(PC1[i] - 1));
        D0.append(keyBinary.charAt(PC1[i + 28] - 1));
    }
    
    // LS循環16輪生成子密鑰
    for (int i = 0; i < 16; ++i) {
        // 循環左移
    	char mTemp;
        mTemp = C0.charAt(0);
        C0.deleteCharAt(0);
        C0.append(mTemp);
        mTemp = D0.charAt(0);
        D0.deleteCharAt(0);
        D0.append(mTemp);
        if(i != 0 && i != 1 && i != 8 && i != 15) {
        	mTemp = C0.charAt(0);
            C0.deleteCharAt(0);
            C0.append(mTemp);
            mTemp = D0.charAt(0);
            D0.deleteCharAt(0);
            D0.append(mTemp);
        }
        // 把左右兩塊合併
        StringBuffer C0D0 = new StringBuffer(C0.toString() + D0.toString());
        
        // PC2置換
        // 根據PC2壓縮C0D0,得到子密鑰
        StringBuffer C0D0Temp = new StringBuffer();
        for (int j = 0; j < 48; ++j) {
            C0D0Temp.append(C0D0.charAt(PC2[j] - 1));
        }
        subKey[i] = C0D0Temp;
    }
    return subKey;
}

十六次迭代

//迭代T
	public void iterationT(StringBuffer L, StringBuffer R) {
		//得到子祕鑰
		StringBuffer[] subKey = getSubKey();
		//這是解密的子祕鑰
		if(encrypt_decrypt != 0) {
			StringBuffer[] temp = getSubKey();
			for (int i = 0; i < 16; ++i) {
                subKey[i] = temp[15 - i];
            }
		}
		StringBuffer Lbackup = new StringBuffer();
		StringBuffer Rbackup = new StringBuffer();
		Lbackup.replace(0, L.length(), L.toString());
		Rbackup.replace(0, R.length(), R.toString());
		//16次迭代
		for(int i = 0; i < 16; i++) {
			//不能直接用等於號!!!!!
			StringBuffer tempL = new StringBuffer(L);
			StringBuffer tempR = new StringBuffer(R);
			//字符串賦值
			L.replace(0, 32, R.toString());
			StringBuffer feistelString = feistel(tempR, subKey[i]);
			
			for(int j = 0; j < 32; j++) {
				R.replace(j, j + 1, (tempL.charAt(j) == feistelString.charAt(j)) ? "0" :"1");
			}
		}
		
		//左右交換
		StringBuffer RL = new StringBuffer(R.toString() + L.toString());
		//逆置換
		StringBuffer substituteRL = new StringBuffer(); // 存儲置換後的LR
        for (int i = 0; i < 64; ++i) {
            substituteRL.append(RL.charAt(IPReverse[i] - 1));
        }
        //生成字符串明文或密文
        for (int i = 0; i < 8; ++i) {
            String temp = substituteRL.substring(i * 8, (i + 1) * 8);
            //加密
            if(encrypt_decrypt == 0) {
            	ciphertext.append((char) Integer.parseInt(temp, 2));
            	StringBuffer tempHex = new StringBuffer(Integer.toHexString(Integer.parseInt(temp, 2)));
            	while(tempHex.length() < 2) {
            		tempHex.insert(0, "0");
            	}
            	ciphertextHex.append(tempHex + " ");
            //解密
            }else {
            	plaintext.append((char) Integer.parseInt(temp, 2));
            }
            	
        }
        //END!
	}

四、數據結構

StringBuffer plaintext 明文字符串

理論上明文字符串長度可以任意,加密時八個字符(字節)一組,也就是64bit,不夠8個字節一組使用PKCS#5標準填充

假設待加密數據長度爲x,那麼將會在後面padding的字節數目爲8-(x%8),每個padding的字節值是8-(x%8)。

特別地,當待加密數據長度x恰好是8的整數倍,也是要在後面多增加8個字節,每個字節是0x08。

StringBuffer ciphertext 密文字符串

密文字符串只能是8字節的整數倍,因爲它是通過明文加密得到的,如果不是8的整數倍也就不存在明文了

StringBuffer key 密鑰

這裏的密鑰是用字符串表示,不是十六進制!!!

StringBuffer ciphertextHex 密文的十六進制表示
int group 分組數(DES64bit爲一個分組,所以需要根據每組來加密相應的明文)
int encrypt_decrypt 算法模式:0表示加密,其餘表示解密

int[] IP IP置換表
int[] IPReverse IP逆置換表

int[] E E擴展表
int[] P P置換
int[] PC1 PC1置換
int[] PC2 PC2壓縮置換
int[][] SBox 8個S-Box

五、運行結果

運行說明:

主函數分爲兩個部分:加密和解密

加密部分輸入明文,密鑰和算法模式(0表示加密,其餘表示解密),輸出密文

解密部分輸入密文(這裏直接用上面生成的密文,好對比結果),密鑰(與上面同樣的密鑰),算法模式,應該輸出同樣的明文

1540126222637

可以看到確實能夠實現加密再解密得到原數據!

六、源代碼


public class DES {
	private StringBuffer plaintext;
	private StringBuffer ciphertext;
	private StringBuffer key;
	private StringBuffer ciphertextHex;
	private int group;
	//0表示加密,其餘表示解密
	private int encrypt_decrypt;
	//IP置換
	private static final int[] IP = { 
			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逆置換
	private static final int[] IPReverse = { 
			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位選擇表(擴展置換表)
    private static final int[] E = { 
    		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 };
    //P換位表(單純換位表)
    private static final int[] P = { 
    		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 };
    //PC1
    private static final 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 };
    // PC2
    private static final 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 };
    // SBox
    private static final int[][] SBox = {
            // 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 } };
    
    //構造函數
	public DES(StringBuffer text, StringBuffer key, int mode) throws Exception {
		plaintext = new StringBuffer(mode == 0 ? text : "");
		ciphertext = new StringBuffer(mode != 0 ? text : "");
		ciphertextHex = new StringBuffer(mode != 0 ? text : "");
		group = mode == 0 ? (text.length()/8 + 1) : (text.length()/8);//分組
		if(ciphertext.length() % 8!= 0)
			throw new Exception("CipherText is not standard!");
		if(key.length() < 8)
			throw new Exception("Key is not standard!");
		this.key = key;
		encrypt_decrypt = mode;
	}
	//PKCS5填充處理明文
	public StringBuffer dealText(final StringBuffer origin) {
		StringBuffer textBinary = new StringBuffer();
		//使用PKCS#5/PKCS7填充
		int max = group*8;
		int padding = max - origin.length();
        for (int i = 0; i < max; ++i) {
        	StringBuffer charBinary;
        	if(i >= origin.length()) {
        		charBinary = new StringBuffer(Integer.toBinaryString(padding));
        	}else
        		charBinary = new StringBuffer(Integer.toBinaryString(origin.charAt(i)));
            while (charBinary.length() < 8) {
            	charBinary.insert(0, 0);
            }
            textBinary.append(charBinary);
        }
        return textBinary;
	}
	//字符串轉二進制
	public StringBuffer string2Binary(final StringBuffer origin) {
		StringBuffer textBinary = new StringBuffer();
        for (int i = 0; i < origin.length(); ++i) {
        	StringBuffer charBinary = new StringBuffer(Integer.toBinaryString(origin.charAt(i)));
            while (charBinary.length() < 8) {
            	charBinary.insert(0, 0);
            }
            textBinary.append(charBinary);
        }
        return textBinary;
	}
	//初始置換IP
	public void start() {
		//把明文或者密文轉換成二進制字符串
		StringBuffer plaintextBinary = new StringBuffer();
		if(encrypt_decrypt == 0)
			//使用PKCS#5/PKCS7填充
			plaintextBinary = dealText(plaintext);
		else {
			//解析字符密文
			plaintextBinary = string2Binary(ciphertext);
		}
		//分組加密或解密
		int loop = group;
        for(int i = 0; i < loop; i++) {
        	group--;
        	IP(plaintextBinary.subSequence(i*64, (i + 1)*64).toString());
        }
	}
	//IP置換
	public void IP(final String plaintextBinary) {
		//通過IP置換明文
        StringBuffer substitutePlaintext = new StringBuffer(); // 存儲置換後的明文
        for (int i = 0; i < 64; ++i) {
            substitutePlaintext.append(plaintextBinary.charAt(IP[i] - 1));
        }
        //把置換後的明文分爲左右兩塊
        StringBuffer L = new StringBuffer(substitutePlaintext.substring(0, 32));
        StringBuffer R = new StringBuffer(substitutePlaintext.substring(32));
        iterationT(L, R);
	}
	//迭代T
	public void iterationT(StringBuffer L, StringBuffer R) {
		//得到子祕鑰
		StringBuffer[] subKey = getSubKey();
		//這是解密的子祕鑰
		if(encrypt_decrypt != 0) {
			StringBuffer[] temp = getSubKey();
			for (int i = 0; i < 16; ++i) {
                subKey[i] = temp[15 - i];
            }
		}
		StringBuffer Lbackup = new StringBuffer();
		StringBuffer Rbackup = new StringBuffer();
		Lbackup.replace(0, L.length(), L.toString());
		Rbackup.replace(0, R.length(), R.toString());
		//16次迭代
		for(int i = 0; i < 16; i++) {
			//不能直接用等於號!!!!!
			StringBuffer tempL = new StringBuffer(L);
			StringBuffer tempR = new StringBuffer(R);
			//字符串賦值
			L.replace(0, 32, R.toString());
			StringBuffer feistelString = feistel(tempR, subKey[i]);
			
			for(int j = 0; j < 32; j++) {
				R.replace(j, j + 1, (tempL.charAt(j) == feistelString.charAt(j)) ? "0" :"1");
			}
		}
		
		//左右交換
		StringBuffer RL = new StringBuffer(R.toString() + L.toString());
		//逆置換
		StringBuffer substituteRL = new StringBuffer(); // 存儲置換後的LR
        for (int i = 0; i < 64; ++i) {
            substituteRL.append(RL.charAt(IPReverse[i] - 1));
        }
        //刪除多餘字符
        if(group == 0) {
        	String temp = substituteRL.substring(56, 64);
        }
        //生成字符串明文或密文
        for (int i = 0; i < 8; ++i) {
            String temp = substituteRL.substring(i * 8, (i + 1) * 8);
            //加密
            if(encrypt_decrypt == 0) {
            	ciphertext.append((char) Integer.parseInt(temp, 2));
            	StringBuffer tempHex = new StringBuffer(Integer.toHexString(Integer.parseInt(temp, 2)));
            	while(tempHex.length() < 2) {
            		tempHex.insert(0, "0");
            	}
            	ciphertextHex.append(tempHex + " ");
            //解密
            }else {
            	if(group == 0 && 7 - i < Integer.parseInt(substituteRL.substring(56, 64), 2)) {
            		break;
            	}
            	plaintext.append((char) Integer.parseInt(temp, 2));
            }
            	
        }
        //END!
	}
	
	//Feistel輪函數
	public StringBuffer feistel(final StringBuffer R, final StringBuffer subKey ) {
		//E擴展
		StringBuffer RExtent = new StringBuffer(); // 存儲擴展後的右邊
        for (int i = 0; i < 48; ++i) {
            RExtent.append(R.charAt(E[i] - 1));
        }
		//異或運算
        for (int i = 0; i < 48; ++i) {
            RExtent.replace(i, i + 1, (RExtent.charAt(i) == subKey.charAt(i)) ? "0" :"1");
        }
		//S-Box
        StringBuffer SBoxString = new StringBuffer();
        for(int i = 0; i < 8; ++i) {
        	String SBoxInput = RExtent.substring(i * 6, (i + 1) * 6);
        	int row = Integer.parseInt(Character.toString(SBoxInput.charAt(0)) + SBoxInput.charAt(5), 2);
            int column = Integer.parseInt(SBoxInput.substring(1, 5), 2);
            
            StringBuffer SBoxOutput = new StringBuffer(Integer.toBinaryString(SBox[i][row * 16 + column]));
            while (SBoxOutput.length() < 4) {
                SBoxOutput.insert(0, 0);
            }
            SBoxString.append(SBoxOutput);
        }
		//P置換
        StringBuffer substituteSBoxString= new StringBuffer(); // 存儲置換後的R
        for (int i = 0; i < 32; ++i) {
        	substituteSBoxString.append(SBoxString.charAt(P[i] - 1));
        }
        return substituteSBoxString;
	}
	
	//子祕鑰生成
	public StringBuffer[] getSubKey() {
		//把key轉換爲二進制
		StringBuffer keyBinary = string2Binary(key);
		
		StringBuffer[] subKey = new StringBuffer[16]; // 存儲子密鑰
		//PC1置換
		StringBuffer C0 = new StringBuffer(); // 存儲密鑰左塊
	    StringBuffer D0 = new StringBuffer(); // 存儲密鑰右塊
	    for (int i = 0; i < 28; ++i) {
            C0.append(keyBinary.charAt(PC1[i] - 1));
            D0.append(keyBinary.charAt(PC1[i + 28] - 1));
        }
        
	    // LS循環16輪生成子密鑰
        for (int i = 0; i < 16; ++i) {
            // 循環左移
        	char mTemp;
            mTemp = C0.charAt(0);
            C0.deleteCharAt(0);
            C0.append(mTemp);
            mTemp = D0.charAt(0);
            D0.deleteCharAt(0);
            D0.append(mTemp);
            if(i != 0 && i != 1 && i != 8 && i != 15) {
            	mTemp = C0.charAt(0);
                C0.deleteCharAt(0);
                C0.append(mTemp);
                mTemp = D0.charAt(0);
                D0.deleteCharAt(0);
                D0.append(mTemp);
            }
            // 把左右兩塊合併
            StringBuffer C0D0 = new StringBuffer(C0.toString() + D0.toString());
            
            // PC2置換
            // 根據PC2壓縮C0D0,得到子密鑰
            StringBuffer C0D0Temp = new StringBuffer();
            for (int j = 0; j < 48; ++j) {
                C0D0Temp.append(C0D0.charAt(PC2[j] - 1));
            }
            subKey[i] = C0D0Temp;
        }
        return subKey;
	}
	//返回密文
	public StringBuffer getCiphertext() {
		return ciphertext;
	}
	//返回密文十六進制
	public StringBuffer getCiphertextHex() {
		return ciphertextHex;
	}
	//返回明文
	public StringBuffer getPlaintext() {
		return plaintext;
	}
	//主函數
	public static void main(String[] args) throws Exception {
		//測試加密
		StringBuffer text = new StringBuffer("NiceToMeetYouDES");
		StringBuffer key = new StringBuffer("aaaaaaaa");
		int mode = 0;
		DES instance = new DES(text, key, mode);
		instance.start();
		System.out.println("DES-Algorithm\n");
		System.out.println("輸入:" + text);
		System.out.println("模式:" + ((mode == 0) ? "加密" : "解密"));
		System.out.println("\n明文:" + instance.getPlaintext());
		System.out.println("密文:" + instance.getCiphertext());
		if(mode == 0)
			System.out.println("密文(十六進制):" + instance.getCiphertextHex());
		System.out.println("祕鑰:" + key);
		System.out.println("");
		
		//測試解密
		text = instance.getCiphertext();
		key = new StringBuffer("````````");
		mode = 1;
		instance = new DES(text, key, mode);
		instance.start();
		System.out.println("輸入:" + text);
		System.out.println("模式:" + ((mode == 0) ? "加密" : "解密"));
		System.out.println("\n明文:" + instance.getPlaintext());
		System.out.println("密文:" + instance.getCiphertext());
		if(mode == 0)
			System.out.println("密文(十六進制):" + instance.getCiphertextHex());
		System.out.println("祕鑰:" + key);
		
	}
}

七、參考資料

DES加密算法詳解

DES算法實現

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