一、概述
Jasypt 这个Java类包为开发人员提供一种简单的方式来为项目增加加密功能,包括:密码Digest认证,文本和对象加密,集成 hibernate,Spring Security(Acegi)来增强密码管理。
Jasypt是一个Java库,可以使开发者不需太多操作来给Java项目添加基本加密功能,而且不需要知道加密原理。
根据Jasypt文档,该技术可用于加密任务与应用程序,例如加密密码、敏感信息和数据通信、创建完整检查数据的sums. 其他性能包括高安全性、基于标准的加密技术、可同时单向和双向加密的加密密码、文本、数字和二进制文件。Jasypt也可以与Acegi Security整合也即Spring Security。Jasypt亦拥有加密应用配置的集成功能,而且提供一个开放的API从而任何一个Java Cryptography Extension都可以使用Jasypt。
Jasypt还符合RSA标准的基于密码的加密,并提供了无配置加密工具以及新的、高可配置标准的加密工具。
1、该开源项目可用于加密任务与应用程序,例如加密密码、敏感信息和数据通信
2、还包括高安全性、基于标准的加密技术、可同时单向和双向加密的加密密码、文本、数字和二进制文件。
3、Jasypt还符合RSA标准的基于密码的加密,并提供了无配置加密工具以及新的、高可配置标准的加密工具。
4、加密属性文件(encryptable properties files)、Spring work集成、加密Hibernate数据源配置、新的命令行工具、URL加密的Apache wicket集成以及升级文档。
5、Jasypt也可以与Acegi Security整合也即Spring Security。Jasypt亦拥有加密应用配置的集成功能,而且提供一个开放的API从而任何一个Java Cryptography Extension都可以使用Jasypt。
二、使用
2.1、jar使用
shell下jar使用
Maven下载好的jar包加密\Maven\org\jasypt\jasypt\1.9.3\jasypt-1.9.3.jar
java -cp jasypt-1.9.3.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI password=G0CvDz7oJn6 algorithm=PBEWithMD5AndDES input=root
input:你要解密的字符串(这里是上面生成的密文)
password:口令(加密过程一样的字符串,现在知道这个有什么用了吧)
algorithm:加密算法(输入加密过程一样的算法)
OUTPUT:下面的字符串就是生成的明文,可以那来对比加密前的字符串
2.2、代码方式1-原生
2.2.1、加密解密-文本原生使用
<dependency>
<groupId>org.jasypt</groupId>
<artifactId>jasypt</artifactId>
<version>1.9.3</version>
</dependency>
示例
public class BasicTextEncryptorTest {
BasicTextEncryptor textEncryptor;
@Before
public void setUp() {
textEncryptor = new BasicTextEncryptor();
textEncryptor.setPassword("EbfYkitulv73I2p0mXI50JMXoaxZTKJ7");
}
@Test
public void encrypt() {
// 加密
System.out.println(textEncryptor.encrypt("root@1234"));
//TJetNWzmC4os1CCb+gHtz+5MpL9NFMML
//KCTSu/Dv1elE1A/ZyppCHgJAAwKiez/p
}
@Test
public void decyptPwd() {
// 解密
// root@1234
System.out.println(textEncryptor.decrypt("TJetNWzmC4os1CCb+gHtz+5MpL9NFMML"));
// root@1234
System.out.println(textEncryptor.decrypt("KCTSu/Dv1elE1A/ZyppCHgJAAwKiez/p"));
}
}
2.2.2、单向散列
一般在做用户认证的时候,通常会使用MD5做简单的散列,然后登录时必须MD5值实现。同样的需求,也可以使用Jasypt来实现。
BasicPasswordEncryptor
@Test
public void encrypt() {
BasicPasswordEncryptor textEncryptor = new BasicPasswordEncryptor();
String encryptPassword = textEncryptor.encryptPassword("EbfYkitulv73I2p0mXI50JMXoaxZTKJ7");
System.out.println(encryptPassword);
boolean checkPassword = textEncryptor.checkPassword("EbfYkitulv73I2p0mXI50JMXoaxZTKJ7", encryptPassword);
System.out.println(checkPassword);
}
2.2.3、多线程加解密
在多核机器上运行时,我们希望并行处理解密处理。为了获得良好的性能,我们可以使用PooledPBEStringEncryptor 和setPoolSize() API来创建一个解密线程池。它们中的每一个都可以由不同的线程并行使用:
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
encryptor.setPoolSize(4);
encryptor.setPassword("some-random-data");
encryptor.setAlgorithm("PBEWithMD5AndTripleDES");
最好将池大小设置为等于机器的核心数。加密和解密的代码与以前的代码相同。
2.3、代码方式2-springboot结合
源码地址:https://github.com/ulisesbocchio/jasypt-spring-boot
pom
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.1</version>
</dependency>
增加JasyptConfig 配置类
@Configuration
public class JasyptConfig {
@Bean("jasyptStringEncryptor")
public StringEncryptor stringEncryptor() {
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
config.setPassword("EbfYkitulv73I2p0mXI50JMXoaxZTKJ7");
// config.setAlgorithm("PBEWithMD5AndDES");//默认配置
// config.setKeyObtentionIterations("1000");//默认配置
config.setPoolSize("4");
// config.setProviderName("SunJCE");//默认配置
// config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");//默认配置
// config.setStringOutputType("base64");//默认配置
encryptor.setConfig(config);
return encryptor;
}
}
配置文件的写入和Spring XML的基本类似。application.yml相当于applicationContext.xml,security.properties就是要进行属性替换的配置文件。
application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/abc?useSSL=false
spring.datasource.username=root
spring.datasource.password=${jdbc.password}
security.properties
jdbc.password=ENC(TJetNWzmC4os1CCb+gHtz+5MpL9NFMML)
启动类增加
@SpringBootApplication
@EnableEncryptableProperties
@PropertySource(value = {"classpath:security.properties"},ignoreResourceNotFound = false)
public class SpringRunnerMain {
public static void main(String[] args) {
SpringApplication.run(SpringRunnerMain.class, args);
}
}
2.4、关于这个口令的配置方式
jasypt的作者建议是把这个盐值放在系统属性、命令行或是环境变量来使用,而不是放在配置文件
还有种常用方式,直接配置方式(这样口令就暴露在这个配置文件里面,不建议);密文使用ENC(……),密钥放在代码中,配置分开
1、启动命令
jar: 命令:java -Djasypt.encryptor.password=jasypt -jar xxx.jar
war:到Tomcat的bin目录下,打开文件catalina.bat/catalina.sh,添加如下参数,然后保存:window:set JAVA_OPTS="-Djasypt.encryptor.password=jasypt" , Linux:JAVA_OPTS="-Djasypt.encryptor.password=jasypt"
或者直接在tomcat bin 目录新建setenv.bat setenv.sh
文件内容如下
Windows:set JAVA_OPTS="-Djasypt.encryptor.password=jasypt"
Linux:export JAVA_OPTS="-Djasypt.encryptor.password=jasypt"
程序会默认使用。
2、获取环境变量
Properties properties = System.getProperties();
Set<Object> objects = properties.keySet();
for (Object object : objects) {
System.out.println("key:" + object + "---:" + properties.get(object));
}
Map<String, String> getenv = System.getenv();
for (Map.Entry<String, String> entry : getenv.entrySet()) {
System.out.println(entry.getKey() + "---:" + entry.getValue());
}
三、核心类库说明
3.1、加密工具类【以文本text为例】
普通文本实现了如下三种方式

以及参看Strong,AES,只是算法不一致
BasicTextEncryptor→PBEWithMD5AndDES
StrongTextEncryptor→PBEWithMD5AndTripleDES
AES256TextEncryptor→PBEWithHMACSHA512AndAES_256
主要是【参看BasicTextEncryptor】
public final class BasicTextEncryptor implements TextEncryptor {
private final StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
public BasicTextEncryptor() {
this.encryptor.setAlgorithm("PBEWithMD5AndDES");
}
public void setPassword(String password) {
this.encryptor.setPassword(password);
}
public void setPasswordCharArray(char[] password) {
this.encryptor.setPasswordCharArray(password);
}
public String encrypt(String message) {
return this.encryptor.encrypt(message);
}
public String decrypt(String encryptedMessage) {
return this.encryptor.decrypt(encryptedMessage);
}
}
更多pbe算法可以参看:java-信息安全(三)-PBE加密算法
参看上述工具类编写方式,以及上述PBE加密算法,编写:PBEWITHSHA1ANDRC4_128 工具类:RC128TextEncryptor

public class RC128TextEncryptor implements TextEncryptor {
private final StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
public RC128TextEncryptor() {
this.encryptor.setAlgorithm("PBEWITHSHA1ANDRC4_128");
}
public void setPassword(String password) {
this.encryptor.setPassword(password);
}
public void setPasswordCharArray(char[] password) {
this.encryptor.setPasswordCharArray(password);
}
public String encrypt(String message) {
return this.encryptor.encrypt(message);
}
public String decrypt(String encryptedMessage) {
return this.encryptor.decrypt(encryptedMessage);
}
}
测试:

public class RC128TextEncryptorTest {
RC128TextEncryptor textEncryptor;
@Before
public void setUp() {
textEncryptor = new RC128TextEncryptor();
textEncryptor.setPassword("EbfYkitulv73I2p0mXI50JMXoaxZTKJ7");
}
@Test
public void encrypt() {
// 加密
System.out.println(textEncryptor.encrypt("root@1234"));
//zjhmIP38jmvob56qyNevHjs=
//iMX2aR70CkLGdtlAdhe2XKI=
}
@Test
public void decyptPwd() {
// 解密
// root@1234
System.out.println(textEncryptor.decrypt("zjhmIP38jmvob56qyNevHjs="));
// root@1234
System.out.println(textEncryptor.decrypt("iMX2aR70CkLGdtlAdhe2XKI="));
}
}
综上所述,所有算法核心是调用:StandardPBEStringEncryptor
3.2、StandardPBEStringEncryptor说明

public final class StandardPBEStringEncryptor implements PBEStringCleanablePasswordEncryptor {
private static final String MESSAGE_CHARSET = "UTF-8";
private static final String ENCRYPTED_MESSAGE_CHARSET = "US-ASCII";
public static final String DEFAULT_STRING_OUTPUT_TYPE = "base64";
private StringPBEConfig stringPBEConfig = null;
private String stringOutputType = "base64";
private boolean stringOutputTypeBase64 = true;
private boolean stringOutputTypeSet = false;
private final StandardPBEByteEncryptor byteEncryptor;
private final Base64 base64;
public StandardPBEStringEncryptor() {
this.byteEncryptor = new StandardPBEByteEncryptor();
this.base64 = new Base64();
}
private StandardPBEStringEncryptor(StandardPBEByteEncryptor standardPBEByteEncryptor) {
this.byteEncryptor = standardPBEByteEncryptor;
this.base64 = new Base64();
}
public synchronized void setConfig(PBEConfig config) {
this.byteEncryptor.setConfig(config);
if (config != null && config instanceof StringPBEConfig) {
this.stringPBEConfig = (StringPBEConfig)config;
}
}
public void setAlgorithm(String algorithm) {
this.byteEncryptor.setAlgorithm(algorithm);
}
public void setPassword(String password) {
this.byteEncryptor.setPassword(password);
}
public void setPasswordCharArray(char[] password) {
this.byteEncryptor.setPasswordCharArray(password);
}
public void setKeyObtentionIterations(int keyObtentionIterations) {
this.byteEncryptor.setKeyObtentionIterations(keyObtentionIterations);
}
public void setSaltGenerator(SaltGenerator saltGenerator) {
this.byteEncryptor.setSaltGenerator(saltGenerator);
}
public void setIvGenerator(IvGenerator ivGenerator) {
this.byteEncryptor.setIvGenerator(ivGenerator);
}
public void setProviderName(String providerName) {
this.byteEncryptor.setProviderName(providerName);
}
public void setProvider(Provider provider) {
this.byteEncryptor.setProvider(provider);
}
public synchronized void setStringOutputType(String stringOutputType) {
CommonUtils.validateNotEmpty(stringOutputType, "String output type cannot be set empty");
if (this.isInitialized()) {
throw new AlreadyInitializedException();
} else {
this.stringOutputType = CommonUtils.getStandardStringOutputType(stringOutputType);
this.stringOutputTypeSet = true;
}
}
synchronized StandardPBEStringEncryptor[] cloneAndInitializeEncryptor(int size) {
StandardPBEByteEncryptor[] byteEncryptorClones = this.byteEncryptor.cloneAndInitializeEncryptor(size);
this.initializeSpecifics();
StandardPBEStringEncryptor[] clones = new StandardPBEStringEncryptor[size];
clones[0] = this;
for(int i = 1; i < size; ++i) {
clones[i] = new StandardPBEStringEncryptor(byteEncryptorClones[i]);
if (CommonUtils.isNotEmpty(this.stringOutputType)) {
clones[i].setStringOutputType(this.stringOutputType);
}
}
return clones;
}
public boolean isInitialized() {
return this.byteEncryptor.isInitialized();
}
public synchronized void initialize() {
if (!this.isInitialized()) {
this.initializeSpecifics();
this.byteEncryptor.initialize();
}
}
private void initializeSpecifics() {
if (this.stringPBEConfig != null) {
String configStringOutputType = this.stringPBEConfig.getStringOutputType();
this.stringOutputType = !this.stringOutputTypeSet && configStringOutputType != null ? configStringOutputType : this.stringOutputType;
}
this.stringOutputTypeBase64 = "base64".equalsIgnoreCase(this.stringOutputType);
}
public String encrypt(String message) {
if (message == null) {
return null;
} else {
if (!this.isInitialized()) {
this.initialize();
}
try {
byte[] messageBytes = message.getBytes("UTF-8");
byte[] encryptedMessage = this.byteEncryptor.encrypt(messageBytes);
String result = null;
if (this.stringOutputTypeBase64) {
encryptedMessage = this.base64.encode(encryptedMessage);
result = new String(encryptedMessage, "US-ASCII");
} else {
result = CommonUtils.toHexadecimal(encryptedMessage);
}
return result;
} catch (EncryptionInitializationException var5) {
throw var5;
} catch (EncryptionOperationNotPossibleException var6) {
throw var6;
} catch (Exception var7) {
throw new EncryptionOperationNotPossibleException();
}
}
}
public String decrypt(String encryptedMessage) {
if (encryptedMessage == null) {
return null;
} else {
if (!this.isInitialized()) {
this.initialize();
}
try {
byte[] encryptedMessageBytes = null;
byte[] encryptedMessageBytes;
if (this.stringOutputTypeBase64) {
encryptedMessageBytes = encryptedMessage.getBytes("US-ASCII");
encryptedMessageBytes = this.base64.decode(encryptedMessageBytes);
} else {
encryptedMessageBytes = CommonUtils.fromHexadecimal(encryptedMessage);
}
byte[] message = this.byteEncryptor.decrypt(encryptedMessageBytes);
return new String(message, "UTF-8");
} catch (EncryptionInitializationException var4) {
throw var4;
} catch (EncryptionOperationNotPossibleException var5) {
throw var5;
} catch (Exception var6) {
throw new EncryptionOperationNotPossibleException();
}
}
}
}
这里涉及了具体加密解密实现逻辑。
直接初始化调用

public class StandardPBEStringEncryptorTest {
StandardPBEStringEncryptor textEncryptor;
@Before
public void setUp() {
textEncryptor = new StandardPBEStringEncryptor();
// textEncryptor.setAlgorithm("");//自行指定
textEncryptor.setPassword("EbfYkitulv73I2p0mXI50JMXoaxZTKJ7");
}
@Test
public void encrypt() {
// 加密
System.out.println(textEncryptor.encrypt("root@1234"));
//Han0rFt6K2jhvrK5swPpD/ctoUMPckIO
//upkr4Rc6bhmpUXhdRoT9qqkhiSfEhTvS
}
@Test
public void decyptPwd() {
// 解密
// root@1234
System.out.println(textEncryptor.decrypt("Han0rFt6K2jhvrK5swPpD/ctoUMPckIO"));
// root@1234
System.out.println(textEncryptor.decrypt("upkr4Rc6bhmpUXhdRoT9qqkhiSfEhTvS"));
}
}
3.3、上述2.3使用池化方式
来源:https://www.cnblogs.com/bjlhx/p/12229296.html
