Pages

Tuesday, December 13, 2011

Password encryption in Java

This time, it's about security.
And specifically about how as a developer, you should protect the passwords of your users.

I think there can't be enough emphasis of how important it is to keep the password of your users safe.
So, instead of 'lecturing' about why you should do it, lets dive in right away into how you do it.

So, given the fact you have different users on your system, and each of them has a password,
we would like to keep their passwords safe.

This translates to storing their passwords somewhere (a DB for example), encrypted.

So before we really give code example how it's done, a small note on encryption:
When you pick an encryption algorithm to apply on your passwords, try to think if you ever
plan on decrypting them. In most cases the answer is 'NO'.
(Picking a symmetrical algorithm also means that in case an attacker finds out the key,
they can use it to decrypt the passwords).

Thus, we'll drop all symmetrical algorithms such as AES(Rijndael), RSA based, etc.. and pick
an asymmetrical encrypting algorithm such as hashing.

Hashing algorithms such as SHA are asymmetrical-key algorithms, meaning that for an attacker
that put their hands on the encrypted password it is impossible to recover the original password.
Different inputs for SHA can yield the same output, but with a very low probability.

Now that we understand why we should use a Hashing algorithm, we can explain the steps for
encrypting and give an example code how it's done in Java.

Encryption recipe:

1. Take password and salt* as an input.
2. Apply some hashing algorithm on the input. (We will choose SHA-256)
3. Repeat step 2 a large amount of times where the input to the algorithm is the last output of the encryption.

*salt - Is an additional fixed input for adding complexity for the encrypted password.

Lets write this in Java:




package nm.example;


import org.apache.commons.codec.binary.Base64;
import java.security.MessageDigest;


public class PasswordEncrypter {


    private final static int NUMBER_OF_HASHING = 10000 ;
    private final static String CHARSET = "UTF-8" ;
    private final static String ENCRYPTING_ALGORITHM = "SHA-256";


    /**
     * Encrypts a given password.
     */
    public static String encryptPassword(String salt, String password) throws Exception {
        // Transform the given password & salt to Base64 in order
        // to work on a closed set of 64 characters instead of Unicode.
        Base64 base64EncoderDecoder = new Base64();
        String b64password = base64EncoderDecoder.encodeAsString(password.getBytes(CHARSET)) ;
        // Create the salt & transform it to Base64.
        String b64Salt = base64EncoderDecoder.encodeAsString(salt.getBytes(CHARSET));
        // The encryption!
        byte[] proposedDigest = getHash(b64password, b64Salt);
        return base64EncoderDecoder.encodeAsString(proposedDigest) ;
    }


    /**
     * From a password, a number of iterations and a salt,
     * returns the corresponding digest
     */
    private static byte[] getHash(String password, String salt) throws Exception {
        MessageDigest digest = MessageDigest.getInstance(ENCRYPTING_ALGORITHM);
        digest.reset();
        digest.update(salt.getBytes(CHARSET));
        byte[] passwordBytes = password.getBytes(CHARSET);
        byte[] input = digest.digest(passwordBytes);
        for (int i = 0; i < NUMBER_OF_HASHING; i++) {
            digest.reset();
            input = digest.digest(input);
        }
        return input;
    }
}

So the output for:  
PasswordEncrypter.encryptPassword("secret-salt", "my-password")
is "NiNP/e/NOzmoCQGaShXENFzpYXv7+EclH9st+dnfBWE="

As you can see I'm using the Apache Commons Codec library for Base64 encoding,
which is available at: http://commons.apache.org/codec/download_codec.cgi


Happy encrypting.

Wednesday, November 30, 2011

(J)Unit testing with in-memory DBs & JPA on Spring FWK

I am aware that this issue has been addressed by many in the community.
I'm not trying to convince why to perform unit testing against a DB, I'm just trying to explain how to do it.

The reasons of why to do it are many, but to name a few, you could say that:
A DB to use in production still doesn't exist or its structure is missing, In-Memory DBs
require no maintenance, you're testing your code against a real DB, etc...

So you are using the Spring FWK and you decided using JPA in your Data Access Layer,
and you write your code for your DAO (or Service) and your sophisticated queries,
right after you wrote the test class for that DAO of course... and now you want to run the unit test.
On runtime your DAO uses an EntityManager, which is initialized with your persistence unit
to perform actions against a DB.

But you want to make sure your code runs and passes the test before you run the build, and test
the entire application against the DB that will be used in production.

To test this DAO, obviously we need a DB to run it against.
If you still don't have a DB that has been created/configured or you just want to get going,
without having to install a new DB just for the sake of testing - In-Memory DB can offer a great solution.

Two In-Memory DBs which I have experience with are HSQLDB & H2 DB.
My preference out of experience is to use H2 DB, as it offers some functionality that HSQLDB doesn't, as well as a very comfortable console to browse through the DB you created.

The "recipe" for using In-Memory DB is as follows:
1. Download the In-Memory DB jars.

2. Include them in your class-path. (If you're running in Eclipse or intelliJ make sure the jars are there).

3. Under the root "tests" package or where your Test class is, make sure to create the "test/META-INF" directory and place the "persistence.xml" file in it.

4. Configure the persistence.xml file to use the In-Memory DB.
    For instance, if you're using Hibernate, you can configure it as follows:

<persistence>
.....
<persistence-unit name="my-unit"....>
       <provider>org.hibernate.ejb.HibernatePersistence</provider>
       <class>org.mycompany.model.MyEntity</class>
       .....
<properties>
   <!-- You have to set this value to either create-drop/create/update -->
            <property name="hibernate.hbm2ddl.auto" value="create" />
            <property name="hibernate.show_sql" value="true" />
            <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" />
            <property name="hibernate.connection.driver_class" value="org.h2.Driver" />
            <property name="hibernate.connection.url" value="jdbc:h2:~/testdb" />
            <property name="hibernate.connection.username" value="sa" />
            <property name="hibernate.connection.password" value="" />
        </properties>
</persistence-unit>

</persistence>  

5. Your unit test class should be annotated with the following:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"/application-context.xml"})
public class MyDAOTest {
...
}

From now on, every time you run your unit test it will run against an In-Memory DB.
Something important to note is that I faced a problem when I used HSQLDB,
and had my entities direct to a schema name different than the default,
that was a schema called "conf" where configuration related data was planned to be kept.
Eventually the test failed.

This is because Hibernate fails to create those schemas.
See this link for more details: https://hibernate.onjira.com/browse/HHH-1853.
What you should do, is create those DB Schemas before the Unit Test executes.

In H2 DB there's a nice feature that lets you run a query or a SQL file when the Spring container boots.
In that file (create.sql) you can write a line to initialize your DB and create the needed Schema for instance:

CREATE SCHEMA conf ;

Which would create the "conf" schema.
What you need to do is set up the URL to the H2 DB as follows:
<property name="hibernate.connection.url" value="jdbc:h2:~/testdb;INIT=RUNSCRIPT FROM '~/create.sql'" />
Which would execute the create.sql file from your home directory (running on Linux).
You could also specify instead of the home directory ("~"), simply a lookup in the classpath:

<property name="hibernate.connection.url" value="jdbc:h2:~/testdb;INIT=RUNSCRIPT FROM 'classpath:create.sql'" />
I anyway recommend you to take a look at H2 DB website:
http://www.h2database.com/html/main.html
to get aquainted with its features closer.

The above H2 DB settings for Hibernate's connection URL will store the H2 DB data to a file (testdb.h2.db) under your home directory. This is very handy in order to get a close look of the created DB and analyze it, H2 DB offers a browser-based console when you run it's jar.

So if you refrained from testing your DAOs in your application until now because you did not
want to run against a full blown DB or didn't know exactly how to do it in the Spring environment,
I hope this post shed some light on this matter.

Happy testing.