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.
For encryption at Hibernate, jasypt uses its password-based encryption capabilities, and any encryptor object implementing PBEStringEncryptor, PBEByteEncryptor, PBEBigIntegerEncryptor or PBEBigDecimalEncryptor can be used to encrypt data, even encryptors created by the user.
But encryption sets a limitation on your Hibernate usage: security standards establish that two different encryption operations on the same data should not return the same value (due to the use of a random salt). Because of this, none of the fields that are set to be encrypted when persisted can be a part of a WHERE clause in your search queries for the entity they belong to.
| Java type | SQL type | Jasypt Hibernate type (org.jasypt.hibernate.type) | Specific features |
|---|---|---|---|
| String | VARCHAR, CLOB, TEXT | EncryptedStringType | |
| byte[] | VARBINARY, BLOB | EncryptedBinaryType | Honors hibernate.jdbc.use_streams_for_binary. |
| Byte | VARCHAR, CLOB, TEXT | EncryptedByteAsStringType | |
| Short | VARCHAR, CLOB, TEXT | EncryptedShortAsStringType | |
| Integer | VARCHAR, CLOB, TEXT | EncryptedIntegerAsStringType | |
| Long | VARCHAR, CLOB, TEXT | EncryptedLongAsStringType | |
| BigInteger | NUMERIC, NUMBER | EncryptedBigIntegerType | |
| BigInteger | VARCHAR, CLOB, TEXT | EncryptedBigIntegerAsStringType | |
| Float | VARCHAR, CLOB, TEXT | EncryptedFloatAsStringType | |
| Double | VARCHAR, CLOB, TEXT | EncryptedDoubleAsStringType | |
| BigDecimal | NUMERIC, NUMBER | EncryptedBigDecimalType | Needs an additional decimalScale property. |
| BigDecimal | VARCHAR, CLOB, TEXT | EncryptedBigDecimalAsStringType | |
| Boolean | VARCHAR, CLOB, TEXT | EncryptedBoleanAsStringType | |
| Date | VARCHAR, CLOB, TEXT | EncryptedDateAsStringType | |
| Calendar | VARCHAR, CLOB, TEXT | EncryptedCalendarAsStringType | Offers an additional storeTimeZone property. |
When storing an encrypted field, note that you will need a higher amount of space to store the result of the encryption than the space you would need to store the unencrypted piece of data. This is specially important when encrypting with EncryptedBigIntegerType or EncryptedBigDecimalType, as NUMBER and NUMERIC fields are defined by means of digits, not bytes, and thus the difference of size will be much higher than intuitively expected (normally you won't use a field smaller than a NUMERIC(60) to store an encrypted normal-size BigInteger).
Setting jasypt to encrypt data with hibernate requires two separate actions:
The Hibernate mapping file can be configured in two different ways:
<hibernate-mapping package="myapp">
...
<typedef name="encryptedString" class="org.jasypt.hibernate.type.EncryptedStringType">
<param name="algorithm">PBEWithMD5AndTripleDES</param>
<param name="password">jasypt</param>
<param name="keyObtentionIterations">1000</param>
</typedef>
...
<class name="UserData" table="USER_DATA">
...
<property name="address" column="ADDRESS" type="encryptedString" />
...
<class>
...
<hibernate-mapping>
Note: only "password" is a required parameter.\ If this configuration method is used, it is not necessary to provide an encryptor to Hibernate (like explained below).
<hibernate-mapping package="myapp">
...
<typedef name="encrypted" class="org.jasypt.hibernate.type.EncryptedStringType">
<param name="encryptorRegisteredName">strongHibernateEncryptor</param>
</typedef>
...
<class name="UserData" table="USER_DATA">
...
<property name="address" column="ADDRESS" type="encrypted" />
...
<class>
...
<hibernate-mapping>
If we have chosen to use the encryptorRegisteredName parameter in our Hibernate mapping file, we will need to bind somehow an encryptor object to that name.
This can be done in two different manners, depending on whether we are using an IoC container like Spring or not.
<bean id="strongEncryptor"
class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor">
<property name="algorithm">
<value>PBEWithMD5AndTripleDES</value>
</property>
<property name="password">
<value>jasypt</value>
</property>
</bean>
<bean id="hibernateStringEncryptor"
class="org.jasypt.hibernate.encryptor.HibernatePBEStringEncryptor">
<property name="registeredName">
<value>strongHibernateStringEncryptor</value>
</property>
<property name="encryptor">
<ref bean="strongEncryptor" />
</property>
</bean>
Also, we can do it all in the hibernateStringEncryptor declaration, if we don't want to use the strongEncryptor outside of Hibernate and we are OK with the standard encryptor implementation:
<bean id="hibernateStringEncryptor"
class="org.jasypt.hibernate.encryptor.HibernatePBEStringEncryptor">
<property name="registeredName">
<value>strongHibernateStringEncryptor</value>
</property>
<property name="algorithm">
<value>PBEWithMD5AndTripleDES</value>
</property>
<property name="password">
<value>jasypt</value>
</property>
</bean>
StandardPBEStringEncryptor strongEncryptor = new StandardPBEStringEncryptor();
...
HibernatePBEEncryptorRegistry registry =
HibernatePBEEncryptorRegistry.getInstance();
registry.registerPBEStringEncryptor("strongHibernateStringEncryptor", strongEncryptor);
Alternatively, we may have chosen to use annotations for mapping our entities instead of separate XML mapping files. If it has been so, we can still use jasypt to encrypt our data.
All we will have to do is, first, define the encryption type with a @TypeDef annotation, which could be either inside the persisted entity class or inside a @TypeDefs declaration in a separate package-info.java file:
@TypeDef(
name="encryptedString",
typeClass=EncryptedStringType.class,
parameters= {
@Parameter(name="encryptorRegisteredName", value="myHibernateStringEncryptor")
}
)
...and then simply map our property with the already declared type:
@Type(type="encryptedString")
public String getAddress() {
return address;
}