Search

Suggested keywords:
  • Java
  • Docker
  • Git
  • React
  • NextJs
  • Spring boot
  • Laravel

Spring Boot and Jasypt integration

  • Share this:

post-title

In this article, we will explore how to integrate Jasypt with Spring Boot. Developers used to have secure information like database username and password in the configuration files. The sensitive information has to be encrypted. In this article, we will explore how to manually and automatically encrypt sensitive data in the configuration files using Jasypt.

What is Jasypt?

Jasypt (Java Simplified Encryption) provides Java software utilities for encrypting user-sensitive data. With Jasypt, you don't need an in-depth understanding of cryptography to set it up. In a few simple steps, you will be able to use Jasypt. Default settings are recommended, but Jasypt does offer some customization options as well.

Steps To Add Encryption Using Jasypt:

Adding Jasypt Maven Dependency

Jasypt can be added to your project in the easiest way possible by using Maven.

Add the maven dependency to the pom.xml file, which can be found in the Maven Repository. In the version tag, you can specify what version you're using <version>YOUR_VERSION</version>.

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

 

Jasypt Maven Plugin

In order to simplify the encryption and decryption process, include jasypt-maven-plugin in the same pom.xml file as plugins. With this plugin, you can encrypt and decrypt property files compatible with Jasypt Spring Boot.

<plugin>
 <groupId>com.github.ulisesbocchio</groupId>
 <artifactId>jasypt-maven-plugin</artifactId>
 <version>3.0.3</version>
</plugin>

Jasypt-maven-plugin automates the encryption and decryption of property values during the build process by adding it to your project's build setup. It is especially useful in a development environment when you need to encrypt sensitive data for deployment or when you need to decrypt values for troubleshooting purposes without having to manually decrypt them.

 

Incorporating the @EnableEncryptableProperties annotation

Spring Boot applications use the @EnableEncryptableProperties annotation to enable encryption and decryption features provided by Jasypt. Adding this annotation to your main application class or any configuration class tells Spring Boot to process certain properties as encrypted and decrypt them with Jasypt before using them.

Add @EnableEncryptableProperties annotation to the main application class.

package com.jasypt.application;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties;
@SpringBootApplication
@EnableEncryptableProperties
public class JasyptIntegrationWithSpringBootApplication {
        public static void main(String[] args) {
                SpringApplication.run(JasyptIntegrationWithSpringBootApplication.class, args);
        }
}

 

Determining the secret key to be used for encryption and decryption

Using the secret key, the password is encrypted and later decrypted to reveal the actual password. The secret key can be any value you choose. In our case it would be blackslate

 

Decrypting & Encrypting Configuration Properties Manually With Jasypt

Let's encrypt a couple of sensitive configuration properties. In my application.properties file, I will add the following two properties.

spring.datasource.username=sa
spring.datasource.password=muthu

The next step is to save the changes and open a new terminal window. Change the current directory to the Spring Boot application's home folder in the terminal window. The pom.xml file should be visible if you list files in this directory.

To encrypt configuration properties, run the following command.

mvn jasypt:encrypt-value -Djasypt.encryptor.password=blacksalte -Djasypt.encryptor.algorithm=PBEWithMD5AndDES -Djasypt.plugin.value="sa"

Here’ is the breakdown of the command:

  1. mvn: It's the command-line tool you use to run Maven.
  2. jasypt:encrypt-value: Specifies the goal of using Jasypt to encrypt a value.
  3. -Djasypt.encryptor.password=blacksalte : Sets the encryption password for Jasypt to encrypt the value. In this case, the -D flag sets the jasypt.encryptor.password property to the specified value.
  4. Djasypt.encryptor.algorithm=PBEWithMD5AndDES : Specifies the encryption algorithm
  5. -Djasypt.plugin.value="sa": This specifies the value to be encrypted. Once again, the -D flag is used to pass a system property to the JVM, in this case setting the jasypt.plugin.value property to "sa".

As a result of running this command, the jasypt-maven-plugin uses Jasypt to encrypt the value of username property using the password 4iSPcV2oeTBVf8BEoXbsSM84gIID7p29z. The encrypted value will then be displayed in the console. Using this encrypted value in your application's configuration files prevents the plaintext from being revealed.

In the below image, just above the BUILD SUCCESS line you'll see the encrypted text within the bracket of the word ENC().

screenshot

Paste this whole text, including ENC and parathesis, in place of the original property value in application.properties.

In order to encrypt the password configuration property value, run the encrypt command one more time.

mvn jasypt:encrypt-value -Djasypt.encryptor.password=blacksalte -Djasypt.encryptor.algorithm=PBEWithMD5AndDES -Djasypt.plugin.value="muthu"

Copy the encrypted value to the application.properties file.

spring.datasource.username=ENC(cctzM9zxExk+ySHnpcsWDOQXBYaUHaTV)
spring.datasource.password=ENC(CXG5UyInw0/Dc4L1SZXKWmyUDnSgnZfl)

 

Automatically Encrypting Configuration Properties with Jasypt

To encrypt the username and password in the application.properties file without manually entering the encrypted text, follow the steps below.

Assume your original configuration looks like this

spring.datasource.username=sa
spring.datasource.password=muthu

To encrypt values, wrap them inside DEC() parenthesis as follows:

spring.datasource.username=DEC(sa)
spring.datasource.password=DEC(muthu)

In the same directory, open a command prompt and type

mvn jasypt:encrypt -Djasypt.encryptor.password=blackslate -Djasypt.encryptor.algorithm=PBEWithMD5AndDES

screenshot

This command replaces DEC() with ENC() and the encrypted text in between when you run it, as follows:

spring.datasource.username=ENC(pLDojxcVv4YsZXtrd168+QFPM2bsdMk3)
spring.datasource.password=ENC(oN1t9vkDmO5R77YDdRoI+7xH5YZwWIjf)

 

Manually Decrypting Encrypted Values

In order to manually decrypt configuration properties encrypted with Jasypt, run the mvn jasypt:decrypt-value command. An example would be:

mvn jasypt:decrypt-value -Djasypt.encryptor.password=blackslate-Djasypt.plugin.value="oN1t9vkDmO5R77YDdRoI+7xH5YZwWIjf"

Here's a breakdown of the command:

  1. mvn: Maven's command-line tool.
  2. jasypt:decrypt-value: A Maven goal that decrypts values using Jasypt.
  3. -Djasypt.encryptor.password=blackslate: This is the decryption password, which should match the encryption password.
  4. -Djasypt.plugin.value="oN1t9vkDmO5R77YDdRoI+7xH5YZwWIjf": The value to be decrypted.

 

Integrating Spring Boot Integration with Jasypt

Consider a scenario where we build a spring boot CRUD application and we need to store sensitive information such as database connection details.

For this reason, it is highly recommended that sensitive data in your configuration file be encrypted using the jasypt method as described above. Using the code below, you can perform CRUD operations

You will need the following dependencies to create your maven project. The following is the complete pom.xml with explanations. You can use the IDE or Spring Initializr to bootstrap your application.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>JasyptIntegrationWithSpringBoot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>JasyptIntegrationWithSpringBoot</name>
<description>Demo project for integrating Jasypt and Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Replace MySQL connector with SQL Server JDBC driver -->
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>9.2.1.jre11</version> <!-- Adjust the version according to your SQL Server version -->
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-maven-plugin</artifactId>
<version>3.0.3</version>
</plugin>
</plugins>
</build>
</project>

 

EntityClass

package com.jasypt.application.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "student")
public class Student {
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private int id;
   private String name;
   private int age;
}

StudentRepository.java

package com.jasypt.application.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.jasypt.application.entity.Student;
public interface StudentRepository extends JpaRepository<Student,Integer> {
        Student findByName(String name);
}

StudentService.java

package com.jasypt.application.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.jasypt.application.entity.Student;
import com.jasypt.application.repository.StudentRepository;
import java.util.List;

@Service
public class StudentService {
  @Autowired
   private StudentRepository studentRepository;
   public Student saveStudent(Student student) {
        return studentRepository.save(student);
   }

   public List<Student> saveStudents(List<Student> students) {
        return studentRepository.saveAll(students);
   }

  public List<Student> getStudents() {
    return studentRepository.findAll();
  }

   public Student getStudentById(int id) {
      return studentRepository.findById(id).orElse(null);
   }

   public Student getStudentByName(String name) {
       return studentRepository.findByName(name);
   }

   public String deleteStudent(int id) {
        studentRepository.deleteById(id);
       return "student removed !! " + id;
   }

   public Student updateStudent(Student student) {
        Student existingStudent = studentRepository.findById(student.getId()).orElse(null);
        existingStudent.setName(student.getName());
        existingStudent.setAge(student.getAge());
        return studentRepository.save(existingStudent);
   }
}

StudentController.java

package com.jasypt.application.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.jasypt.application.entity.Student;
import com.jasypt.application.service.StudentService;
@RestController
@RequestMapping("/api")
public class StudentController {
         @Autowired
         private StudentService studentService;
         @PostMapping("/addStudent")
         public Student addStudent(@RequestBody Student student) {
         return studentService.saveStudent(student);
         }
         @PostMapping("/addStudents")
         public List<Student> addStudents(@RequestBody List<Student> students) {
         return studentService.saveStudents(students);
         }
         @GetMapping("/students")
         public List<Student> findAllStudents() {
         return studentService.getStudents();
         }
         @GetMapping("/studentById/{id}")
         public Student findStudentById(@PathVariable int id) {
         return studentService.getStudentById(id);
         }
         @GetMapping("/student/{name}")
         public Student findStudentByName(@PathVariable String name) {
         return studentService.getStudentByName(name);
         }
         @PutMapping("/update")
         public Student updateStudent(@RequestBody Student student) {
         return studentService.updateStudent(student);
         }
         @DeleteMapping("/delete/{id}")
         public String deleteStudent(@PathVariable int id) {
         return studentService.deleteStudent(id);
         }
}

JasyptEncryptorConfig.java

package com.jasypt.application.config;
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;

@Configuration
public class JasyptEncryptorConfig {

	@Bean(name = "jasyptStringEncryptor")
	public StringEncryptor passwordEncryptor(){
		PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
		SimpleStringPBEConfig config = new SimpleStringPBEConfig();
		config.setPassword("blackslate"); // encryptor's private key
		config.setAlgorithm("PBEWithMD5AndDES");
		config.setKeyObtentionIterations("1000");
		config.setPoolSize("1");
		config.setProviderName("SunJCE");
		config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
		config.setStringOutputType("base64");
		encryptor.setConfig(config);
		return encryptor;
	}
}

The above code defines a configuration class for setting up Jasypt encryption in a Spring Boot application. It declares a bean named jasyptStringEncryptor of type StringEncryptor and configures it using PooledPBEStringEncryptor with a SimpleStringPBEConfig. The configuration includes specifying the password (private key) used for encryption, the encryption algorithm (PBEWithMD5AndDES), key obtention iterations, pool size, provider name, salt generator, and string output type. The configured encryptor is then returned as a bean. This configuration ensures that Jasypt encryption is properly set up with the specified parameters in the Spring Boot application, providing a mechanism for secure string encryption and decryption.

 

Application Configuration

spring.datasource.url=jdbc:sqlserver://localhost:1433;databaseName=student_details
spring.datasource.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.datasource.username=ENC(cctzM9zxExk+ySHnpcsWDOQXBYaUHaTV)
spring.datasource.password=ENC(CXG5UyInw0/Dc4L1SZXKWmyUDnSgnZfl)
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.SQLServerDialect
server.port=9090

 

Demo ScreenShots

When we run the application, secure credentials in the configuration files will be decrypted and it will be used to connect to the database. Let's make few API calls and see if the data is actually stored in the DB.

Add Student

When we hit http://localhost:9090/api/addStudent a candidate will be inserted. I would also add Annamalai following the same process

screenshot

 

Get Student

When we hit  http://localhost:9090/api/students we will get all the candidates added

screenshot

 

The records added in the student table created in sql

screenshot

 

Conclusion

In this article, we explained what is Jasypt and how it can be integrated with Spring Boot using an example.

Muthu Annamalai

About author
Technical Writer | Pre-Final Year Student | Code & Community | Developer who works everyday to improve himself.