首页  编辑  

MySQL敏感数据加密

Tags: /MySQL/   Date Created:

SQL 加密

要求所有敏感数据均加密存储,因此数据库中的配置信息如密码字段,应该以密文形式存储,不应该使用明文。

MySQL 5.6及以下

MySQL低版本支持 encode('明文', '密码') 和 decode('密文', '密码')函数,这两个函数输入和输出,均是字符串,可以直接使用,但 MySQL 8.0不支持这两个函数。
MySQL低版本,同样支持 aes_encrypt 和 aes_descrypt 函数。

MySQL 8.0及以上

请使用 aes_encrypt(‘明文', '密码') 加密,使用 aes_decrypt('密文', '密码') 解密。
由于加密解密输出的是二进制,因此如果需要可读文本输出,可以用 hex 函数和 unhex 函数进行十六进制转换即可。
例如:

select hex(aes_encrypt('abc', 'good boy'));
select aes_decrypt(unhex('AFFAA96FB6F1954757BFCD341F07CA6B'), 'good boy');

利用Java加密

我们也可以利用Java代码来实现在数据库外对数据加密。优点是和MySQL本身无关,自主性和安全性更高。

生成密钥

/**
 * 生成密钥对象
 */
private static SecretKey aesGenerateKey(String password) throws Exception {
	// 指定的RNG算法名称, 创建安全随机数生成器
	SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
	//设置加密用的种子,密钥
	random.setSeed(password.getBytes());
	// 创建AES算法生成器
	KeyGenerator gen = KeyGenerator.getInstance("AES");
	// 初始化算法生成器
	gen.init(128, random);
	// 生成 AES密钥对象
	return gen.generateKey();
	// 也可以直接创建密钥对象: return new SecretKeySpec(key, ALGORITHM);
	// return new SecretKeySpec(key, ALGORITHM);
}

AES 加密

/**
 * AES 加密
 *
 * @param content  需要加密的内容
 * @param password 加密密码
 * @return 加密后的HEX字符串,失败返回 null
 */
public static String aesEncrypt(String content, String password) {
	if (content == null || password == null) return null;

	try {
		SecretKey key = aesGenerateKey(password);
		Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
		cipher.init(Cipher.ENCRYPT_MODE, key);
		byte[] result = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));
		return bin2hex(result, false);
	} catch (Exception e) {
		return null;
	}
}

AES 解密

/**
 * AES 解密
 *
 * @param content  待解密内容,为HEX字符串
 * @param password 解密密钥
 * @return 解密后的字符串,失败返回 null
 */
public static String aesDecrypt(String content, String password) {
	if (content == null || password == null) return null;

	try {
		SecretKey key = aesGenerateKey(password);
		Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
		cipher.init(Cipher.DECRYPT_MODE, key);
		byte[] result = cipher.doFinal(hex2bin(content));
		return new String(result, StandardCharsets.UTF_8);
	} catch (Exception e) {
		return null;
	}
}