SpringBoot 配置文件数据加密

前言

SpringBoot 配置文件中的数据库账户、密码等敏感数据不能明文展示,否则代码泄露的话,数据库的数据会被恶意利用。

加密算法

  • Jasypt Spring Boot 2.x 默认使用的加密算法是 PBEWithMD5AndDES,其中的 IV 生成器是 org.jasypt.iv.NoIvGenerator
  • Jasypt Spring Boot 3.x 默认使用的加密算法是 PBEWITHHMACSHA512ANDAES_256,其中的 IV 生成器是 org.jasypt.iv.RandomIvGenerator

添加 Maven 坐标

1
2
3
4
5
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.4</version>
</dependency>

加密与解密测试

测试加密与解密的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class EncryptTest {

/**
* 加密/解密所需的秘钥(盐)
*/
private final String salt = "Jasypt@Test";

/**
* 加密
*/
@Test
public void encrypt() {
BasicTextEncryptor textEncryptor = new BasicTextEncryptor();
// 加密所需的秘钥(盐)
textEncryptor.setPassword(salt);
// 要加密的数据
String password = textEncryptor.encrypt("root");
// 每次生成的密文都不一样
System.out.println("encrypt password: " + password);
}

/**
* 解密
*/
@Test
public void decrypt() {
BasicTextEncryptor textEncryptor = new BasicTextEncryptor();
// 解密所需的秘钥(盐)
textEncryptor.setPassword(salt);
// 要解密的数据
String password = textEncryptor.decrypt("AM7Q/hDyHcuNswbXO02c1w==");
System.out.println("decrypt password: " + password);
}

}

值得一提的是,在上述手动调用 Jasypt API 的代码中,BasicTextEncryptor 类使用加密算法是 PBEWithMD5AndDES。若希望使用 PBEWITHHMACSHA512ANDAES_256 加密算法,可以使用 AES256TextEncryptor 类来替代,更多内容请查看 Jasypt 的源码。

测试加密与解密的命令行

  • 命令行加密
1
java -cp jasypt-1.9.3.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI input="root" password="Jasypt@Test" algorithm=PBEWithMD5AndDES ivGeneratorClassName=org.jasypt.iv.NoIvGenerator
  • 命令行解密
1
java -cp jasypt-1.9.3.jar org.jasypt.intf.cli.JasyptPBEStringDecryptionCLI input="AM7Q/hDyHcuNswbXO02c1w==" password="Jasypt@Test" algorithm=PBEWithMD5AndDES ivGeneratorClassName=org.jasypt.iv.NoIvGenerator

SpringBoot 配置文件

测试环境

配置解密所需的秘钥(盐)与解密算法,并使用 ENC() 包裹加密后的数据信息,这样 Jasypt 才知道要解密哪些数据。

特别注意

在 SpringBoot 的配置文件中,强烈建议使用 algorithmiv-generator-classname 参数来指定解密算法。这样可以避免在应用启动时,可能由于加解密使用的算法不一致,导致 Jasypt 无法解密配置文件的密文数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 配置解密所需的秘钥(盐)、解密算法
jasypt:
encryptor:
password: Jasypt@Test
algorithm: PBEWithMD5AndDES
iv-generator-classname: org.jasypt.iv.NoIvGenerator

# 使用加密后的数据信息
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/wcscanner?characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true
username: ENC(bRVJmN0LlgBAIcXSknCTFQ==)
password: ENC(u1HCmk1og6N0wvmnewJI2Q==)

生产环境

命令行参数方式

上面的 YAML 配置方式,虽然数据库的配置信息使用了密文,但还是非常不安全,因为解密的秘钥(盐)暴露在 application.yml 配置文件中。为了防止秘钥(盐)意外泄漏,被恶意反解出密码,可以在应用部署的时候使用命令行参数传入秘钥(盐)。

1
java -jar shop.jar --jasypt.encryptor.password=Jasypt@Test --jasypt.encryptor.algorithm=PBEWithMD5AndDES --jasypt.encryptor.iv-generator-classname=org.jasypt.iv.NoIvGenerator

Linux 环境变量方式

为了方便统一管理秘钥(盐),可以将秘钥添加到 Linux 系统的环境变量里。

  • 编辑配置文件
1
vim /etc/profile
  • 在配置文件末尾,添加环境变量(秘钥)
1
export JASYPT_PASSWORD=Jasypt@Test
  • 使配置文件生效
1
source /etc/profile
  • 运行 SpringBoot 应用
1
java -jar shop.jar --jasypt.encryptor.password=${JASYPT_PASSWORD} --jasypt.encryptor.algorithm=PBEWithMD5AndDES --jasypt.encryptor.iv-generator-classname=org.jasypt.iv.NoIvGenerator

常见错误

应用启动提示解密失败

SpringBoot 应用启动时,提示解密失败,输出下述的错误信息:

1
Decryption of Properties failed,  make sure encryption/decryption passwords match

这一般是加密与解密时使用的算法不一致导致的,建议检查 SpringBoot 的配置文件,观察是否有使用 algorithmiv-generator-classname 参数来指定加密算法,没有的话就加上去。

1
2
3
4
5
jasypt:
encryptor:
password: Jasypt@Test
algorithm: PBEWithMD5AndDES
iv-generator-classname: org.jasypt.iv.NoIvGenerator

JCE 密钥长度限制问题

使用 PBEWITHHMACSHA512ANDAES_256 加密算法后,SpringBoot 应用启动时抛出以下异常。这是由于使用了强加密算法,且未在 Java 虚拟机中安装 Java 加密扩展(JCE)无限强度管辖权策略文件,导致在使用 AES、ElGamal 等加密算法时密钥的长度受到了限制。

1
A possible cause is you are using strong encryption algorithms and you have not installed the Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files in this Java Virtual Machine

解决办法是下载 JCE 文件到本地虚拟机,JCE 文件可以从下述地址下载,安装教程可看 这里

参考资料