Security: Transparent encryption of persisted data (with Jasypt UserTypes)

This article discusses the setup needed to store sensitive data with hibernate in an encrypted manner. For this purpose, the open source library Jasypt (Java Simplified Encryption) is used.

Jasypt can be found at: http://www.jasypt.org

The objectives are:

  • Data has to be encrypted when stored into the database and decrypted when retrieved.
  • Encryption and decryption operations should be transparent for the application's business logic.
  • Encryption mechanisms should be implemented as a Hibernate UserType, and thus set up and configured at the Hibernate mapping files.

 

Encryptable data types

The following data types can be transparently encrypted by Jasypt:

 

Java typeSQL typeJasypt Hibernate typeSpecific Features
StringVARCHAR, CLOB, TEXTEncryptedStringType
byte[]VARBINARY, BLOBEncryptedBinaryTypeHonors hibernate.jdbc.use_streams_for_binary
ByteVARCHAR, CLOB, TEXTEncryptedByteAsStringType
ShortVARCHAR, CLOB, TEXTEncryptedShortAsStringType
IntegerVARCHAR, CLOB, TEXTEncryptedIntegerAsStringType
LongVARCHAR, CLOB, TEXTEncryptedLongAsStringType
BigIntegerNUMERIC, NUMBEREncryptedBigIntegerType
BigIntegerVARCHAR, CLOB, TEXTEncryptedBigIntegerAsStringType
FloatVARCHAR, CLOB, TEXTEncryptedFloatAsStringType
DoubleVARCHAR, CLOB, TEXTEncryptedDoubleAsStringType
BigDecimalNUMERIC, NUMBEREncryptedBigDecimalTypeNeeds an additional decimalScale property
BigDecimalVARCHAR, CLOB, TEXTEncryptedBigDecimalAsStringType
BooleanVARCHAR, CLOB, TEXTEncryptedBooleanAsStringType
DateVARCHAR, CLOB, TEXTEncryptedDateAsStringType
CalendarVARCHAR, CLOB, TEXTEncryptedCalendarAsStringTypeOffers an additional storeTimeZone property

 

Steps

 

1. Configure a Jasypt encryptor

First of all, you will have to instantiate a Jasypt encryptor for, let's say, Strings, so that it can be used for performing the encryption operations from inside the Hibernate type system. Once created, you will have to register the encryptor for Hibernate:

   ...
   /*
    * Create and configure the encryptor
    */
   StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
   encryptor.setAlgorithm("PBEWithMD5AndDES"); // not really needed as it is the default
   encryptor.setPassword(myPassword);
   
   /*
    * Register the encryptor for use from within Hibernate types
    */
   HibernatePBEEncryptorRegistry registry = HibernatePBEEncryptorRegistry.getInstance();
   registry.registerPBEStringEncryptor("hibernateStringEncryptor",encryptor);
   ...

You will have to make sure that this code gets executed before the first encryption or decryption operation is performed by the Hibernate types (for instance, in a webapp, with a ContextListener).

 

2. Map your encrypted attributes

Now, you will only have to declare the new type and use if at your mappings:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
 
<hibernate-mapping package="com.myapp">

  <typedef name="encryptedString" class="org.jasypt.hibernate.type.EncryptedStringType">
      <param name="encryptorRegisteredName">hibernateStringEncryptor</param>
  </typedef>


  <class name="UserData" table="USER_DATA" >

    <id name="id" column="ID">
        <generator class="native" />
    </id>

    <property name="login" column="LOGIN" type="string" />
    <property name="name" column="NAME" type="encryptedString" />
    <property name="email" column="EMAIL" type="encryptedString" />
    <property name="address" column="ADDRESS" type="encryptedString" />

  </class>
    
</hibernate-mapping>

 

Alternative: Direct configuration of encryptor at mapping

Alternatively, you might prefer not to create, configure and register a Jasypt encryptor beforehand, but instead leave it all to the UserType's responsibility. (Note that this will reduce the flexibility of configuration you can get from jasypt encryptors, and let you with a basic set of configuration parameters.)

In this case, you may only have to configure your mapping like this:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
 
<hibernate-mapping package="com.myapp">

  <typedef name="encryptedString" class="org.jasypt.hibernate.type.EncryptedStringType">
      <param name="algorithm">PBEWithMD5AndDES</param>
      <param name="password">thisisatest</param>
      <param name="keyObtentionIterations">1000</param>
  </typedef>
  

  <class name="UserData" table="USER_DATA" >

    <id name="id" column="ID">
        <generator class="native" />
    </id>

    <property name="login" column="LOGIN" type="string" />
    <property name="name" column="NAME" type="encryptedString" />
    <property name="email" column="EMAIL" type="encryptedString" />
    <property name="address" column="ADDRESS" type="encryptedString" />

  </class>
    
</hibernate-mapping>

This way, when the first data storage or retrieval operation is performed, the UserType object will automatically instantiate a StandardPBEStringEncryptor object, configure it with the specified parameters, and use it.


 

More information

There is much more about using Jasypt for Hibernate transparent encryption, which you can read at: