Background

When building a web application, we eventually have to connect to a database to retrieve data and to update data. One thing we don’t want to experience is having our database password leaked. Cloud providers solve this issue by providing a service to store sensitive information (e.g., AWS Secrets Manager). We need to explore an alternative solution to avoid reliance on external services. I researched two Java libraries that allow us to store sensitive data: Jasypt and dotenv.

Jasypt

Jasypt (Java Simplified Encryption) is a library that allows us to encrypt data easily. By using its Spring Boot integration library, we can securely store encrypted passwords in the application.properties file. This way, we don’t have to worry about having our passwords exposed.

Jasypt Integration

The example below uses jasypt-spring-boot v3.0.5

To use Jasypt in a Spring Boot project, we have to import the library. In the pom.xml file, add this code:

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

We need to import the jasypt maven plugin to generate a password. Add this to the plugin section in pom.xml:

1
2
3
4
5
6
7
8
<plugins>
    <plugin>
        <groupId>com.github.ulisesbocchio</groupId>
        <artifactId>jasypt-maven-plugin</artifactId>
        <version>3.0.5</version>
    </plugin>
    ...
</plugins>

To generate the password, run this command in the terminal:

mvn jasypt:encrypt-value -Djasypt.encryptor.password="foo" -Djasypt.plugin.value="bar" -Djasypt.encryptor.algorithm=PBEWITHHMACSHA512ANDAES_256

In this example, the command will generate an encrypted string of input bar using Jasypt password foo and algorithm PBEWITHHMACSHA512ANDAES_256.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
  @Bean(name="encryptorBean")
  public StringEncryptor stringEncryptor() {
    PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
    SimpleStringPBEConfig config = new SimpleStringPBEConfig();
    config.setPassword("foo");
    config.setPoolSize(1);
    config.setAlgorithm("PBEWITHHMACSHA512ANDAES_256");
    config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
    config.setIvGeneratorClassName("org.jasypt.iv.RandomIvGenerator");
    config.setStringOutputType("base64");
    config.setKeyObtentionIterations(1000);

    encryptor.setConfig(config);
    return encryptor;
  }

In this code, we create a Jasypt string encryptor bean with a password foo. To use this bean as the Jasypt encryptor, add this line in the application.properties file:

jasypt.encryptor.bean=encryptorBean

Then, we can use the encrypted password as a value in the application.properties file:

spring.datasource.username=postgres
spring.datasource.password=ENC(zTdPfmM+TLuXbPVUBlrQ0PIvDxdz8PDxFfSNc7P8qHOE03PSpXwUrazHLtYNfwn5)

Dotenv

Dotenv is the library that we also use in frontend to store configuration data in a .env file. When an application starts, it will append the values inside .env file into the system environment variables.

Dotenv Integration

The example below uses spring-dotenv 4.0.0

We have to import the library to use dotenv in Spring Boot. In pom.xml, add this line:

1
2
3
4
5
<dependency>
  <groupId>me.paulschwarz</groupId>
  <artifactId>spring-dotenv</artifactId>
  <version>4.0.0</version>
</dependency>

Remember to include .env in the .gitignore file.

Then, create a .env file inside the project’s main folder. In this case, we can store the username and password of PostgreSQL by writing:

PG_USERNAME=foo
PG_PASSWORD=bar

in the .env file.

Finally, we can replace the username and password value inside application.properties by using the value above.

spring.datasource.username=${PG_USERNAME}
spring.datasource.password=${PG_PASSWORD}

Which One is Better ?

After using both libraries, I conclude that using dotenv is a better choice. Although jasypt enables us to store encrypted information, it may still expose the information to the public (e.g., pushing the application.properties file to Github). In contrast, dotenv stores it in a file that external parties do not have access to. Integrating the library also requires less effort.