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 type | SQL type | 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 | EncryptedBooleanAsStringType | |
Date | VARCHAR, CLOB, TEXT | EncryptedDateAsStringType | |
Calendar | VARCHAR, CLOB, TEXT | EncryptedCalendarAsStringType | Offers 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:
- The Jasypt website: http://www.jasypt.org
- The Jasypt + Hibernate 3 integration guide: http://www.jasypt.org/hibernate3.html
Comments