java 檔案加密 用的是md5值進行檔案加密
阿新 • • 發佈:2019-02-19
加密解密的背景, 原理和用法在程式碼註釋裡
程式碼:
import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Scanner; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESKeySpec; import javax.swing.JFileChooser; /** * (1)jdk版本:1.40以上 * (2)加密背景:檔案加密 加密方法:三重des加密 * (3)加密解密原理: * 加密時,對輸入的48位祕鑰,前兩位,中間兩位和後44位,分別求md5值, * 先用第一個md5值加密,再用第二個md5值加密,最後用第三個md5值加密,,共三重加密, * 解密時,對輸入的byte陣列即加密後的檔案, 先用第三個md5值解密,再用第二個md5值解密,再用第一個md5值解密,這樣返回的就是解密後的檔案 * md5值的獲取用 java.security 包裡的類 * 加密解密用的是 javax.crypto 包裡面的類 * (4)加密解密過程用法: * 在console 輸入祕鑰 AD67EA2F3BE6E5ADD368DFE03120B5DF92A8FD8FEC2F0746 * 再輸入需要加密的檔名 def.txt(檔案路徑是相對路徑是相對這個的路徑 D:\***\EclipseWorkingspace\WorkspaceLearning\jsp_api) * 再輸入en,即可實現加密 * 在以上路徑下出現加密檔案 en_def.txt, * 解密過程方法:輸入祕鑰 AD67EA2F3BE6E5ADD368DFE03120B5DF92A8FD8FEC2F0746 * 再輸入需要解密的檔名 en_def.txt * 再輸入de,即可實現解密 * * */ public class fileencrypter { /** * 加密函式 輸入: 要加密的檔案,密碼(由0-F組成,共48個字元,表示3個16位的密碼)如: * AD67EA2F3BE6E5ADD368DFE03120B5DF92A8FD8FEC2F0746 其中: * AD67EA2F3BE6E5AD DES密碼一 D368DFE03120B5DF DES密碼二 92A8FD8FEC2F0746 DES密碼三 * 輸出:對輸入的檔案加密後,儲存到同一資料夾下增加了 "en+原檔名" 為副檔名的檔案中。 * * param: * sKey 是三個md5值的字串拼接, 一共48位 */ private void encrypt(File fileIn, String sKey) { try { if (sKey.length() == 48) { byte[] bytK1 = getKeyByStr(sKey.substring(0, 16)); byte[] bytK2 = getKeyByStr(sKey.substring(16, 32)); byte[] bytK3 = getKeyByStr(sKey.substring(32, 48)); FileInputStream fis = new FileInputStream(fileIn); byte[] bytIn = new byte[(int) fileIn.length()]; for (int i = 0; i < fileIn.length(); i++) { bytIn[i] = (byte) fis.read(); } // 加密 byte[] bytOut = encryptByDES(encryptByDES(encryptByDES(bytIn, bytK1), bytK2), bytK3); String fileOut = "en_"+fileIn.getPath(); FileOutputStream fos = new FileOutputStream(fileOut); for (int i = 0; i < bytOut.length; i++) { fos.write((int) bytOut[i]); } fos.close(); } else ; } catch (Exception e) { e.printStackTrace(); } } /** * 解密函式 輸入: 要解密的檔案,密碼(由0-F組成,共48個字元,表示3個16位的密碼)如: * AD67EA2F3BE6E5ADD368DFE03120B5DF92A8FD8FEC2F0746 其中: * AD67EA2F3BE6E5AD DES密碼一 D368DFE03120B5DF DES密碼二 92A8FD8FEC2F0746 DES密碼三 * 輸出:對輸入的檔案解密後,儲存到使用者指定的檔案中。 */ private void decrypt(File fileIn, String sKey) { try { if (sKey.length() == 48) { String strPath = fileIn.getPath(); strPath = "de"+strPath.substring(2, strPath.length()); JFileChooser chooser = new JFileChooser(); chooser.setCurrentDirectory(new File(".")); chooser.setSelectedFile(new File(strPath)); byte[] bytK1 = getKeyByStr(sKey.substring(0, 16)); byte[] bytK2 = getKeyByStr(sKey.substring(16, 32)); byte[] bytK3 = getKeyByStr(sKey.substring(32, 48)); FileInputStream fis = new FileInputStream(fileIn); byte[] bytIn = new byte[(int) fileIn.length()]; for (int i = 0; i < fileIn.length(); i++) { bytIn[i] = (byte) fis.read(); } // 解密 byte[] bytOut = decryptByDES(decryptByDES(decryptByDES(bytIn, bytK3), bytK2), bytK1); File fileOut = chooser.getSelectedFile(); fileOut.createNewFile(); FileOutputStream fos = new FileOutputStream(fileOut); for (int i = 0; i < bytOut.length; i++) { fos.write((int) bytOut[i]); } fos.close(); System.out.println("解密成功"); } } catch (Exception e) { System.out.println("解密錯誤!"); } } /** * 用DES方法加密輸入的位元組 bytKey需為8位元組長,是加密的密碼 * param:bytP 檔案 , bytKey 密碼 * return: */ private byte[] encryptByDES(byte[] bytP, byte[] bytKey) throws Exception { DESKeySpec desKS = new DESKeySpec(bytKey); SecretKeyFactory skf = SecretKeyFactory.getInstance("DES"); SecretKey sk = skf.generateSecret(desKS); Cipher cip = Cipher.getInstance("DES"); cip.init(Cipher.ENCRYPT_MODE, sk); return cip.doFinal(bytP); } /** * 用DES方法解密輸入的位元組 bytKey需為8位元組長,是解密的密碼 */ private byte[] decryptByDES(byte[] bytE, byte[] bytKey) throws Exception { DESKeySpec desKS = new DESKeySpec(bytKey); SecretKeyFactory skf = SecretKeyFactory.getInstance("DES"); SecretKey sk = skf.generateSecret(desKS); Cipher cip = Cipher.getInstance("DES"); cip.init(Cipher.DECRYPT_MODE, sk); return cip.doFinal(bytE); } /** * 輸入密碼的字元形式,返回位元組陣列形式。 如輸入字串:AD67EA2F3BE6E5AD * 返回位元組陣列:{173,103,234,47,59,230,229,173} */ private byte[] getKeyByStr(String str) { byte[] bRet = new byte[str.length() / 2]; for (int i = 0; i < str.length() / 2; i++) { Integer itg = new Integer(16 * getChrInt(str.charAt(2 * i)) + getChrInt(str.charAt(2 * i + 1))); bRet[i] = itg.byteValue(); } return bRet; } /** * 計算一個16進位制字元的10進位制值 輸入:0-F */ private int getChrInt(char chr) { int iRet = 0; if (chr == "0".charAt(0)) iRet = 0; if (chr == "1".charAt(0)) iRet = 1; if (chr == "2".charAt(0)) iRet = 2; if (chr == "3".charAt(0)) iRet = 3; if (chr == "4".charAt(0)) iRet = 4; if (chr == "5".charAt(0)) iRet = 5; if (chr == "6".charAt(0)) iRet = 6; if (chr == "7".charAt(0)) iRet = 7; if (chr == "8".charAt(0)) iRet = 8; if (chr == "9".charAt(0)) iRet = 9; if (chr == "A".charAt(0)) iRet = 10; if (chr == "B".charAt(0)) iRet = 11; if (chr == "C".charAt(0)) iRet = 12; if (chr == "D".charAt(0)) iRet = 13; if (chr == "E".charAt(0)) iRet = 14; if (chr == "F".charAt(0)) iRet = 15; return iRet; } public String md5s(String plainText) { String str = null; try { MessageDigest md = MessageDigest.getInstance("MD5"); md.update(plainText.getBytes()); byte b[] = md.digest(); int i; StringBuffer buf = new StringBuffer(""); for (int offset = 0; offset < b.length; offset++) { i = b[offset]; if (i < 0) i += 256; if (i < 16) buf.append("0"); buf.append(Integer.toHexString(i)); } // System.out.println("result: " + buf.toString());// 32位的加密 // System.out.println("result: " + buf.toString().substring(8, // 24));// 16位的加密 str = buf.toString().substring(8, 24); } catch (NoSuchAlgorithmException e) { // TODO Auto-generated catch block e.printStackTrace(); } return str; } public static void main(String args[]) { fileencrypter da = new fileencrypter();//相對路徑是相對這個的路徑 D:\***\EclipseWorkingspace\WorkspaceLearning\jsp_api Scanner scan = new Scanner(System.in); String pass = scan.next(); String pass1 = pass.substring(0, 2); String pass2 = pass.substring(2, 4); String pass3 = pass.substring(4); System.out.println(pass1); System.out.println(pass2); System.out.println(pass3); String name = scan.next(); // System.out.println("加密請輸入en, 解密請輸入de"); String method = scan.next(); if (method.equals("en")) da.encrypt(new File(name), da.md5s(pass1) + da.md5s(pass2) + da.md5s(pass3)); else if(method.equals("de")) da.decrypt(new File(name), da.md5s(pass1) + da.md5s(pass2) + da.md5s(pass3)); else System.out.println("input error!"); } }