These days where a cheap GPU for about 100 € is capable to create 3 billion of MD5 Hashes per second, we need not only need to use salts the right way but we also need to choose a strong, non-reversible and slow hashing schemes when storing passwords in our application.
Heimdall is a library that implements a secure and upgradable password hashing mechanism and uses at the time of writing this article PBKDF2 SHA-1 HMAC with 20000 iterations and a 192 bit (24 byte) salt per default.
In the following short examples I’d like to demonstrate how to create password hashes, how to verify passwords and how to check if a password hash needs to be recreated using a more secure algorithm.
Why Heimdall?
Heimdall acts as a wrapper not only to create and verify hashes but also to check if a hash is outdated and needs to be recreated using a more secure algorithm or a higher iteration count.
QAWare have written a nice article about “http://qaware.blogspot.de/2015/03/secure-password-storage-and.html[Secure password storage and authentication]” that summarizes common mistakes when storing passwords for further reading here.
More detailed information about hashing in Java is offered by the Open Web Application Security Project here.
For a discussion about choosing the correct iteration count when using PKBDF2-SHA256 can be found on Stackexchange.com here.
Dependencies
We need two dependencies here, Heimdall and Guava (afaik Guava won’t be needed with the upcoming version of Heimdall).
So finally this is our build.gradle (using Gradle):
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'application'
mainClassName = "com.hascode.tutorial.HeimdallExamples"
sourceCompatibility = 1.8
version = '1.0.0'
jar {
manifest {
attributes 'Implementation-Title': 'hasCode.com Heimdall Encryption Tutorial', 'Implementation-Version': version
}
}
repositories {
mavenCentral()
maven {
url 'https://raw.githubusercontent.com/qaware/heimdall/master/repository/'
}
}
dependencies {
compile 'de.qaware:heimdall:1.2'
compile 'com.google.guava:guava:18.0'
}
Hashing in Action
In the following application, we’re ..
-
creating a password hash
-
printing the hash to STDOUT
-
verifying the hash against the password
-
verifying the hash against a false password
In addition, inside the verification method, we’re checking if our password hash needs a rehash.
package com.hascode.tutorial;
import de.qaware.heimdall.Password;
import de.qaware.heimdall.PasswordException;
import de.qaware.heimdall.PasswordFactory;
import de.qaware.heimdall.SecureCharArray;
public class HeimdallExamples {
public static void main(final String[] args) throws PasswordException {
char[] plaintextPassword = "soosecret".toCharArray();
String hashedPassword = hashPassword(plaintextPassword);
System.out.println("the hashed password is: " + hashedPassword);
System.out.println("verifying a wrong password succeeds: " + verifyPassword("wrongpassword".toCharArray(), hashedPassword));
System.out.println("verifying the right password succeeds: " + verifyPassword("soosecret".toCharArray(), hashedPassword));
}
private static String hashPassword(final char[] plaintextPassword) throws PasswordException {
Password password = PasswordFactory.create();
try (SecureCharArray cleartextPassword = new SecureCharArray(plaintextPassword)) {
return password.hash(cleartextPassword);
}
}
private static boolean verifyPassword(final char[] plaintextPassword, final String hashedPassword) throws PasswordException {
Password password = PasswordFactory.create();
try (SecureCharArray cleartext = new SecureCharArray(plaintextPassword)) {
if (password.verify(cleartext, hashedPassword)) {
if (password.needsRehash(hashedPassword)) {
String renewedHashedPassword = password.hash(cleartext);
System.out.println("password needed rehash: new hash is " + renewedHashedPassword);
// store new hash etc ...
}
return true;
}
return false;
}
}
}
We may run the application using our IDE our Gradle e.g.
$ gradle run
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:run
the hashed password is: 1:1:SKSJ8ayV9Lxo/J7wh2opqVeqJKc82Dic:i=4e20:MmsdqRcqN//ltOWfsw8FXoq0vhLI6hRb
verifying a wrong password succeeds: false
verifying the right password succeeds: true
BUILD SUCCESSFUL
Total time: 8.112 secs
Tutorial Sources
Please feel free to download the tutorial sources from my GitHub repository, fork it there or clone it using Git:
git clone https://bitbucket.org/hascode/heimdall-encryption-tutorial.git