jens
jens

Reputation: 1862

Jasypt out of maintenance? What to use for encryption with Spring Boot

Jasypt (https://github.com/jasypt/jasypt) and the according Spring Boot integration (https://github.com/ulisesbocchio/jasypt-spring-boot) do not really seem to be alive any longer.

What are current good practices for encrypting properties in Spring Boot applications using open source libraries? Simple solutions preferred.

Upvotes: 12

Views: 9621

Answers (4)

luooyii
luooyii

Reputation: 21

Many people mentioned spring cloud config, it is a good choice. But the usage of it has some change and it is quite heavy if I just want to use encryption. In my project, if I import spring-cloud-config, the output jar increased by 8m. After much trial and error, I've tried to summarize the best practices for using only encryption.

First if you just want to use encryption without any other requirements. You can just import spring-cloud-context. And it just increased 0.2m in my project. And in this way, you also need not to add config to skip config-center check.

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-context</artifactId>
</dependency>

And then configure password and salt, both are required. You can also generate your own salt with KeyGenerators.string().generateKey() For more info, refer to this page. https://docs.spring.io/spring-security/reference/features/integrations/cryptography.html

encrypt:
  key: your-password
  salt: ac89c61c7a21dd95

As for how to generate encrypted text. Spring CLI removed encryption command in latest version. And it is quite heavy to run a config server. And I wrote a code to generate them.

public class SecretEncryptor {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("Please input password:");
        String password = scanner.nextLine();
        System.out.print("Please input salt:");
        String salt = scanner.nextLine();
        TextEncryptor encryptor = Encryptors.text(password, salt);

        while (true) {
            System.out.println();
            System.out.print("Please input plain text:");
            String plainText = scanner.nextLine();
            System.out.println("Encrypted text: " + encryptor.encrypt(plainText));
        }
    }
}

And now, you can paste them to your spring configuration file in this format.

    password: '{cipher}17dae13ba67605b6cebd4651'

Upvotes: 1

blagerweij
blagerweij

Reputation: 3421

Spring Cloud has builtin support for decrypting properties. Any property that starts with {cipher}... will automatically be decrypted at runtime. Similar to jasypt, a 'master' encryption key is used. Configuring this key can be done by specifying encrypt.key in bootstrap.yaml or by specifying the ENCRYPT_KEY environment variable. Default uses symmetric encryption, but it's also possible to use asymmetric keys.

spring:
  datasource:
    password: {cipher}xxxxx

Encryption

To encrypt a value to ciphertext, there are different options:

  1. The Spring CLI had support for encrypting values: spring encrypt --key MySeCrEtMaStErKeY 'secretAPIkey' however spring cli support is now gone (since version 3).

  2. you could do it via this tooling

  3. simply use this Java snippet (see here)

  4. You can run Spring Cloud Config Server, and use the encrypt endpoint

Decryption

Then start your app (that needs to have a dependency to spring-cloud-starter-config) by specifying the master encryption key in bootstrap.yaml or using an environment variable:

ENCRYPT_KEY=MySeCrEtMaStErKeY java -jar myapp.jar

See https://docs.spring.io/spring-cloud-commons/docs/current/reference/html/#encryption-and-decryption

For more sophisticated setups, I highly recommend using Hashicorp Vault. It's open source and free to use.

Upvotes: 8

This dependency supported on LTS spring boot with java17.

<dependency>
        <groupId>com.github.ulisesbocchio</groupId>
        <artifactId>jasypt-spring-boot</artifactId>
        <version>3.0.5</version>
</dependency>

Run this Maven command to generate encrypted password.

mvn jasypt:encrypt-value -Djasypt.encryptor.password="the password" -Djasypt.plugin.value="theValueYouWantToEncrypt"

Upvotes: 0

shirdisai
shirdisai

Reputation: 43

blagerweij's answer is correct. I tried to follow his suggestion but I ran into an issue with the new version of the Spring Boot CLI and I'm trying to explain how I solved my issue. I'm just sharing my findings in case it helps anyone.

I'm using Spring Boot 2.7 for my project and I was trying to find a way to encrypt some sensitive data in the application.properties file. I did some research and found a couple of options.

a. Use the Jasypt library for encryption & decryption.

b. Use a key vault like Hashicorp or AWS Secrets manager

c. Write my own encryption and decryption function in Spring Boot. Run the sensitive data(e.g. database password) thru the encryption function and store the encrypted value in the application.properties file. Use the decryption function where required to decrypt the value.

Cons of each approach

a - Jasypt library is out of maintenance since end of 2022. This can be deduced from the maven repository.

b - AWS Secrets manager costs money. I'm helping an NGO on this project and we are trying to minimize cost without compromising on security. I did not research Hashicorp since my application is hosted on AWS.

c - Spring Boot uses autoconfiguration to configure the data source. So the decryption of the DB password stored in application.properties needs to happen during the autoconfiguration. Something similar needs to happen to decrypt the Oauth2 keys. I couldn't figure out a way to override the autoconfiguration and decrypt the sensitive data in the override.

I landed on this page after a lot of research and am very grateful to blagerweij for his post. He suggested using the Spring CLI to generate the encrypted password and Spring cloud library to do the decryption. So I tried it out. If you include the Spring cloud starter library in your dependencies, it automatically takes care of the decryption. I tried using the Spring Boot CLI to generate the encrypted password but the encrypt/decrypt options don't work with the new version of the CLI. Please refer to this link for more details - https://github.com/spring-cloud/spring-cloud-cli/issues/180

If you refer to the link above, there are a couple of suggestions to generate the encrypted password and one of them is the spring-crypto-cli. I used the spring-crypto-cli as mentioned in the link below to generate the encrypted password https://github.com/mptechnology/spring-crypto-cli

I then used this encrypted password in my application.properties file as follows. As shown, you need to prefix the encrypted value with {cipher}. This tells Spring that the value is encrypted and needs to be decrypted. spring.datasource.password={cipher}f480c675

I mentioned above that we need to use the spring-cloud-starter library in our project for decryption to happen automatically. The below link gives you the compatibility matrix between Spring Boot and the Spring cloud library. Since I'm using Spring Boot 2.7.0, I had to use the 2021.0.x version of the Spring cloud starter library and that is where this link helped me. https://spring.io/projects/spring-cloud/

Upvotes: 1

Related Questions