Java使用AES對稱加密算法對文件加解密


為了安全,我們會采取對文件的重要信息進行加密。本文將介紹如何使用對稱加密算法AES對文件進行加解密,包括:“替換local_policy.jar和US_export_policy.jar文件”、“加密文件內容”、“自定義PropertyPlaceholderConfigurer子類解密文件”。

1、替換local_policy.jar和US_export_policy.jar文件。

替換${java_home}/jre/lib/security下的local_policy.jar和US_export_policy.jar文件。

我們加密使用的密鑰長度大於128,而正常Java運行環境限制了密鑰長度不能大於128。所以我們需要下載能支持密鑰大於128的local_policy.jar和US_export_policy.jar文件,替換掉${java_home}/jre/lib/security下的對應的文件。

2、加密文件內容。

如數據庫連接文件,將數據庫用戶名和密文進行加密。將用戶名和密碼使用AES加密后,填寫到文件:

# 數據庫驅動
driverClassName=com.mysql.cj.jdbc.Driver
# 數據庫URL
db.mysql.url=jdbc:mysql://localhost:3306/%s?useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL
# 數據庫用戶名
db.mysql.username.encryption=81A3FD464E18C4497A79CE7CC9D5B660
db.nbx.mysql.username.encryption=81A3FD464E18C4497A79CE7CC9D5B660
# 密碼
db.mysql.password.encryption=16CCEF25E22FA42E89821B7B27858DE26DD8BFF1139FF2C70BECCA88E373F809
db.nbx.mysql.password.encryption=16CCEF25E22FA42E89821B7B27858DE26DD8BFF1139FF2C70BECCA88E373F809

key鍵多了個”.encryption”,后面使用PropertyPlaceholderConfigurerUtil對其進行處理。

3、自定義 PropertyPlaceholderConfigurer子類解密文件。

PropertyPlaceholderConfigurer是個bean工廠后置處理器的實現,新建一個類PropertyPlaceholderConfigurerUtil繼承它,可以在容器啟動時,對加密的文件進行解密。

PropertyPlaceholderConfigurerUtil重寫了processProperties方法。processProperties方法找到文件里以“.encryption”結尾的key,將它的value進行解密,並去掉“.encryption”:

public class PropertyPlaceholderConfigurerUtil extends PropertyPlaceholderConfigurer {
	
	@Override
	protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props) throws BeansException {
		AESUtil aesHelper = new AESUtil();
		Enumeration<?> keys = props.propertyNames();
		while (keys.hasMoreElements()) {
			String key = (String) keys.nextElement();
			String value = props.getProperty(key);
			if (key.endsWith(".encryption") && null != value) {
				props.remove(key);
				key = key.substring(0, key.length() - 11);
				value = aesHelper.decrypt(value.trim());
				props.setProperty(key, value);
			}
			System.setProperty(key, value);
		}
		super.processProperties(beanFactoryToProcess, props);
	}
	
}

解密:

	/**
	 * * Input encrypted String represented in HEX * * @return a string decrypted in
	 * plain text
	 */
	public String decrypt(String hexCipherText) {
		try {
			String plaintext = new String(dcipher.doFinal(hexToByte(hexCipherText)), "UTF-8");
			return plaintext;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	public static byte[] hexToByte(String hexString) {
		int len = hexString.length();
		byte[] ba = new byte[len / 2];
		for (int i = 0; i < len; i += 2) {
			ba[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + Character.digit(hexString.charAt(i + 1), 16));
		}
		return ba;
	}

生成密鑰:

	/**
	 * * Input a string that will be md5 hashed to create the key. * * @return void,
	 * cipher initialized
	 */
	public AESUtil() {
		try {
			SecretKeySpec skey = new SecretKeySpec("xxxxxxxxxxxxxxxx".getBytes(), "AES");
			this.setupCrypto(skey);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

獲取和初始化加密、解密Cipher對象:

	private void setupCrypto(SecretKey key) {
		// Create an 8-byte initialization vector
		byte[] iv = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
		AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv);
		try {
			ecipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
			dcipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
			// CBC requires an initialization vector
			ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
			dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

加密字符串:

	/**
	 * * Input is a string to encrypt. * * @return a Hex string of the byte array
	 */
	public String encrypt(String plaintext) {
		try {
			byte[] ciphertext = ecipher.doFinal(plaintext.getBytes("UTF-8"));
			return byteToHex(ciphertext);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	public static String byteToHex(byte[] raw) {
		if (raw == null) {
			return null;
		}
		final StringBuilder hex = new StringBuilder(2 * raw.length);
		for (final byte b : raw) {
			hex.append(HEXES.charAt((b & 0xF0) >> 4)).append(HEXES.charAt((b & 0x0F)));
		}
		return hex.toString();
	}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM