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