Sunday, May 15, 2016

Encrypting Properties File Values with Jasypt


Encrypting Properties File Values with Jasypt


What's the fuzz all about?

Property files are text resources in your standard web application that contains key-value information. There may come a time when information should not be stored in plain sight. This article will demonstrate how to encrypt properties file values using Jasypt encryption module. Jasypt is freely available and comes with Spring Framework integration.

Prerequisites

Library Versions:
  • Spring 3.1+
  • Jasypt 1.9.0+

A standard java web-based application may consist numerous properties file. An example of those files would be:
  • application.properties
  • jdbc.properties
  • mail.properties
  • amazon.properties

As an example for a file like mail.properties it would contain key-value pairs used by the application to configure a web-application at different stages of the running web application.


Plain Text Values In Properties Files

The following code snippet below is a typical example of a property configuration for an SMTP service. Note that the username and password entries are provided in clear text.

Code Snippet 1. Property file values
1
2
3
4
5
local.mail.smtps.host=smtp.gmail.com
local.mail.smtps.port=465
local.mail.smtps.debug=true
local.mail.smtps.username=morpheus@gmail.com
local.mail.smtps.password=Take the blue pill

As you can see sensitive information like the username and password is stored in plain text. To make it even worst, we check this in to a source repository like github. Wouldn't it be nice if we could encrypt username and password values?

Encrypted Values in Properties File


With Jasypt you can enter encrypted values by enclosing them with ENC('value'). The values are decrypted in-memory (i.e. during load-time) using a Jasypt-based extension of Spring Framework's org.springframework.context.support.PropertySourcesPlaceholderConfigurer.

Code Snippet 2. Jasypt TextEncryptor solution for encrypting property file values.
1
2
3
4
5
6
mail.smtps.username=ENC(iXm7KjIoubkQVmbJdTJxGJPPIHkZ6H9fq7ZJsfsGpIk=)
mail.smtps.password=ENC(zcV8BmkkZchyHzEmNyM70seLHUFwFz4va8w5wpvYXYE=)

mail.smtps.host=smtp.gmail.com
mail.smtps.port=465
mail.smtps.debug=true

Source: mail.properties

Encrypting the property value using Jasypt


Standard Property Placeholder Configuration


The following configuration is a spring framework's standard property placeholder configuration.

Code Snippet 3. Standard Property Placeholder Configuration
<context:property-placeholder location="classpath*:*.properties"/>

Jasypt Text Encryptor Configuration


The code snippet shown below enables the jasypt BasicTextEncryptor implementation with an override to the standard spring property placeholder configuration.

Code Snippet 4. Jasypt TextEncryptor Configuration
1
2
3
4
5
6
<bean id="textEncryptor" class="org.jasypt.util.text.BasicTextEncryptor"
  p:password="go-big-or-go-home"/>

<bean id="propertyPlaceholder" class="org.jasypt.spring31.properties.EncryptablePropertySourcesPlaceholderConfigurer"
        p:locations="classpath*:*.properties"
        c:textEncryptor-ref="textEncryptor"/>

You may want to vary your configuration for each environment. For instance dev would be just the default Spring PropertySourcesPlaceholderConfigurer and stage, prod would use Jasypt's EncryptablePropertySourcesPlaceholderConfigurer. One would use Spring Framework Profile Feature (or equivalent) to vary configurations between deployment but this type of discussion is beyond the scope of this blog.

Code Snippet 5. Mail Sender Bean Configuration
1
2
3
4
5
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"
  p:protocol="smtps"p:host="${mail.smtps.host}"
  p:port="${mail.smtps.port}"
  p:username="${mail.smtps.username}"
  p:password="${mail.smtps.password}"/>


Code Snippet 6. Spring Annotation-based Configuration
1
 2
 3
 4
 5
 6
 7
 8
 9
10
@Controller
public class MailController {

 @Value("${mail.smtps.username}")
 private String email;

 @Value("${mail.smtps.password}")
 private String password;

}

Source: app-ctx.xml

Generating Salted Encrypted Values


I created an example of how you would produce an encrypted value using a JUnit test class.
The JUnit test shown on the code snippet below is an example code for generating the encrypted value.
Update the secret password as needed but make sure not to check-in the real one.

Note that each time you run the test it will produce a different encrypted text value because the encryption is salted. SEE TextEncryptorTest.java

Code Snippet 7. Unit example for generating an encrypted value
1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.lagnada.xmx1024.integration;

import org.jasypt.util.text.BasicTextEncryptor;
import org.junit.Before;
import org.junit.Test;

import static org.fest.assertions.Assertions.assertThat;

/**
 * Test Utility for generating encrypted passwords for {@link org.jasypt.spring31.properties.EncryptablePropertySourcesPlaceholderConfigurer}
 */
public class TextEncryptorTest
{

    BasicTextEncryptor encryptor;

    @Before
    public void setUp() throws Exception
    {
        encryptor = new BasicTextEncryptor();
        encryptor.setPassword("go-big-or-go-home");
    }

    @Test
    public void generateEncryptedText()
    {
        String plainText = "Take the blue pill";
        String encrypted = encryptor.encrypt(plainText);
        System.out.printf("encrypted: %s%n", encrypted);
        assertThat(encrypted).isNotNull();
        assertThat(encrypted).isNotEqualTo(plainText);
    }
}

After running the JUnit code on Code Snippet 7, use the encrypted text value and enclose it with ENC() in any of your sourced properties file.

Code Snippet 8. Encrypted property value example
mail.smtps.password=ENC(eVrfrMcWl9J7fiC+9q4w8bNR+MSeTT5yfh1JL0/mUtk=)


Summary

Please note that the caveat here is that this solution is not entirely secure at runtime. One can certainly debug an application and see the clear-text value of the encrypted property.

The entire source code can be pulled at github xmx1024. Please feel free to fork it.


Reference:

What is Jasypt?


Secure SMTP with Spring JavaMailSender


Overview

Like many cost-effective individuals out there I migrated most of my email service which I was paying approximately $50/year for to use Google Apps For Your Domain. This is a free service that in fact I am very satisfied with. But using the smtp service with the Spring JavaMailSender on my old email account was straight forward. The problem I now have is that Google Apps For Your Domain uses the smtps protocol to send emails and because I was using an older version of Java Mail (1.3) I could not programmatically send emails using the secure smtp protocol. In addition to that, the default implemation of JavaMailSender (JavaMailSenderImpl.java) in Spring Framework currently does not have the ability to smoothly handle sending messages using the secure smtp (smtps) protocol.

I stumbled into this when developing a web application that requires an SMTP account to send test emails and other email notifications to the users of this application. Not having the luxury to run my own SMTP server I decided that I would just temporarily use a Gmail (TM) account for sending the messages during development. It just so happens that Gmail uses Secure SMTP to send email messages and on top of that it requires the user to authenticate.

Java Libraries You Will Need

In further investigating this issue it turns out that pre Java Mail 1.4, there is no support for SMTPS Protocol. So we need to download the latest version at Java Mail.
  • Option #1:

    Download the latest Java Mail API jars.
    When using this route be warned that on the final click to download the java mail product you will be re-routed to install the Sun(TM) Download Manager. I am just really puzzled why Sun(TM) has the need to create their own download managers.

  • Option #2:

    Download the latest
    Java Platform Enterprise
    Edition
    and use the mail.jar that came with that product.

The particular class file that you want to check for in these jars are: com.sun.mail.smtp.SMTPSSLTransport.
Please note that for either options you will still need the Java Activation Framework (activation.jar).

JavaMailSenderImpl with Secure SMTP/SMTPS Support

In my own extension of the the JavaMailSenderImpl.java (see Source Code), it will automatically set the protocol to smtps and add Java Mail smtps properties if the property smtp.isSecure is set to true. Basically, the properties smtp host, username, password, and port will be required.  Also note the property smtp.isSecure is not a Java Mail property. It is just the property name that I came up with so that the code can toggle between normal smtp and smtps protocol.

I also created an override for the super.doSend(..) method so that after calling the Transport.connect(..) method, it will test for connection via the Transport.isConnected() method. This is just an extra step to make sure that we are connected to the SMTPS server and may not be needed in some cases.

Futhermore, If you have a CRUD for the server configuration,  the mail.properties value may be replaced with an implementation that retrieves its values from the database as well.

Update

The solution below now works using Spring 3.x version and Java Mail 1.4.5. The following Spring config is all you need to enable smtps.

<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"
p:protocol="smtps" p:host="smtp.gmail.com" p:port="465"
p:username="morpheus@gmail.com" p:password="take-the-blue-pill" />


Friday, April 27, 2012

Decoupling Domain Objects

Overview

Given a top down design where the domain objects do not match the entity objects, one of the common techniques in object oriented design is to decouple the object layers. One decoupling technique is to use composite objects. Each level of abstraction will utilize its own composite object (Domain and View). It seems like a lot to write from the looks of it but most IDE supports creations of delegate methods now anyways.

Components

Service Layer, Persistent Object, Domain Object, View Object


Service Layer

public interface BlogManager {
    Blog load(String name) throws EntityNotFoundException;
}

public class BlogManagerImpl implements BlogManager {
    // Fictitious EntityManager
    EntityManager em;

    public Blog load(String name) throws EntityNotFoundException {
        Blog blog = null;
        BlogData data = em.query("select b from BlogData b where b.name = ?", name);
        return new Blog(data);
    }
}

Persistent Object

BlogData: an entity-managed persistent object (managed by hibernate for example)
@Peristent
public class BlogData {

   private String name;

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }
}

Domain

Blog (First-class citizen)
public class Blog {
    private BlogData delegate;

    public Blog(BlogData delegate) {
        this.delegate = delegate;
    }

    // Example delegate methods
    public getName() {
        return delegate.getName();
    }

    public BlogData getData() {
        return delegate;
    }
}

View Object

public class BlogBean {

    private Blog delegate;

    public BlogBean(Blog delegate) {
        this.delegate = delegate;
    }

    public String getName() {
        return delegate.getName();
    }

    // custom UI method

    public boolean isActive() {
        // custom code (UI Logic)
    }
}

Example Controller

@Controller
public class BlogController {

    @RequestMapping("/getBlog")
    public void getBlog(String name) {
        ModelMap model = new ModelMap();
        BlogBean blog = blogManager.load(name);
        model.addAttribute("blog", blog);
    }

}