About this Tutorial
This tutorial will show you how to use Jasypt
hibernate integration to transparently encrypt database columns.
Jasypt is a java library which allows developers to add basic encryption capabilities to their projects with minimum effort, and without the need of having deep knowledge on how cryptography works.
- High-security, standards-based encryption techniques, both for unidirectional and bidirectional encryption. Encrypt passwords, texts, numbers, binaries...
- Transparent integration with Hibernate.
- Suitable for integration into Spring-based applications and also transparently integrable with ACEGI (Spring Security).
Jasypt provides an integration package (org.jasypt.hibernate.type) which provides several Hibernate UserType implementations to allow one or several of the properties in a mapped Hibernate entity to be declared as being of an encrypted type. Types allowed to be stored encrypted include strings, binaries (byte arrays), numeric types, booleans and dates.
Persistence of those properties will be done in an encrypted manner, but in a completely transparent way for the application.
This can be useful for encrypting personal data, private messages, etc, so that it is avoided that anyone with read access to the "critical" tables can read all of its contents.
But encryption sets some limitations on your Hibernate usage:
- encrypted properties can not be used as part of projection queries (SUM, MAX, ..) as this is done on the database before decryption by hibernate.
- encrypted properties can not also be part of an ORDER BY clause.
- for encrypted properties to appear on a WHERE clause, their encryptor must be configured to use a fixed SaltGenerator
Please see Jasypt
for more information.
 | This tutorial assumes you are using Hibernate as your persistence framework and have already completed the Persistence and Using Hibernate tutorials. |
Table of Contents
- Adding Jasypt as a dependency to your proyect
- Defining hibernate encrypted Types
- Registering Jasypt encryptors as Spring beans
- Annotating encrypted properties
- Setting encryption password as environment variable
Adding Jasypt as a dependency to your project
First is adding Jasypt library as a dependency to your project. For that you need to locate <dependencies /> section on your pom.xml.
Once located add the following lines:
<dependency>
<groupId>org.jasypt</groupId>
<artifactId>jasypt</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.3</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.3</version>
</dependency>
Defining hibernate encrypted Types
Jasypt uses custom Hibernate UserTypes to provide transparent encryption of your data. For this you can create src/main/resources/jasyptHibernateTypes.hbm.xml and add the following configuration:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-
"http:>
<hibernate-mapping>
<!-- VARCHAR, CLOB, TEXT based types -->
<typedef name="encryptedString" class="org.jasypt.hibernate.type.EncryptedStringType">
<param name="encryptorRegisteredName">jasyptHibernateEncryptor</param>
</typedef>
<typedef name="encryptedBigDecimalAsString" class="org.jasypt.hibernate.type.EncryptedBigDecimalAsStringType">
<param name="encryptorRegisteredName">jasyptHibernateEncryptor</param>
</typedef>
<typedef name="encryptedBigIntegerAsString" class="org.jasypt.hibernate.type.EncryptedBigIntegerAsStringType">
<param name="encryptorRegisteredName">jasyptHibernateEncryptor</param>
</typedef>
<typedef name="encryptedBooleanAsString" class="org.jasypt.hibernate.type.EncryptedBooleanAsStringType">
<param name="encryptorRegisteredName">jasyptHibernateEncryptor</param>
</typedef>
<typedef name="encryptedByteAsString" class="org.jasypt.hibernate.type.EncryptedByteAsStringType">
<param name="encryptorRegisteredName">jasyptHibernateEncryptor</param>
</typedef>
<typedef name="encryptedCalendarAsString" class="org.jasypt.hibernate.type.EncryptedCalendarAsStringType">
<param name="encryptorRegisteredName">jasyptHibernateEncryptor</param>
</typedef>
<typedef name="encryptedDateAsString" class="org.jasypt.hibernate.type.EncryptedDateAsStringType">
<param name="encryptorRegisteredName">jasyptHibernateEncryptor</param>
</typedef>
<typedef name="encryptedDoubleAsString" class="org.jasypt.hibernate.type.EncryptedDoubleAsStringType">
<param name="encryptorRegisteredName">jasyptHibernateEncryptor</param>
</typedef>
<typedef name="encryptedFloatAsString" class="org.jasypt.hibernate.type.EncryptedFloatAsStringType">
<param name="encryptorRegisteredName">jasyptHibernateEncryptor</param>
</typedef>
<typedef name="encryptedIntegerAsString" class="org.jasypt.hibernate.type.EncryptedIntegerAsStringType">
<param name="encryptorRegisteredName">jasyptHibernateEncryptor</param>
</typedef>
<typedef name="encryptedLongAsString" class="org.jasypt.hibernate.type.EncryptedLongAsStringType">
<param name="encryptorRegisteredName">jasyptHibernateEncryptor</param>
</typedef>
<typedef name="encryptedShortAsString" class="org.jasypt.hibernate.type.EncryptedShortAsStringType">
<param name="encryptorRegisteredName">jasyptHibernateEncryptor</param>
</typedef>
<!-- VARBINARY, BLOB based type -->
<typedef name="encryptedBinary" class="org.jasypt.hibernate.type.EncryptedBinaryType">
<param name="encryptorRegisteredName">jasyptByteHibernateEncryptor</param>
</typedef>
<!-- NUMERIC, NUMBER based types -->
<typedef name="encryptedBigDecimal" class="org.jasypt.hibernate.type.EncryptedBigDecimalType">
<param name="encryptorRegisteredName">jasyptBigDecimalHibernateEncryptor</param>
</typedef>
<typedef name="encryptedBigInteger" class="org.jasypt.hibernate.type.EncryptedBigIntegerType">
<param name="encryptorRegisteredName">jasypBigIntegertHibernateEncryptor</param>
</typedef>
</hibernate-mapping>
Open src/main/resources/hibernate.cfg.xml for the basic archetypes (or core/src/main/resources/hibernate.cfg.xml for the modular archetypes) and register this file with the following XML:
<mapping resource="jasyptHibernateTypes.hbm.xml"/>
This sample file includes all encrypted types supported by Jasypt 1.2, you can safely remove those you are not planning to use.
It also assumes that you are planing to use a single String encryptor shared between VARCHAR based types, you will register on the next section.
Registering Jasypt encriptors as Spring beans
Now you'll create Jasypt encryptors that will be used by hibernate encrypted UserTypes you just defined on previous section. Open src/main/webapp/WEB-INF/applicationContext.xml (or core/src/main/resources/applicationContext.xml for a modular archetype) and add the following to it:
<bean id="stringEncryptor" class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor" lazy-init="false">
<property name="algorithm" value="PBEWithMD5AndDES" />
<property name="password" value="${jasypt_password}" />
</bean>
<bean id="hibernateEncryptor" class="org.jasypt.hibernate.encryptor.HibernatePBEStringEncryptor" lazy-init="false">
<!-- This property value must match "encryptorRegisteredName" used when defining hibernate user types -->
<property name="registeredName" value="jasyptHibernateEncryptor" />
<property name="encryptor" ref="stringEncryptor" />
</bean>
We leave encryption password as a placeholder as it will be replaced, at Spring context load time, from an environment variable. Notice that we set lazy-init="false" to force the beans to get loaded. These beans need to be loaded at startup to register the encryptor.
Annotating encrypted properties
Next thing to do is annotate persistent properties with org.hibernate.annotations.Type annotation and the proper encrypted type.
For this we will use on this tutorial a sample object holding 3 properties, of types String, Long and Date, that we want Jasypt to transparently encrypt when persisting them to the database:
package org.appfuse.tutorial.model;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.Type;
@Entity
@Table(name="sensible_personal_data")
public class SensiblePersonalData implements Serializable{
private Long id;
private String name;
private String email;
private Long favoriteNumber;
private Date dateOfBirth;
@Id @GeneratedValue(strategy=GenerationType.AUTO)
public Long getId() {
return id;
}
public String getName() {
return name;
}
@Column(name="email", length=50)
@Type(type="encryptedString")
public String getEmail() {
return email;
}
@Column(name="favorite_number", length=50)
@Type(type="encryptedLongAsString")
public Long getFavoriteNumber() {
return favoriteNumber;
}
@Column(name="dob", length=50)
@Type(type="encryptedDateAsString")
public Date getDateOfBirth() {
return dateOfBirth;
}
public void setName(String name) {
this.name = name;
}
public void setDateOfBirth(Date dateOfBirthDate) {
this.dateOfBirth = dateOfBirthDate;
}
public void setEmail(String email) {
this.email = email;
}
public void setFavoriteNumber(Long favoriteNumber) {
this.favoriteNumber = favoriteNumber;
}
public void setId(Long id) {
this.id = id;
}
}
You need to add this class to hibernate.cfg.xml as usual. (See Persistence tutorial)
Setting encryption password as environment variable
As keeping encryption password stored on a text file inside the application is not a good practice, we will set it through an environment variable.
By default Spring PropertyPlaceholderConfigurer (configured in applicationContext-resources.xml) can resolve placeholder properties from environment variables so all we have to do is set it just before starting the application:
For unix folks:
export jasypt_password="thisIsMySecretPassword"
mvn jetty:run-war
For windows users:
set jasypt_password="thisIsMySecretPassword"
mvn jetty:run-war
And that's all!!