Encrypting Spring Boot Configuration with Jasypt – A Complete Guide
This article explains how to securely encrypt sensitive Spring Boot configuration properties such as database passwords using the Jasypt library, covering dependency setup, YAML configuration, encryption/decryption testing, custom encryptors, property detectors, resolvers, filters, and Maven plugin usage, all with practical code examples.
1. Overview
When using Spring Boot, sensitive information like database credentials is often stored in application.yml in plain text, which is insecure. Jasypt provides a simple way to encrypt these values and automatically decrypt them at runtime.
2. Simple Usage
2.1 Add Dependencies
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.4.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- web and test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<!-- jdbc -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- jasypt encryption -->
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>2.2 Configure application.yml
jasypt:
encryptor:
# encryption algorithm
algorithm: PBEWITHHMACSHA512ANDAES_256
# secret salt (should be supplied via env, CLI or system property)
password: jaspyt_password2.3 Encryption/Decryption Test
/**
* @author HLH
* @description Encryption/Decryption test
*/
@SpringBootTest
@RunWith(SpringRunner.class)
public class JasyptTest {
@Autowired
private StringEncryptor stringEncryptor;
/**
* Encryption test
*/
@Test
public void jasyptTest() {
// encrypt
System.out.println(stringEncryptor.encrypt("root")); // e.g. JSrINYe4IBotHndG...
// decrypt
System.out.println(stringEncryptor.decrypt("JSrINYe4IBotHndG...")); // root
}
/**
* Manual test using Jasypt API directly
*/
@Test
public void test() {
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")); // encrypted value
}
}3. Using Encrypted Value in DataSource
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.10.31/mp
username: root
# wrap the encrypted password with ENC()
password: ENC(R2H69h1aEgJ3EDPLXAVQ5CxZJWtl8EvqIJUtlATRt6om4w46/J+blu2JAvkR7Yvp)4. Jasypt Configuration Details
All configuration properties are defined in JasyptEncryptorConfigurationProperties . The only required property is the secret jasypt.encryptor.password ; other properties have sensible defaults.
5. Custom Encryption Bean
@Bean("jasyptStringEncryptor")
public StringEncryptor jasyptStringEncryptor(Singleton
configProps) {
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
JasyptEncryptorConfigurationProperties props = configProps.get();
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
config.setPassword(props.getPassword());
config.setAlgorithm(props.getAlgorithm());
config.setKeyObtentionIterations(props.getKeyObtentionIterations());
config.setPoolSize(props.getPoolSize());
config.setProviderName(props.getProviderName());
config.setSaltGeneratorClassName(props.getSaltGeneratorClassname());
config.setIvGeneratorClassName(props.getIvGeneratorClassname());
config.setStringOutputType(props.getStringOutputType());
encryptor.setConfig(config);
return encryptor;
}6. Custom Property Detector
The detector decides whether a property value is encrypted and extracts the raw value.
@Bean(name = "encryptablePropertyDetector")
public EncryptablePropertyDetector encryptablePropertyDetector() {
return new MyEncryptablePropertyDetector();
}
public class MyEncryptablePropertyDetector implements EncryptablePropertyDetector {
@Override
public boolean isEncrypted(String value) {
return value != null && value.startsWith("ENC@"); // custom rule
}
@Override
public String unwrapEncryptedValue(String value) {
return value.substring("ENC@".length());
}
}7. Custom Prefix/Suffix
If you only need a different prefix/suffix, modify application.yml :
jasypt:
encryptor:
algorithm: PBEWITHHMACSHA512ANDAES_256
password: jaspyt_password
property:
prefix: ENC(
suffix: )8. Custom Property Resolver
@Bean("encryptablePropertyResolver")
public EncryptablePropertyResolver encryptablePropertyResolver(StringEncryptor encryptor, EncryptablePropertyDetector detector) {
return new MyEncryptablePropertyResolver(encryptor, detector);
}
public class MyEncryptablePropertyResolver implements EncryptablePropertyResolver {
private final StringEncryptor encryptor;
private final EncryptablePropertyDetector detector;
public MyEncryptablePropertyResolver(StringEncryptor encryptor, EncryptablePropertyDetector detector) {
this.encryptor = encryptor;
this.detector = detector;
}
@Override
public String resolvePropertyValue(String value) {
return Optional.ofNullable(value)
.filter(detector::isEncrypted)
.map(v -> {
try {
String raw = detector.unwrapEncryptedValue(v.trim());
return encryptor.decrypt(raw);
} catch (EncryptionOperationNotPossibleException e) {
throw new DecryptionException("Unable to decrypt: " + value, e);
}
})
.orElse(value);
}
}9. Custom Property Filter
The filter can exclude certain property sources or keys from decryption.
@Bean(name = "encryptablePropertyFilter")
public EncryptablePropertyFilter encryptablePropertyFilter(Singleton
configProps) {
return new MyEncryptablePropertyFilter(configProps.get());
}
public class MyEncryptablePropertyFilter implements EncryptablePropertyFilter {
private final JasyptEncryptorConfigurationProperties props;
public MyEncryptablePropertyFilter(JasyptEncryptorConfigurationProperties props) { this.props = props; }
@Override
public boolean shouldInclude(PropertySource
source, String name) {
List
exclude = props.getProperty().getFilter().getExcludeNames();
List
include = props.getProperty().getFilter().getIncludeNames();
if (CollectionUtils.isEmpty(include) && CollectionUtils.isEmpty(exclude)) {
return true;
}
if (matches(source.getName(), exclude) || matches(name, exclude)) {
return false;
}
return CollectionUtils.isEmpty(include) || matches(source.getName(), include) || matches(name, include);
}
private boolean matches(String value, List
patterns) {
return value != null && !CollectionUtils.isEmpty(patterns) && patterns.stream().anyMatch(value::matches);
}
}10. Maven Plugin for Encryption/Decryption
10.1 Add Plugin
<build>
<plugins>
<!-- Jasypt Maven Plugin -->
<plugin>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-maven-plugin</artifactId>
<version>3.0.2</version>
</plugin>
</plugins>
</build>10.2 Encrypt a value
mvn jasypt:encrypt-value \
-Djasypt.encryptor.password="jaspyt_password" \
-Djasypt.plugin.value="root" \
-Djasypt.encryptor.algorithm="PBEWITHHMACSHA512ANDAES_256"The command prints the encrypted string, which can be placed inside ENC() in application.yml .
10.3 Decrypt a value
mvn jasypt:decrypt-value \
-Djasypt.encryptor.password="jaspyt_password" \
-Djasypt.plugin.value="
" \
-Djasypt.encryptor.algorithm="PBEWITHHMACSHA512ANDAES_256"This returns the original plain text.
11. Mind Map
The article concludes with a visual mind map summarising the whole Jasypt integration process.
Java Architect Essentials
Committed to sharing quality articles and tutorials to help Java programmers progress from junior to mid-level to senior architect. We curate high-quality learning resources, interview questions, videos, and projects from across the internet to help you systematically improve your Java architecture skills. Follow and reply '1024' to get Java programming resources. Learn together, grow together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.