Friday, November 05, 2010

Data Encryption with Jasypt Spring JPA and Hibernate

If you are storing private user data you must encrypt it to protect your users and also to avoid consequences (see HIPAA and California/Massachusetts Privacy Laws as an example).

Before continuing let me state that this is not a post about if you should store private data or not, that depends on the real necessities and your professional judgment. This is not a post about how to store your keyring the right way neither a security-for-pros post.

Jasypt is simple and yet tested by security experts that do the job for you so do not rely on obscurity to protect your data, use a Library like Jasypt.

Spring allows to clean your code especially if you use annotations and JPA facilitates persistance supporting annotations. JPA unfortunately is missing still so many features that I forgot a while ago about changing my persistence provider in the future. Hibernate provides a really clean (at least in comparison with others I had to implement in the past) solution.

I am sharing a typical configuration to get a JUnit test up and running but exactly the same applies to a container managed (Web) application.
So in your pom.xml
<!-- Encryption / Decryption -->
        <dependency>
            <groupId>org.jasypt</groupId>
            <artifactId>jasypt</artifactId>
            <version>1.7</version>
            <scope>compile</scope>
        </dependency>

In spring config file:
<context:property-placeholder location="test.properties" ignore-unresolvable="true"/>
<bean id="hibernateStringEncryptor" class="org.jasypt.hibernate.encryptor.HibernatePBEStringEncryptor">
        <property name="registeredName">
            <value>hibernateStringEncryptor</value>
        </property>
        <property name="password">
            <value>${jasypt.password}</value>
        </property>
    </bean>

In your test.properties (Which of course will use a different password than the one you use in development/integration, staging and production environments ):
#Holder for all general test properties
jasypt.password=jasypt

In JPA Entities the proposed annotation on top of the getter did not work for me. I had to annotate the field itself which makes sense BTW:
@TypeDef(
        name="encryptedString", 
        typeClass=EncryptedStringType.class, 
        parameters={@Parameter(name="encryptorRegisteredName",
                               value="hibernateStringEncryptor")}
)

@Type(type="encryptedString")
private String ssn;   

4 comments:

Ashish said...

Good one, helped my Jasypt integration.

Abhi said...

Very helpful

javabuddy said...

Nicely explained. Thank you. I have actually tried this. I am facing one problem. I have users and their email addresses are unique in entity. I have encrypted email addresses. But when I add user with the same email address, it generates different encrypted string. Can you guide how should I solve this problem please?

Nestor Urquiza said...

@javabuddy: I think you should provide a test case demonstrating your statement and then share it with the jasypt community.

Followers