1. 程式人生 > >Java實現檔案的DES加密與解密演算法

Java實現檔案的DES加密與解密演算法

一、基礎知識

      根據金鑰型別不同將現代密碼技術分為兩類:對稱加密演算法(祕金鑰匙加密)和非對稱加密演算法(公開金鑰加密)。
對稱鑰匙加密系統是加密和解密均採用同一把祕金鑰匙,而且通訊雙方都必須獲得這把鑰匙,並保持鑰匙的祕密。
非對稱金鑰加密系統採用的加金鑰匙(公鑰)和解金鑰匙(私鑰)是不同的。

1.1    對稱加密演算法

對稱加密演算法用來對敏感資料等資訊進行加密,常用的演算法包括:
DES(Data Encryption Standard):資料加密標準,速度較快,適用於加密大量資料的場合。
3DES(Triple DES):是基於DES,對一塊資料用三個不同的金鑰進行三次加密,強度更高。
AES(Advanced Encryption Standard):高階加密標準,是下一代的加密演算法標準,速度快,安全級別高;


1.2    對稱演算法

常見的非對稱加密演算法如下:
RSA:由 RSA 公司發明,是一個支援變長金鑰的公共金鑰演算法,需要加密的檔案塊的長度也是可變的;
DSA(Digital Signature Algorithm):數字簽名演算法,是一種標準的 DSS(數字簽名標準);
ECC(Elliptic Curves Cryptography):橢圓曲線密碼編碼學。

1.3    加密演算法的選擇

前面簡單介紹了各種對稱和非對稱加密演算法,那我們在實際使用的過程中究竟該使用哪一種比較好呢?
我們應該根據自己的使用特點來確定,由於非對稱加密演算法的執行速度比對稱加密演算法的速度慢很多,當我們需要加密大量的資料時,建議採用對稱加密演算法,提高加解密速度。
對稱加密演算法不能實現簽名,因此簽名只能非對稱演算法。
由於對稱加密演算法的金鑰管理是一個複雜的過程,金鑰的管理直接決定著他的安全性,因此當資料量很小時,我們可以考慮採用非對稱加密演算法。
在實際的操作過程中,我們通常採用的方式是:採用非對稱加密演算法管理對稱演算法的金鑰,然後用對稱加密演算法加密資料,這樣我們就集成了兩類加密演算法的優點,既實現了加密速度快的優點,又實現了安全方便管理金鑰的優點。
如果在選定了加密演算法後,那採用多少位的金鑰呢?一般來說,金鑰越長,執行的速度就越慢,應該根據的我們實際需要的安全級別來選擇,一般來說,RSA建議採用1024位的數字,ECC建議採用160位,AES採用128為即可。

二、程式碼實現

saveDesKey生成金鑰,存放在DesKey.xml中
encrypt和decrypt根據DesKey.xml中的金鑰,來加密和解密檔案



import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.security.Key;
import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;

public class DesUtil {
	private static String keyfileName = "DesKey.xml";
	/**
	 * <p> DES解密檔案
	 * @param file 需要解密的檔案
	 * @param dest 解密後的檔案
	 * @throws Exception
	 */
	public static void decrypt(String file, String dest) throws Exception {
		Cipher cipher = Cipher.getInstance("DES");
		cipher.init(Cipher.DECRYPT_MODE, getKey());
		InputStream is = new FileInputStream(file);
		OutputStream out = new FileOutputStream(dest);
		CipherOutputStream cos = new CipherOutputStream(out, cipher);
		byte[] buffer = new byte[1024];
		int r;
		while ((r = is.read(buffer)) >= 0) {
			cos.write(buffer, 0, r);
		}
		cos.close();
		out.close();
		is.close();
	}
	/**
	 * <p>DES加密檔案
	 * @param file 原始檔
	 * @param destFile 加密後的檔案
	 * @throws Exception
	 */
	public static void encrypt(String file, String destFile) throws Exception {
			Cipher cipher = Cipher.getInstance("DES");
			cipher.init(Cipher.ENCRYPT_MODE, getKey());
			InputStream is = new FileInputStream(file);
			OutputStream out = new FileOutputStream(destFile);
			CipherInputStream cis = new CipherInputStream(is, cipher);
			byte[] buffer = new byte[1024];
			int r;
			while ((r = cis.read(buffer)) > 0) {
				out.write(buffer, 0, r);
			}
			cis.close();
			is.close();
			out.close();
		}
	private static Key getKey() {
		Key kp = null;
		try {
			String fileName = keyfileName;
			InputStream is = new FileInputStream(fileName);
			ObjectInputStream oos = new ObjectInputStream(is);
			kp = (Key) oos.readObject();
			oos.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return kp;
	}
	public static void main(String[] args) throws Exception {
		DesUtil.saveDesKey();
		DesUtil.encrypt("desinput.txt", "desoutput.txt");
		DesUtil.decrypt("desoutput.txt","desinput2.txt");
		//desinput.txt 經過加密和解密後生成的 desinput2.txt 應該與原始檔一樣
	}
	/**
	 * <p> 生成KEY,並儲存
	 */
	public static void saveDesKey(){		
		try {
			SecureRandom sr = new SecureRandom();
			//為我們選擇的DES演算法生成一個KeyGenerator物件
			KeyGenerator kg = KeyGenerator.getInstance ("DES" );
			kg.init (sr);
			FileOutputStream fos = new FileOutputStream(keyfileName);
		    ObjectOutputStream oos = new ObjectOutputStream(fos);
			//生成金鑰
			Key key = kg.generateKey();
		    oos.writeObject(key);
		    oos.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}