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(); } } }