Encrypting Properties With Jasypt

Properties are used in many Java applications as a simple way of separating parts that are likely to change, from the parts that are not that likely to change. Consider for example this typical bean definition in a Spring configuration file:

In order to simplify deployment and maintenance, it’s quite common to extract properties related to server names, ports, and user credentials from the Spring configuration file into a separate property file, like in this ldap.properties:

In the configuration file, the previously hard-coded values are replaced with “property placeholders”, ie variables enclosed with ${}:

In order to perform the property value substitution in a transparent way, a PropertyPlaceholderConfigurer is configured:

Spring will pick up that one has been configured and run it before any beans are instantiated. It will read the property file and replace the placeholders with the actual values. Quite handy and very simple.

But what if your organization dislikes having sensitive information like passwords lying around in property files, in clear text? Let’s say that your boss demands that all such passwords must be encrypted. Wouldn’t it be great if the password then somehow could be automatically decrypted before being used? This can quite easily be achieved using the Jasypt library.

It’s a two-step process. First we need to encrypt the password. Then we configure a different PropertyPlaceholderConfigurer that is capable of decrypting the property after it has been read.

Encrypting the password

The available encryption algorithms are currently limited to Password Based Encryptors (PBE). There are scripts for encrypting and decrypting in the Jasypt distribution. This is the procedure for encrypting a text (assuming the Jasypt library has been unpacked in JASYPT_HOME):

Let’s verify that it can actually be decrypted:

Good. Note that the encryption is “salted”, so you’ll never get the same result twice. You’ll always be able to decrypt it, though. Want to see? OK, one more time then:

Now, let’s encrypt our password:

We’ll replace the password value in the properties file with the string above, surrounded by ENC():

Configure A Decrypting PropertyPlaceholderConfigurer

We’ll simply replace our existing PropertyPlaceholderConfigurer with the Jasypt EncryptablePropertyPlaceholderConfigurer:

It delegates the actual decryption to a StringEncryptor implementation:

The encryptor in turn needs a configuration that provides information such as the algorithm to use and the encryption password. It delegates that responsibility to a PBEConfig implementation that expects the password to be available in an environment variable or a system property:

Providing the encryption password as a system property is actually a good thing. A system property can be cleared just when the application has started, thereby minimizing considerably the time that the password is exposed.

Running The Application

It won’t work with a Maven property:

We check the Surefire reports and find the cause of the error:

It does however work with an environment variable:

Issues With Java5

If we’re on Java5 (or lower), we’ll need ICU4J. Otherwise, we’ll run into this:

There are two places where we’ll need ICU4J: the command line tools and our Maven project.

ICU4J With The Command Line Tools

Reviewing the Jasypt scripts, we find that it’s possible to customize the classpath:

ICU4J With Maven

Add this profile to the Maven pom.xml to get ICU4J in the classpath:

Currently, the 4.0 version is not available in the central Maven repo, but 3.8 seems to work just fine.

Summary

Using Jasypt, it’s actually quite easy to use encrypted values in your property files. In a Spring-based application, it’s simply a question of replacing the existing PropertyPlaceholderConfigurer with the Jasypt encrypting equivalent, plus two more beans providing encryption and configuration. Choose how to provide the encryption password, and you’re set to go.

If running on Java5 or lower, you’ll also need to add ICU4J to your classpath, for the encryption scripts as well as your build and deployment environment.

References

This Post Has 30 Comments

  1. Great post! This is exactly what I was looking for.

  2. Can you please provide a little sample spring application , (Sample Code) for Jasypt, it will be very helpfull to understnd all the steps and from begining to end.
    if u can please mail or upload a sample Spring application with Jasypt.

  3. Hi, I am still getting this error for Jasypt1.5 , i tried to include my classpath variable and path for ICU, can you please let me know what exaclt we need to do to run Encyption.bat on windows
    i am using
    java version “1.4.2_17″
    Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2
    Java HotSpot(TM) Client VM (build 1.4.2_17-b06, mixed mode)

    Here is what i did
    C:jasypt-1.5bin>encrypt.bat input=”my test data” password=m
    —-ENVIRONMENT—————–
    Runtime: Sun Microsystems Inc. Java HotSpot(TM) Client VM 1.4
    —-ARGUMENTS——————-
    input: my test data
    password: my_pa_word
    —-ERROR———————–
    java.lang.NoClassDefFoundError: com/ibm/icu/text/Normalizer

    I added in classpath — C:icu4j-4_0icu4j-4_0.jar
    and iin path C:icu4j-4_0

    Do I need to add JSYPT in classpath ??
    please help.

  4. What do I need to do to resolve the following error:
    PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property ‘passwordEnvName’ threw exception; nested exception is java.lang.Error: getenv no longer supported, use properties and -D instead: APP_ENCRYPTION_PASSWORD]

    1. Not sure about this one, but System.getenv was re-instated in Java5 after having been deprecated in 1.2. Could it be that you’re using an older Java?

  5. I am using 1.4.
    I only want to be able to pick up the password from my properties file not as an environment variable

  6. Hi. I’m creating an application with Spring and Hibernate. I follow the steps to encrypt the hibernate password and it works correctly on Windows but it doesn’t work on linux Debian. Do I have to configure the APP_ENCRYPTION_PASSWORD in somewhere or something?

    thank you in advance…

  7. Hi:
    Mr.Sandberg .I’m a Chinese student. On this point I hame some problems. at ”
    org.jasypt.exceptions.EncryptionInitializationException:
    Password not set for Password Based Encryptor


    According to the method that is you. if between “ENC” and “()”
    have a space,then Compile OK, but when the project submitted to the user or running password is incorrect. What should I do?

    both isn’t have some space?

    you have time to return? Here or EMAIL. thanks.

  8. Great post! This is exactly what I was looking for too.

  9. Will this work on Windows7? I have a system environment variable set for the password to decrypt the datasouce password. After debugging the source code, it’s still not clear to me where I messed up. With jasypt 1.8, I’m getting this…

    java.lang.NullPointerException at org.jasypt.encryption.pbe.config.SimplePBEConfig.getPasswordCharArray(SimplePBEConfig.java:434) at org.jasypt.encryption.pbe.StandardPBEByteEncryptor.resolveConfigurationPassword(StandardPBEByteEncryptor.java:740)

  10. Looking at that line, it seems the password property is null. Perhaps that gives you a hint where to look further.

  11. SOLVED

    The problem was resolved after a reboot.

  12. Hi,

    Thank you for this blog.
    However I have a query. Can we use JASYPT Encryptor with PropertyFactoryBean. So before making a properties file available to bean it is decrypted.

    Thank You
    Aditya Sharma

  13. Cool, very helpful description!!!

    I just followed your instructions, ran into the NullPointer from above, added the missing property for my master password and was able to use encryption within one hour!

    Thank you very much for this clear step by step instruction
    Thorsten

  14. Can i hide the value of “APP_ENCRYPTION_PASSWORD”?

    In my situation the encrpytion work is done by 3rd party than they won’t provide their password they use for encrypting the string.

    Thank you. The blog is very clear!!

  15. My batch processes kicks off automatically during nights and there is no way of manual intervention, so how can i handle the master password(APP_ENCRYPTION_PASSWORD) ?

    Just a person encrypts database password and paste it in the properties file and using shell scripts the application kicks off automatically. Then how can the application able to receive the master password ? How can I secure master password ?

  16. I’m getting org.jasypt.exceptions.EncryptionOperationNotPossibleException.

    I used encrypt.bat to encrypt my password and able to get it back with decrypt.bat. I added to environment variable and updated my property file.

    I still have the same exception. Can you point out anywhere else I should check? I wonder if OS makes any difference. I’m on Windows 7.

  17. Hi, I debugged and finally traced down to “javax.crypto.BadPaddingException Given final block not properly padded”. Does anyone know where I might be doing wrong?

  18. This is the perfect solution.
    Excellent post.

  19. Thanks for your this Nice Post. Simple & Well explained. Keep writing…

  20. I am getting NULL Pointer Exception….Can someone help
    I hardcoded password to make sure I am passing all values…

    16:15:50,230 INFO XmlBeanDefinitionReader:315 – Loading XML bean definitions from class path resource [applicationContext.xml]
    16:15:50,905 INFO XmlBeanDefinitionReader:315 – Loading XML bean definitions from class path resource [hibernate.cfg.xml]
    16:15:51,913 INFO EncryptablePropertyPlaceholderConfigurer:177 – Loading properties file from URL [file:config/jdbc.properties]
    16:15:51,914 INFO EncryptablePropertyPlaceholderConfigurer:177 – Loading properties file from URL [file:config/broker.properties]
    16:15:52,027 ERROR EMMSServer:85 – EMMS Server starting problem :
    org.jasypt.exceptions.EncryptionInitializationException: java.lang.NullPointerException
    at org.jasypt.encryption.pbe.StandardPBEByteEncryptor.initialize(StandardPBEByteEncryptor.java:708)
    at org.jasypt.encryption.pbe.StandardPBEStringEncryptor.initialize(StandardPBEStringEncryptor.java:553)
    at org.jasypt.encryption.pbe.StandardPBEStringEncryptor.decrypt(StandardPBEStringEncryptor.java:705)
    at org.jasypt.properties.PropertyValueEncryptionUtils.decrypt(PropertyValueEncryptionUtils.java:72)
    at org.jasypt.spring31.properties.EncryptablePropertyPlaceholderConfigurer.convertPropertyValue(EncryptablePropertyPlaceholderConfigurer.java:109)
    at org.springframework.beans.factory.config.PropertyResourceConfigurer.convertProperty(PropertyResourceConfigurer.java:121)
    at org.springframework.beans.factory.config.PropertyResourceConfigurer.convertProperties(PropertyResourceConfigurer.java:104)
    at org.springframework.beans.factory.config.PropertyResourceConfigurer.postProcessBeanFactory(PropertyResourceConfigurer.java:81)
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:681)
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:656)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:446)
    at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:139)
    at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:83)
    at com.csc.emms.server.EMMSServer.main(EMMSServer.java:90)
    at com.csc.emms.service.servicelauncher.ServiceLauncher.start(ServiceLauncher.java:65)
    at com.csc.emms.service.servicelauncher.ServiceLauncher.serviceMain(ServiceLauncher.java:33)
    Caused by: java.lang.NullPointerException
    at org.jasypt.normalization.Normalizer.normalizeToNfc(Normalizer.java:88)
    at org.jasypt.encryption.pbe.StandardPBEByteEncryptor.initialize(StandardPBEByteEncryptor.java:653)
    … 15 more

    below are the code:
    ==================

    <property name="password" value="” />

    1. I am also getting the same exception, NPE…
      Did you get any resolution for it then please enlighten me!

      Thanks,
      Pratik

  21. Nice and clear! Thank you.

  22. How should put here

    if i have multiple user name and password for different databases in same properties file?

  23. Hi,

    I tried the above implementation but im getting this issue :

    org.xml.sax.SAXParseException; lineNumber: 6; columnNumber: 68; schema_reference.4: Failed to read schema document ‘http://www.jasypt.org/schema/encryption/’, because 1) could not find the document; 2) the document could not be read; 3) the root element of the document is not .

    Can someone please help me here ?

    Thanks,
    Wasim

  24. Great blog post! This explanation was short but tremendously helpful. Thank you for sharing.

  25. Thank you very much for this!!!
    I would like to know, This article is almost 10 years old, is there any differences when going with jasypt 1.9.2 and spring 4.3.11.RELEASE

  26. Great Post. Thank you very much.

Leave a Reply

Close Menu