Password Encryption Spring Hibernate Jasypt
In my previous tutorial you saw how to encrypt spring or hibernate application password without using any third party API. Today I will show you how to encrypt your application database properties using Jasypt Java library. Jasypt is a java library which provides basic encryption capabilities without putting much effort and of-course coding. As I don’t want to go to the shortcut route and show you only configuration part of Jasypt encryption. To better understand I will create sample Spring Hibernate application to show you how this works.
Tools needed:
- Eclipse 4.0 or above
- JDK 1.8
- Sybase 15.7 (You can use any database)
Steps:
- First create table using below script in Sybase database:
create table dbo.EquitySwapTest ( underlierRicCode varchar(20) null, underlierSmID int null, underlierCusip varchar(20) null, underlierAssetType varchar(20) null, div_list_id int null, eventDate int null ) on 'default'
- Insert some dummy data for test:
INSERT INTO OTC.dbo.EquitySwapTest( underlierRicCode ,underlierSmID ,underlierCusip ,underlierAssetType ,div_list_id ,eventDate ) VALUES ( 'underlierRicCode' ,12365 ,'underlierCusip' ,'underlierAssetType' ,1254 ,20151028 )
You can encrypt password using Jasypt utility which you download from here but that will take very long time so I have written custom class to encrypt passoword using StandardPBEStringEncryptor Jaypt API to use it. Please encrypt password using below class:
- JaspytPasswordEncryptor.java:
package com.javahonk; import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; public class JaspytPasswordEncryptor { public static void main(String[] args) { String jaspytEncryptionKey = "javahonk_key"; String jaspytAlgorithm = "PBEWithMD5AndDES"; String passwordToEncrypt = "javahonk123"; System.out.println("Password to encrypt: "+passwordToEncrypt); String encryptedPassword = getEncryptedString(jaspytEncryptionKey, jaspytAlgorithm, passwordToEncrypt); System.out.println("Encrypted password: "+ encryptedPassword); String decryptedPassword = getDecryptedString(jaspytEncryptionKey, jaspytAlgorithm, encryptedPassword); System.out.println("Decrypted password: "+decryptedPassword); } /* * Java services use the following: * jaspytEncryptionKey:javahonk_key * jaspytAlgorithm:PBEWithMD5AndDES */ public static String getEncryptedString( String jaspytEncryptionKey, String jaspytAlgorithm, String passwordToEncrypt){ StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); encryptor.setPassword(jaspytEncryptionKey); encryptor.setAlgorithm(jaspytAlgorithm); String encryptText = encryptor.encrypt(passwordToEncrypt); return encryptText; } public static String getDecryptedString( String jaspytEncryptionKey, String jaspytAlgorithm, String passwordToDecrypt){ StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); encryptor.setPassword(jaspytEncryptionKey); encryptor.setAlgorithm(jaspytAlgorithm); String decryptText = encryptor.decrypt(passwordToDecrypt); return decryptText; } }
- As you see above we are using below:
- Run this class as java application and in my case I got this encrypted password:
Important: To use this password just wrap it in the ENC “function” to tell Jasypt to decrypt it while application runs as below:
ENC(VRFGe5YeQmlnpDAYfQtKU+K/cPTuhU6r)
Now let’s complete project how this works:
- Create maven project name: SpringHibernatePassEncryptionJasypt and below is final project structure:
- Only important jar to encrypt password with Jasypt is to include below jar dependencies in your pom.xml:
<dependency> <groupId>org.jasypt</groupId> <artifactId>jasypt</artifactId> <version>1.9.2</version> </dependency> <dependency> <groupId>org.jasypt</groupId> <artifactId>jasypt-spring2</artifactId> <version>1.9.2</version> </dependency>
- pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.javahonk</groupId> <artifactId>SpringHibernatePassEncryptionJasypt</artifactId> <version>0.0.1-SNAPSHOT</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <apache.commons.lang.version>3.3.2</apache.commons.lang.version> <commons.collections.version>3.2.1</commons.collections.version> <commons.logging.version>1.2</commons.logging.version> <org.apache.log4j.version>2.1</org.apache.log4j.version> <objenesis.version>2.1</objenesis.version> <cglib.version>3.2.0-SS</cglib.version> <clusterAPI.version>1.0</clusterAPI.version> <coherence.version>3.7</coherence.version> <coherence-incubator.version>11.3.0</coherence-incubator.version> <galaxy.version>v_10_0_20141003</galaxy.version> <dom4j.version>1.6.1</dom4j.version> <protobuf.version>2.6.1</protobuf.version> <protoc-jar.version>2.6.1.3</protoc-jar.version> <xercesImpl.version>unknown</xercesImpl.version> <org.springframework.version>4.1.5.RELEASE</org.springframework.version> <org.ow2.asm.version>5.0.3</org.ow2.asm.version> <org.javassist.version>3.18.1-GA</org.javassist.version> <org.jboss.logging.version>3.1.3.GA</org.jboss.logging.version> <org.apache.geronimo.version>1.1.1</org.apache.geronimo.version> <org.hibernate.core.version>4.3.9.Final</org.hibernate.core.version> <org.hibernate.entitymanager.version>4.3.9.Final</org.hibernate.entitymanager.version> <org.hibernate.annotations.version>4.0.5.Final</org.hibernate.annotations.version> <org.hibernate.jpa.version>1.0.0.Final</org.hibernate.jpa.version> <json-simple.version>1.1</json-simple.version> <jasypt.version>1.9.2</jasypt.version> <junit.version>4.12</junit.version> </properties> <dependencies> <!-- JUNIT --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> </dependency> <!-- Spring --> <!-- Core utilities used by other modules. Define this if you use Spring Utility APIs (org.springframework.core.*/org.springframework.util.*) --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${org.springframework.version}</version> </dependency> <!-- Expression Language (depends on spring-core) Define this if you use Spring Expression APIs (org.springframework.expression.*) --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>${org.springframework.version}</version> </dependency> <!-- Bean Factory and JavaBeans utilities (depends on spring-core) Define this if you use Spring Bean APIs (org.springframework.beans.*) --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${org.springframework.version}</version> </dependency> <!-- Aspect Oriented Programming (AOP) Framework (depends on spring-core, spring-beans) Define this if you use Spring AOP APIs (org.springframework.aop.*) --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${org.springframework.version}</version> </dependency> <!-- Application Context (depends on spring-core, spring-expression, spring-aop, spring-beans) This is the central artifact for Spring's Dependency Injection Container and is generally always defined --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${org.springframework.version}</version> </dependency> <!-- Various Application Context utilities, including EhCache, JavaMail, Quartz, and Freemarker integration Define this if you need any of these integrations --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${org.springframework.version}</version> </dependency> <!-- JDBC Data Access Library (depends on spring-core, spring-beans, spring-context, spring-tx) Define this if you use Spring's JdbcTemplate API (org.springframework.jdbc.*) --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${org.springframework.version}</version> </dependency> <!-- Object-to-Relation-Mapping (ORM) integration with Hibernate, JPA, and iBatis. (depends on spring-core, spring-beans, spring-context, spring-tx) Define this if you need ORM (org.springframework.orm.*) --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${org.springframework.version}</version> </dependency> <!-- Web application development utilities applicable to both Servlet and Portlet Environments (depends on spring-core, spring-beans, spring-context) Define this if you use Spring MVC, or wish to use Struts, JSF, or another web framework with Spring (org.springframework.web.*) --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${org.springframework.version}</version> </dependency> <!-- Support for testing Spring applications with tools such as JUnit and TestNG This artifact is generally always defined with a 'test' scope for the integration testing framework and unit testing stubs --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${org.springframework.version}</version> <scope>test</scope> </dependency> <!-- Spring Aspects --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>${org.springframework.version}</version> </dependency> <!-- Spring Tx --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>com.oracle.coherence</groupId> <artifactId>coherence</artifactId> <version>${coherence.version}</version> </dependency> <dependency> <groupId>com.wellsfargo.clusterAPI</groupId> <artifactId>ClusterClient</artifactId> <version>${clusterAPI.version}</version> </dependency> <dependency> <groupId>com.wellsfargo.clusterAPI</groupId> <artifactId>ClusterInfoInvocation</artifactId> <version>${clusterAPI.version}</version> </dependency> <dependency> <groupId>com.wellsfargo.galaxy</groupId> <artifactId>attributes</artifactId> <version>${galaxy.version}</version> </dependency> <dependency> <groupId>com.wellsfargo.galaxy</groupId> <artifactId>eqd</artifactId> <version>${galaxy.version}</version> </dependency> <dependency> <groupId>com.wellsfargo.galaxy</groupId> <artifactId>eqdframework</artifactId> <version>${galaxy.version}</version> </dependency> <dependency> <groupId>com.oracle.coherence.incubator</groupId> <artifactId>coherence-common</artifactId> <version>${coherence-incubator.version}</version> </dependency> <dependency> <groupId>com.oracle.coherence.incubator</groupId> <artifactId>coherence-commandpattern</artifactId> <version>${coherence-incubator.version}</version> </dependency> <dependency> <groupId>com.oracle.coherence.incubator</groupId> <artifactId>coherence-messagingpattern</artifactId> <version>${coherence-incubator.version}</version> </dependency> <dependency> <groupId>com.oracle.coherence.incubator</groupId> <artifactId>coherence-processingpattern</artifactId> <version>${coherence-incubator.version}</version> </dependency> <!-- dom4j --> <dependency> <groupId>dom4j</groupId> <artifactId>dom4j</artifactId> <version>${dom4j.version}</version> </dependency> <!-- xerces --> <dependency> <groupId>xerces</groupId> <artifactId>xercesImpl</artifactId> <version>${xercesImpl.version}</version> </dependency> <dependency> <groupId>com.tunnelvisionlabs</groupId> <artifactId>antlr4</artifactId> <version>4.4</version> <classifier>complete</classifier> </dependency> <!-- objenesis --> <dependency> <groupId>org.objenesis</groupId> <artifactId>objenesis</artifactId> <version>${objenesis.version}</version> </dependency> <!-- apache commons --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>${apache.commons.lang.version}</version> </dependency> <!-- commons-io --> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> </dependency> <!-- commons collections --> <dependency> <groupId>commons-collections</groupId> <artifactId>commons-collections</artifactId> <version>${commons.collections.version}</version> </dependency> <!-- commons logging --> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>${commons.logging.version}</version> </dependency> <!-- cglib --> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <!--<version>3.1</version> --> <version>${cglib.version}</version> </dependency> <!-- jdbc driver --> <dependency> <groupId>com.sybase.jdbcx</groupId> <artifactId>jconn4</artifactId> <version>7.07</version> </dependency> <!-- aop alliance --> <dependency> <groupId>aopalliance</groupId> <artifactId>aopalliance</artifactId> <version>1.0</version> </dependency> <!-- asm --> <dependency> <groupId>org.ow2.asm</groupId> <artifactId>asm</artifactId> <version>${org.ow2.asm.version}</version> </dependency> <!-- javassist --> <dependency> <groupId>org.javassist</groupId> <artifactId>javassist</artifactId> <version>${org.javassist.version}</version> </dependency> <!-- jboss logging --> <dependency> <groupId>org.jboss.logging</groupId> <artifactId>jboss-logging</artifactId> <version>${org.jboss.logging.version}</version> </dependency> <!-- hibernate --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>${org.hibernate.core.version}</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>${org.hibernate.entitymanager.version}</version> </dependency> <dependency> <groupId>org.hibernate.common</groupId> <artifactId>hibernate-commons-annotations</artifactId> <version>${org.hibernate.annotations.version}</version> </dependency> <dependency> <groupId>org.hibernate.javax.persistence</groupId> <artifactId>hibernate-jpa-2.1-api</artifactId> <version>${org.hibernate.jpa.version}</version> </dependency> <dependency> <groupId>com.googlecode.json-simple</groupId> <artifactId>json-simple</artifactId> <version>${json-simple.version}</version> </dependency> <!-- Log4j --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>${org.apache.log4j.version}</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>${org.apache.log4j.version}</version> </dependency> <dependency> <groupId>org.jasypt</groupId> <artifactId>jasypt</artifactId> <version>${jasypt.version}</version> </dependency> <dependency> <groupId>org.jasypt</groupId> <artifactId>jasypt-spring2</artifactId> <version>${jasypt.version}</version> </dependency> </dependencies> </project>
- spring-context.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd"> <context:annotation-config /> <context:component-scan base-package="com.javahonk.dao, com.javahonk.model" /> <bean class="org.jasypt.spring.properties.EncryptablePropertyPlaceholderConfigurer"> <constructor-arg ref="encryptor" /> <property name="locations"> <list> <value>classpath:hibernate/hibernate.properties</value> </list> </property> <property name="ignoreUnresolvablePlaceholders" value="true"/> <property name="ignoreResourceNotFound" value="true"/> </bean> <bean id="encryptor" class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor"> <property name="algorithm" value="PBEWithMD5AndDES" /> <property name="password" value="javahonk_key" /> </bean> <import resource="hibernate-context.xml"/> </beans>
- log4j2.xml:
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="INFO" shutdownHook="disable"> <Properties> <Property name="envrionment.target">DEV</Property> </Properties> <Properties> <Property name="logging.dir">./</Property> </Properties> <Appenders> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" /> </Console> <RollingFile name="RollingFile" fileName="./logs/rolling-file.log" filePattern="${sys:logging.dir}/logs/rolling-file-%d{yyyy-MM-dd}-%i.log"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" /> <!-- TODO:Change to time based policy --> <Policies> <TimeBasedTriggeringPolicy interval="1" modulate="true" /> <SizeBasedTriggeringPolicy size="100 MB" /> </Policies> <DefaultRolloverStrategy max="4" /> </RollingFile> </Appenders> <Loggers> <Root level="info"> <AppenderRef ref="Console" /> <!-- <AppenderRef ref="file" /> --> <AppenderRef ref="RollingFile" /> </Root> </Loggers> </Configuration>
- hibernate.querites.xml: For this demo we are not using any query and if you want you can utilize it:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd" > <hibernate-mapping> </hibernate-mapping>
- hibernate-context.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd"> <context:component-scan base-package="com.javahonk.dao, com.javahonk.model" /> <tx:annotation-driven transaction-manager="transactionManager" /> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${jdbc.driverClassName}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="packagesToScan"> <list> <value>com.javahonk.model</value> <value>com.javahonk.dao</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">${hibernate.dialect}</prop> <prop key="hibernate.show_sql">${hibernate.show_sql}</prop> <prop key="hibernate.c3p0.max_size">${hibernate.c3p0.max_size}</prop> <prop key="hibernate.c3p0.min_size">${hibernate.c3p0.min_size}</prop> <prop key="hibernate.c3p0.timeout">${hibernate.c3p0.timeout}</prop> <prop key="hibernate.c3p0.max_statements">${hibernate.c3p0.max_statements}</prop> </props> </property> <property name="mappingLocations" value="hibernate.queries.xml"></property> </bean> <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"/> </bean> </beans>
- hibernate.properties:
jdbc.driverClassName=com.sybase.jdbc4.jdbc.SybDriver default_streamed_object_size=5000 default_max_query_size=1000 jdbc.url=jdbc:sybase:Tds:javahonk.com:12000 jdbc.username=javahonk jdbc.password=ENC(VRFGe5YeQmlnpDAYfQtKU+K/cPTuhU6r) hibernate.dialect=org.hibernate.dialect.SybaseASE157Dialect hibernate.show_sql=false hibernate.jdbc.lob.non_contextual_creation=true c3p0.acquireIncrement=2 c3p0.maxPoolSize=10 c3p0.minPoolSize=1 c3p0.maxIdleTime=1800
- GenericDao.java:
package com.javahonk.dao; import java.util.List; public interface GenericDao<T> { public List<T> getEquitySwapByHibernateQuery(int eventDate); }
- GenericDaoHandler.java:
package com.javahonk.dao; import java.util.List; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; @Repository @Transactional public class GenericDaoHandler<T> implements GenericDao<T>{ @Autowired private SessionFactory sessionFactory; @SuppressWarnings("unchecked") @Override public List<T> getEquitySwapByHibernateQuery(int eventDate) { Session session = sessionFactory.getCurrentSession(); Query query = session.createSQLQuery("SELECT * FROM OTC.dbo.EquitySwapTest where eventDate = :eventDate"); query.setParameter("eventDate", eventDate); List<T> dividendPayDate = query.list(); return dividendPayDate; } }
- PasswordEncyrptorTestApp.java: To test the application:
package com.javahonk; import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.springframework.context.ApplicationContext; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.javahonk.dao.GenericDao; public class PasswordEncyrptorTestApp { private static final Logger logger = LogManager.getLogger(PasswordEncyrptorTestApp.class.getName()); public static void main(String[] args) { logger.info("Starting HibernateTestApp..."); ApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml"); GenericDao<?> genericDao = context.getBean(GenericDao.class); List<?> dataList2 = genericDao.getEquitySwapByHibernateQuery(20151028); logger.info("Got the data: {}", dataList2); ((AbstractApplicationContext) context).close(); } }
To test this application right click PasswordEncyrptorTestApp.java –> Run As –> Java Application and if everything setup correctly you will see below output:
12:41:54.408 [main] INFO com.javahonk.PasswordEncyrptorTestApp - Got the data: [[underlierRicCode, 12365, underlierCusip, underlierAssetType, 1254, 20151028], [underlierRicCode, 12365, underlierCusip, underlierAssetType, 1254, 20151028], [underlierRicCode, 12365, underlierCusip, underlierAssetType, 1254, 20151028], [underlierRicCode, 12365, underlierCusip, underlierAssetType, 1254, 20151028], [underlierRicCode, 12365, underlierCusip, underlierAssetType, 1254, 20151028], [underlierRicCode, 12365, underlierCusip, underlierAssetType, 1254, 20151028], [underlierRicCode, 12365, underlierCusip, underlierAssetType, 1254, 20151028], [underlierRicCode, 12365, underlierCusip, underlierAssetType, 1254, 20151028]]
For more information on Jasypt encryption please visit its official site here
Download Project: SpringHibernatePassEncryptionJasypt
Thanks its really helpful
Very useful resource. Thanks. 🙂