1. 程式人生 > >java 檔案加密 用的是md5值進行檔案加密

java 檔案加密 用的是md5值進行檔案加密

加密解密的背景, 原理和用法在程式碼註釋裡

程式碼:

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!");
	}
	
}