Jasypt 是一个用于加密和解密字符串的 Java 库,常用于保护配置文件中的敏感信息(如数据库密码、API 密钥等)。StringEncryptor
是 Jasypt 的核心接口,用于执行字符串的加密和解密操作。以下是 StringEncryptor
的详细使用指南:
1. 添加依赖
在 pom.xml
中添加 Jasypt 依赖:
<dependency><groupId>com.github.ulisesbocchio</groupId><artifactId>jasypt-spring-boot-starter</artifactId><version>3.0.5</version>
</dependency>
2. 配置加密密钥
在 application.yml
中配置加密密钥:
jasypt:encryptor:password: mySecretKey # 加密密钥
3. 使用 StringEncryptor
3.1 注入 StringEncryptor
在 Spring Boot 应用中,可以直接注入 StringEncryptor
:
import org.jasypt.encryption.StringEncryptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class EncryptionService {@Autowiredprivate StringEncryptor stringEncryptor;public String encrypt(String plainText) {return stringEncryptor.encrypt(plainText);}public String decrypt(String encryptedText) {return stringEncryptor.decrypt(encryptedText);}
}
3.2 加密和解密示例
public class Main {public static void main(String[] args) {String plainText = "mySecretPassword";String encryptedText = stringEncryptor.encrypt(plainText);System.out.println("Encrypted: " + encryptedText);String decryptedText = stringEncryptor.decrypt(encryptedText);System.out.println("Decrypted: " + decryptedText);}
}
4. 加密配置文件中的敏感信息
4.1 加密字符串
使用 Jasypt 提供的命令行工具或 Java 代码加密字符串:
java -cp jasypt-1.9.3.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI \input="mySecretPassword" password=mySecretKey algorithm=PBEWithMD5AndDES
输出示例:
----ENVIRONMENT-----------------Runtime: Oracle Corporation Java HotSpot(TM) 64-Bit Server VM 25.271-b09----ARGUMENTS-------------------algorithm: PBEWithMD5AndDES input: mySecretPassword password: mySecretKey----OUTPUT----------------------h7J8K9L0M1N2O3P4Q5R6S7T8U9V0W1X2Y3Z4
4.2 在配置文件中使用加密字符串
在 application.yml
中使用 ENC()
包裹加密字符串:
spring:datasource:password: ENC(h7J8K9L0M1N2O3P4Q5R6S7T8U9V0W1X2Y3Z4)
5. 自定义 StringEncryptor
5.1 配置自定义加密器
在 application.yml
中配置自定义加密器:
jasypt:encryptor:password: mySecretKeyalgorithm: PBEWithMD5AndDESkey-obtention-iterations: 1000pool-size: 2salt-generator-classname: org.jasypt.salt.RandomSaltGeneratoriv-generator-classname: org.jasypt.iv.RandomIvGeneratorstring-output-type: base64
5.2 自定义 StringEncryptor
Bean
在 Java 配置类中定义自定义 StringEncryptor
:
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class JasyptConfig {@Bean("jasyptStringEncryptor")public StringEncryptor stringEncryptor() {StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();EnvironmentStringPBEConfig config = new EnvironmentStringPBEConfig();config.setPassword("mySecretKey");config.setAlgorithm("PBEWithMD5AndDES");config.setKeyObtentionIterations("1000");config.setPoolSize("2");config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");config.setIvGeneratorClassName("org.jasypt.iv.RandomIvGenerator");config.setStringOutputType("base64");encryptor.setConfig(config);return encryptor;}
}
6. 使用场景
6.1 保护数据库密码
在 application.yml
中加密数据库密码:
spring:datasource:url: jdbc:mysql://localhost:3306/mydbusername: rootpassword: ENC(h7J8K9L0M1N2O3P4Q5R6S7T8U9V0W1X2Y3Z4)
6.2 保护 API 密钥
在 application.yml
中加密 API 密钥:
api:key: ENC(h7J8K9L0M1N2O3P4Q5R6S7T8U9V0W1X2Y3Z4)
7. 注意事项
-
密钥管理:加密密钥应妥善保管,避免泄露。
-
加密算法:根据安全需求选择合适的加密算法。
-
性能影响:加密和解密操作会带来一定的性能开销,需根据实际情况评估。
---------------------------------------------------------------
Jasypt 配置详解
1、Jasypt 默认使用 StringEncryptor 解密属性,如果在 Spring 上下文中找不到自定义的 StringEncryptor,则使用如下默认值:
2、唯一需要的属性是 jasypt.encryptor.password ,其余的可以使用默认值。虽然所有这些属性都可以在属性文件中声明,但为了安全 password 属性官方不推荐存储在属性文件中,而应作为系统属性、命令行参数或环境变量传递。
方式一:作为程序启动时的命令行参数来带入
java -jar app.jar --jasypt.encryptor.password=xxxxxx
方式二:作为程序启动时的应用环境变量来带入
java -Djasypt.encryptor.password=xxxxxx -jar app.jar
方式三:作为系统环境变量的方式来带入
3、官网默认加解密算法为 "PBEWITHHMACSHA512ANDAES_256",它是 sha512 加 AES 高级加密,需要 Java JDK 1.9 及以上支持,或者添加 JCE 无限强度权限策略文件,否则运行会报错:加密引发异常,一个可能的原因是您正在使用强加密算法,并且您没有在这个Java虚拟机中安装Java加密扩展(JCE)无限强权限策略文件。此时换成 PBEWithMD5AndDES 算法即可,它是 md5 加 des 标准加密。
自定义加密器 StringEncryptor
1、所有的 StringEncryptor 属性,都可以在全局配置文件中进行配置。也可以在后台添加 StringEncryptor bean,此时默认的加密程序将被忽略。
2、相比之下这样安全性会更高一点,因为它没有在配置文件中直接暴露密钥。
import org.jasypt.encryption.StringEncryptor;
import org.jasypt.encryption.pbe.PooledPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author wangmaoxiong
* @version 1.0
* @date 2020/5/29 15:24
*/
@Configuration
public class AppConfig {
/**
* 自定义 StringEncryptor,覆盖默认的 StringEncryptor
* bean 名称是必需的,从 1.5 版开始按名称检测自定义字符串加密程序,默认 bean 名称为:jasyptStringEncryptor
*
* @return
*/
@Bean("jasyptStringEncryptor")
public StringEncryptor jasyptStringEncryptor() {
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
config.setPassword("wangmaox");
config.setAlgorithm("PBEWithMD5AndDES");
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);
return encryptor;
}
}
2、请注意,bean 名称是必需的,因为 jasypt spring boot 从 1.5 版开始按名称检测自定义字符串加密程序,默认 bean 名称为:jasyptStringEncryptor,但也可以通过定义属性来覆盖,例如 jasypt.encryptor.bean=encryptorBean,然后使用该名称定义自定义加密程序:
复制
@Bean("encryptorBean") public StringEncryptor stringEncryptor() { ... }
--------------------------------------------------------------
public class JasyptUtils {/*** {@link StringEncryptor} 加解密。* 同一个密钥(secretKey)对同一个内容执行加密,生成的密文都是不一样的,但是根据根据这些密文解密成明文都是可以.* 1、Jasypt 默认使用 {@link StringEncryptor} 来解密全局配置文件中的属性,所以提供密文时,也需要提供 {@link StringEncryptor} 加密的密文* 2、{@link StringEncryptor} 接口有很多的实现类,比如常用的 {@link PooledPBEStringEncryptor}* 3、setConfig(final PBEConfig config):为对象设置 {@link PBEConfig} 配置对象* 4、encrypt(final String message):加密内容* 5、decrypt(final String encryptedMessage):解密内容** @param secretKey :密钥。加/解密必须使用同一个密钥* @param message :加/解密的内容* @param isEncrypt :true 表示加密、false 表示解密* @return*/public static String stringEncryptor(String secretKey, String message, boolean isEncrypt) {PooledPBEStringEncryptor pooledPBEStringEncryptor = new PooledPBEStringEncryptor();pooledPBEStringEncryptor.setConfig(getSimpleStringPBEConfig(secretKey));String result = isEncrypt ? pooledPBEStringEncryptor.encrypt(message) : pooledPBEStringEncryptor.decrypt(message);return result;}/*** 设置 {@link PBEConfig} 配置对象,SimpleStringPBEConfig 是它的实现类* 1、所有的配置项建议与全局配置文件中的配置项保持一致,特别是 password、algorithm 等等选项,如果不一致,则应用启动时解密失败而报错.* 2、setPassword(final String password):设置加密密钥,必须与全局配置文件中配置的保存一致,否则应用启动时会解密失败而报错.* 3、setPoolSize(final String poolSize):设置要创建的加密程序池的大小.* 4、setAlgorithm(final String algorithm): 设置加密算法的值, 此算法必须由 JCE 提供程序支持* 5、setKeyObtentionIterations: 设置应用于获取加密密钥的哈希迭代次数。* 6、setProviderName(final String providerName):设置要请求加密算法的安全提供程序的名称* 7、setSaltGeneratorClassName:设置 Sal 发生器* 8、setIvGeneratorClassName:设置 IV 发生器* 9、setStringOutputType:设置字符串输出的编码形式。可用的编码类型有 base64、hexadecimal** @param secretKey* @return*/private static SimpleStringPBEConfig getSimpleStringPBEConfig(String secretKey) {SimpleStringPBEConfig config = new SimpleStringPBEConfig();config.setPassword(secretKey);config.setPoolSize("1");config.setAlgorithm("PBEWithMD5AndDES");config.setKeyObtentionIterations("1000");config.setProviderName("SunJCE");config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");config.setIvGeneratorClassName("org.jasypt.iv.RandomIvGenerator");config.setStringOutputType("base64");return config;}public static void main(String[] args) throws Exception {String message = "2268461750@qq.com";String password = "wangmaox";//一个同样的密码和秘钥,每次执行加密,密文都是不一样的。但是解密是没问题的。String jasyptEncrypt = stringEncryptor(password, message, true);System.out.println(jasyptEncrypt);String jasyptEncrypt1 = stringEncryptor(password, "UVgGJ4BAS8XrVNsamg60RO0ADCzdCKuR2+bvINv7Wyej3YTqVmxp5g1", false);System.out.println(jasyptEncrypt1);} }
---------------------------------------------------------------
一、Jasypt介绍
前言
在大多数项目中,配置文件中的 mysql 数据库密码、redis 密码等其他敏感性密码都是以明文形式存在,这种配置本身没有任何问题,但是,在某些情况下,可能会对公司造成不可挽救的损失,比如:某一天,小明因为加班过度,头脑发昏,不小心把公司项目上传到自己的GitHub 仓库里面了,导致的后果就是,公司数据库用户名密码泄露,被某些大佬加以利用…
所以,基于上面这种情况,加入配置文件中数据库用户密码等其他敏感信息都是经过加密处理过的呢???是不是可以大概率避免这种情况。Jasypt因此应运而生。
什么是Jasypt?
Jasypt 是一个 java 库,可以使开发者不需要太多操作来给 Java 项目添加基本加密功能,而且不需要知道加密原理。Jasypt为开发人员提供了一种简单易用加密功能,包括:密码认证、字符串加密等。
Jasypt 有哪些特点?
高安全性、基于标准的加密技术,适用于单向和双向加密。加密密码、文本、数字、二进制文件
文本加密与解密:Jasypt允许你加密字符串,并在需要时轻松解密回原始形式。这对于存储如数据库密码、API密钥等敏感信息非常有用。
密码器支持:它支持多种加密算法(如PBEWITHMD5ANDDES、PBEWITHSHA256AND256BITAES-CBC-BC等),并允许自定义加密策略。
配置文件加密:特别适用于Spring框架,Jasypt可以透明地解密在配置文件中加密的属性,比如数据库连接字符串中的密码。
环境感知:可以在不同的环境中(如开发、测试、生产)使用不同的加密策略和密钥,增强安全性。
无状态操作:Jasypt的加密操作不依赖于外部状态,使得它易于部署和使用。
集成友好:提供了与Spring框架的紧密集成,可以通过Spring Boot Starter轻松配置和使用。
哪些信息要加密呢?
一般来说,项目配置文件里,所有涉及信息安全的配置项(或字段)都应该做处理,典型的比如:
数据库密码,如mysql
第三方缓存中间件的密码,如 redis、mongodb
其他中间件,如消息中间件、zk、nacos等
各种第三方服务的 Access_Key
用途
安全存储配置信息:在配置文件中加密mysql、redis等数据库密码,防止明文泄露。
应用内加密逻辑:在应用内部对敏感数据进行加解密操作,例如用户密码的存储和验证。
日志安全:在记录包含敏感信息的日志前对其进行加密,确保日志安全。
数据交换安全:在不同系统间交换数据时,对数据进行加密传输,保障数据传输的安全性。
二、Springboot整合Jasypt
环境配置
SpringBoot2.0以上
Jasypt 3.0.3
jdk8
2.1 添加依赖
创建一个 Springboot 项目,项目版本 2.0 以上,并添加 Jasypt 相关依赖。
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
2.2 添加Jasypt配置
jasypt:
encryptor:
# 盐值
password: 123
# 指定加密方式
algorithm: PBEWithMD5AndDES
iv-generator-classname: org.jasypt.iv.NoIvGenerator
property:
# 标识为加密属性的前缀
prefix: ENC(
# 标识为加密属性的后缀
suffix: )
2.3 编写加/解密工具类
public class JasyptUtil {
/**
* PBE 算法
*/
public static final String PBE_ALGORITHMS_MD5_DES = "PBEWITHMD5ANDDES";
public static final String PBE_ALGORITHMS_MD5_TRIPLEDES = "PBEWITHMD5ANDTRIPLEDES";
public static final String PBE_ALGORITHMS_SHA1_DESEDE = "PBEWITHSHA1ANDDESEDE";
public static final String PBE_ALGORITHMS_SHA1_RC2_40 = "PBEWITHSHA1ANDRC2_40";
private JasyptUtil() {
}
/**
* Jasypt 加密
*
* @param encryptedStr 加密字符串
* @param password 盐值
* @return
*/
public static String encrypt(String encryptedStr, String password) {
return encrypt(encryptedStr, PBE_ALGORITHMS_MD5_DES, password);
}
/**
* Jasypt 加密
*
* @param encryptedStr 加密字符串
* @param algorithm 加密算法
* PBE ALGORITHMS: [PBEWITHMD5ANDDES, PBEWITHMD5ANDTRIPLEDES, PBEWITHSHA1ANDDESEDE, PBEWITHSHA1ANDRC2_40]
* @param password 盐值
* @return
*/
public static String encrypt(String encryptedStr, String algorithm, String password) {
// StandardPBEStringEncryptor、StandardPBEBigDecimalEncryptor、StandardPBEBigIntegerEncryptor、StandardPBEByteEncryptor
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
EnvironmentPBEConfig config = new EnvironmentPBEConfig();
// 指定加密算法
config.setAlgorithm(algorithm);
// 加密盐值
config.setPassword(password);
//config.setIvGeneratorClassName("org.jasypt.iv.NoIvGenerator");
encryptor.setConfig(config);
// 加密
return encryptor.encrypt(encryptedStr);
}
/**
* Jasypt 解密
*
* @param decryptStr 解密字符串
* @param password 盐值
* @return
*/
public static String decrypt(String decryptStr, String password) {
return decrypt(decryptStr, PBE_ALGORITHMS_MD5_DES, password);
}
/**
* Jasypt 解密
*
* @param decryptStr 解密字符串
* @param algorithm 指定解密算法:解密算法要与加密算法一一对应
* PBE ALGORITHMS: [PBEWITHMD5ANDDES, PBEWITHMD5ANDTRIPLEDES, PBEWITHSHA1ANDDESEDE, PBEWITHSHA1ANDRC2_40]
* @param password 盐值
* @return
*/
public static String decrypt(String decryptStr, String algorithm, String password) {
// StandardPBEStringEncryptor、StandardPBEBigDecimalEncryptor、StandardPBEBigIntegerEncryptor、StandardPBEByteEncryptor
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
EnvironmentPBEConfig config = new EnvironmentPBEConfig();
// 指定解密算法:解密算法要与加密算法一一对应
config.setAlgorithm(algorithm);
// 加密秘钥
config.setPassword(password);
//config.setIvGeneratorClassName("org.jasypt.iv.NoIvGenerator");
encryptor.setConfig(config);
// 解密
return encryptor.decrypt(decryptStr);
}
public static void main(String[] args) {
String encryptedStr = "I am the string to be encrypted";
String algorithm = PBE_ALGORITHMS_SHA1_RC2_40;
String password = "salt";
String str = JasyptUtil.encrypt(encryptedStr, algorithm, password);
System.out.println("加密后的字符串:" + str);
System.out.println("解密后的字符串:" + JasyptUtil.decrypt(str, algorithm, password));
}
}
2.4 修改配置文件
2.5 自定义加密器
在上面的内容中,使用的是默认的加密规则,这一点会让当自定义加密盐 (jasypt.encryptor.password) 泄漏时可能变得不安全。那么如何进一步防止密码泄露安全呢?
2.5.1 自定义加密器
为了进一步防止密码泄露,我们可以自定义加密规则。
自定义加密规则非常简单,只需要提供自定义的加密器配置类,然后通过jasypt.encryptor.bean配置指定加密配置类即可。
/**
* 自定义加密器
*/
public class MyStringEncryptor implements StringEncryptor {
/**
* 加解密PBE 算法
*/
public static final String PBE_ALGORITHMS_MD5_DES = "PBEWITHMD5ANDDES";
public static final String PBE_ALGORITHMS_MD5_TRIPLEDES = "PBEWITHMD5ANDTRIPLEDES";
public static final String PBE_ALGORITHMS_SHA1_DESEDE = "PBEWITHSHA1ANDDESEDE";
public static final String PBE_ALGORITHMS_SHA1_RC2_40 = "PBEWITHSHA1ANDRC2_40";
/**
* 加解密盐值
*/
private String password;
/**
* 加解密算法
*/
private String algorithm = PBE_ALGORITHMS_MD5_DES;
public MyStringEncryptor(String password) {
this.password = password;
}
public MyStringEncryptor(String password, String algorithm) {
this.password = password;
this.algorithm = algorithm;
}
@Override
public String encrypt(String message) {
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
// 加解密盐值
encryptor.setConfig(getConfig(this.password));
return encryptor.encrypt(message);
}
@Override
public String decrypt(String encryptedMessage) {
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
encryptor.setConfig(getConfig(this.password));
return encryptor.decrypt(encryptedMessage);
}
public SimpleStringPBEConfig getConfig(String password) {
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
// 加密盐值
config.setPassword(password);
// 加解密算法
config.setAlgorithm(PBE_ALGORITHMS_MD5_DES);
// 设置密钥获取迭代次数
config.setKeyObtentionIterations(1000);
// 线程池大小:默认1
config.setPoolSize(1);
// 盐值生成器className
config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
// iv(initialization vector,初始化向量) 生成器className
config.setIvGeneratorClassName("org.jasypt.iv.NoIvGenerator");
// 设置字符串输出类型
config.setStringOutputType("base64");
return config;
}
}
将自定义加密器添加到 Spring IoC 容器中。
@Configuration
public class JasyptConfig {
/**
* 加解密盐值
*/
@Value("${jasypt.encryptor.password}")
private String password;
// @Bean("jasyptStringEncryptor")
@Bean("myStringEncryptor")
public StringEncryptor myStringEncryptor() {
return new MyStringEncryptor(password);
}
}
修改配置文件
jasypt:
encryptor:
# 指定加解密在spring ioc容器中bean的名称,默认 jasyptStringEncryptor
bean: myStringEncryptor
# 盐值
password: 123
注意:Jasypt默认加解密器beanName为jasyptStringEncryptor,如果不想在配置文件中指定自定义加密器名称,需将自定义加密器beanName设置为jasyptStringEncryptor,否则将不生效。
————————————————