Jasypt 简介
什么是 Jasypt?
- Jasypt(Java Simplified Encryption)是一个Java库,它允许开发人员以最小的努力为项目添加基本的加密功能,而无需深入了解密码学的工作原理。
- 基于标准的高安全性加密技术,适用于单向和双向加密。加密密码,文本,数字,二进制文件
- 与 Hibernate 的透明集成。
- 适合集成到基于 Spring 的应用程序中,也可以透明地与 Spring 安全性集成。
- 用于加密应用程序(即数据源)配置的集成功能。
- 多处理器/多核系统中高性能加密的特定功能。
- 开放 API 以与任何 JCE 提供程序一起使用。
支持的加密功能
Jasypt 基于 Java Cryptography Extension (JCE),支持以下加密功能:
- 对称加密:数据加密和解密使用同一个密钥(如 AES、DES)。
- 单向加密:如哈希算法(SHA-256),适合存储密码等不可逆信息。
- 文件加密:支持二进制文件的加解密。
- 配置加密:特别适用于对敏感配置(如数据库密码、API 密钥)的保护。
Jasypt加密场景
- System Property 系统变量
- Envirnment Property 环境变量
- Command Line argument 命令行参数
- Application.properties 应用配置文件
- Yaml properties 应用配置文件
- other custom property sources 其它配置文件
SpringBoot项目中集成jasypt
- 添加依赖jar
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>
- 配置application.yml配置文件
jasypt:
encryptor:
# 指定解密算法,需要和加密时使用的算法一致
algorithm: PBEWithMD5AndDES
keyObtentionIterations: 1000
# 指定加密密钥,生产环境请放到启动参数里面
password: G0CvDz7oJn6
poolSize: 1
saltGeneratorClassname: org.jasypt.salt.RandomSaltGenerator
stringOutputType: base64
jasypt3.0后,默认支持的算法为 PBEWITHHMACSHA512ANDAES_256 ,该算法需要JDK1.9 以上支持或者添加JCE(Java Cryptography Extension 无限强度权限策略文件)支持。
- 使用工具类加解密
public class JasyptUtils {
private static final PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
private static final String PASSWORD = System.getProperty("jasypt.encryptor.password", "defaultPassword");
static {
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
config.setAlgorithm("PBEWithMD5AndDES");
config.setPassword(PASSWORD);
config.setKeyObtentionIterations("1000");
config.setPoolSize("1");
config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
config.setStringOutputType("base64");
encryptor.setConfig(config);
}
public static String encrypt(String plaintext) {
try {
return encryptor.encrypt(plaintext);
} catch (Exception e) {
throw new RuntimeException("加密失败", e);
}
}
public static String decrypt(String encryptedText) {
try {
return encryptor.decrypt(encryptedText);
} catch (Exception e) {
throw new RuntimeException("解密失败", e);
}
}
}
- 配置文件密钥安全性处理
datasource:
# driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:13306/oauth?characterEncoding=utf-8&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull&useSSL=false&useUnicode=true&rewriteBatchedStatements=true
username: root
password: ENC(Ifn6fVWW1eA/jVy9fkLhI3pONN/wuCVsm3bfSEzNE10=)
Jasypt 常见加密算法
支持的默认算法一览
Jasypt 提供了多种加密算法,常见的包括以下几种:
| 算法名称 | 类型 | 说明 |
|---|---|---|
| PBEWithMD5AndDES | 对称加密 | 默认算法,使用 MD5 和 DES 结合,适合基础加密需求。 |
| PBEWithHMACSHA512AndAES_256 | 对称加密 | 高级加密算法,支持更高安全性,需 JDK 1.9 或添加 JCE 支持。 |
| PBEWithSHA1AndDESede | 对称加密 | 使用 SHA1 和 DESede(Triple DES)结合,适合需要更强加密的场景。 |
| PBEWithMD5AndTripleDES | 对称加密 | 提供更高的安全性,推荐在对性能要求较低的场景使用。 |
| PBEWithSHA256And128BitAES-CBC-BC | 对称加密 | 支持 AES-128 位加密,适合现代化安全需求。 |
各算法的特点和适用场景
-
PBEWithMD5AndDES
- 特点:性能较好,适合普通加密需求。
- 适用场景:配置文件加密、敏感信息保护。
-
PBEWithHMACSHA512AndAES_256
- 特点:更高强度的加密算法,适合对安全性要求高的场景。
- 适用场景:企业级应用的关键数据加密,如 API 密钥、数据库配置。
-
PBEWithSHA1AndDESede
- 特点:加密强度中等,兼顾性能和安全性。
- 适用场景:中小型项目的敏感信息加密。
-
PBEWithMD5AndTripleDES
- 特点:高安全性,性能稍低。
- 适用场景:需要持久性存储的重要数据加密。
-
PBEWithSHA256And128BitAES-CBC-BC
- 特点:AES 加密提供更现代化的安全性,适合对性能有较高要求的场景。
- 适用场景:移动端和分布式系统中的配置加密。
Jasypt 使用注意事项
密钥安全管理
-
避免硬编码密码:
密钥不应直接写在代码或配置文件中,推荐通过系统环境变量或启动参数传递。java -jar app.jar --jasypt.encryptor.password=yourSecretKey -
限制密钥权限:
密钥文件或环境变量的访问权限应严格控制,仅允许授权用户和进程访问。 -
定期更换密钥:
为提高安全性,应定期更换加密密钥并重新加密存储的数据。
异常处理和日志记录
-
加解密异常捕获:
在加解密过程中,可能出现密钥错误、算法不支持等异常,需捕获并记录日志。try { String encrypted = encryptor.encrypt("plaintext"); } catch (Exception e) { log.error("Encryption failed: ", e); } -
敏感数据保护:
避免在日志中记录明文数据或加密密钥,以防泄露敏感信息。
性能优化建议
-
使用池化加密器:
配置PooledPBEStringEncryptor的poolSize参数,根据系统并发需求合理设置线程池大小。config.setPoolSize("5"); -
减少解密操作:
对需要频繁访问的解密数据,推荐缓存解密后的内容,避免重复解密带来的性能开销。 -
选择适合的算法:
根据实际需求选择加密算法,简单配置可选择PBEWithMD5AndDES,复杂场景可选更高级的算法。
真实场景应用
数据库配置加密
将数据库的用户名和密码加密存储,防止配置文件泄露时敏感信息暴露:
datasource:
url: jdbc:mysql://localhost:3306/mydb
username: ENC(encryptedUsername)
password: ENC(encryptedPassword)
敏感信息保护(如 API Key)
在项目中加密存储第三方服务的 API Key:
api:
key: ENC(encryptedApiKey)
与 Spring Security 集成
通过 Jasypt 加密用户认证信息或加密存储会话令牌,提升应用的安全性。
通过正确使用 Jasypt 提供的加密算法与安全配置,我们可以有效保护敏感信息的安全,同时保证性能与易用性。Jasypt 在 Spring Boot 中的无缝集成,使其成为开发者处理配置加密的首选方案。
测试方式一
# maven依赖:org.jasypt:jasypt
java -cp jasypt-1.9.2.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI password=xxxyyyzzz algorithm=PBEWithMD5AndDES input="明文"
java -cp jasypt-1.9.2.jar org.jasypt.intf.cli.JasyptPBEStringDecryptionCLI password=xxxyyyzzz algorithm=PBEWithMD5AndDES input=密文
# 好像是必须带上ivGeneratorClassName=org.jasypt.iv.RandomIvGenerator
java -cp jasypt-1.9.3.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI password=xxxyyyzzz algorithm=PBEWithMD5AndDES ivGeneratorClassName=org.jasypt.iv.RandomIvGenerator input="明文"
java -cp jasypt-1.9.3.jar org.jasypt.intf.cli.JasyptPBEStringDecryptionCLI password=xxxyyyzzz algorithm=PBEWithMD5AndDES ivGeneratorClassName=org.jasypt.iv.RandomIvGenerator input=密文
# maven依赖:com.melloware:jasypt
# com.melloware:jasypt:1.9.4报错:Bad argument: ivGeneratorClassName=org.jasypt.iv.RandomIvGenerator,需要去掉ivGeneratorClassName参数
java -cp jasypt-1.9.4.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI password=password algorithm=PBEWithMD5AndDES input="XXX"
java -cp jasypt-1.9.4.jar org.jasypt.intf.cli.JasyptPBEStringDecryptionCLI password=password algorithm=PBEWithMD5AndDES input="XXX"
测试方式二
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
config.setPassword("jaspyt_password");
config.setAlgorithm("PBEWITHHMACSHA512ANDAES_256");
config.setKeyObtentionIterations("1000");
config.setPoolSize("1");
config.setProviderName("SunJCE");
config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
//config.setIvGeneratorClassName("org.jasypt.iv.RandomIvGenerator");
config.setStringOutputType("base64");
encryptor.setConfig(config);
System.out.println(encryptor.encrypt("root"));
测试方式三
import org.jasypt.encryption.StringEncryptor;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class TestAppTest {
@Resource
private StringEncryptor stringEncryptor;
@Test
public void testEncrypt() {
// 加密
System.out.println(stringEncryptor.encrypt("100"));
// 解密
System.out.println(stringEncryptor.decrypt("9eO11FBv04dwRC3KUJjpXx0XpfA/nlhWy0ee91bpAlbLJZAlMtlh+pRFnL9HsX8o0do26JwkwnAuqk/RVuwa5FRtAdzwsL2B6ce1vQ43z2hXmbuiUBoDyh0UCbnVHqNX"));
}
}
秘钥处理
- 将加密密码以明文形式写在配置文件中并不安全,实际开发中也不推荐这样使用。
- 打包后部署项目,可以使用如下命令在启动项目时指定秘钥:
#方式1:
java -jar xxx.jar -Djasypt.encryptor.password=加密数据的秘钥
#方式2:
java -jar xxx.jar --jasypt.encryptor.password=加密数据的秘钥
SpringBoot何时解密?
jasypt-spring-boot-starter在服务运行(启动)时会自动对密文进行解密处理