I’m working on a spray framework REST based tech demo project, and I want to securely store passwords as salted hashes in a database. I took a look around at existing projects, and couldn’t find quite what I was looking for.

  • simple to use and understand
  • based on JVM built in crypto libraries
  • written in Scala

The closest thing I found was this: Java PBKDF2 Password Hashing Code

But it is written in Java…. So I took a crack at porting it to Scala.

It lives here on github:

https://github.com/dholbrook/scala-password-hash

The public methods createHash() and validatePassword() are for the most part the same as the Java version. Some of the private methods are quite a bit different.

slowEquals

This is an interesting method in the Java implementation. It is designed to always take the same amount of time to determine equality regardless of the length of the arrays being compared. Additionally it uses the XOR operator ^ to produce consistent branching. I suspect using XOR in Java this way is somewhat controversial, regardless I used a similar approach in my Scala implementation.

Java: slowEquals()
1
2
3
4
5
6
7
private static boolean slowEquals(byte[] a, byte[] b)
{
    int diff = a.length ^ b.length;
    for(int i = 0; i < a.length && i < b.length; i++)
        diff |= a[i] ^ b[i];
    return diff == 0;
}

The most significant change in the Scala port is making diff immutable. The same result is achieved by folding over a range, and using an accumulator seeded by the initial test of a.length ^ b.length.

Scala: slowEquals()
1
2
3
4
5
6
7
private def slowEquals(a: Array[Byte], b: Array[Byte]): Boolean = {
  val range = 0 until scala.math.min(a.length, b.length)
  val diff = range.foldLeft(a.length ^ b.length) {
    case (acc, i) => acc | a(i) ^ b(i)
  }
  diff == 0
}

fromHex / toHex

The utility functions fromHex and toHex saw a big size reduction.

Java: fromHex() and toHex()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
    private static byte[] fromHex(String hex)
    {
        byte[] binary = new byte[hex.length() / 2];
        for(int i = 0; i < binary.length; i++)
        {
            binary[i] = (byte)Integer.parseInt(hex.substring(2*i, 2*i+2), 16);
        }
        return binary;
    }

    private static String toHex(byte[] array)
    {
        BigInteger bi = new BigInteger(1, array);
        String hex = bi.toString(16);
        int paddingLength = (array.length * 2) - hex.length();
        if(paddingLength > 0)
            return String.format("%0" + paddingLength + "d", 0) + hex;
        else
            return hex;
    }
Scala: fromHex() and toHex()
1
2
3
4
5
    private def fromHex(hex: String): Array[Byte] =
      hex.sliding(2, 2).toArray.map(Integer.parseInt(_, 16).toByte)

    private def toHex(bytes: Array[Byte]): String =
      bytes.map("%02X" format _).mkString

Testing

I tested the code by using it in conjunction with the existing Java implementation. Verifying that passwords created by each side were interoperable with the other. I used ScalaCheck to randomly generate a set of passwords to test.

PasswordHashTest
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
package scalapasswordhash

import org.scalacheck.Gen
import org.scalacheck.Gen._
import org.scalatest.FunSuite
import org.scalatest.prop.GeneratorDrivenPropertyChecks
import passwordhash.{PasswordHash => JPasswordHash}

class PasswordHashTest extends FunSuite with GeneratorDrivenPropertyChecks  {

  test("hash generated from Java should validate with Scala") {
    forAll (identifier) { (password: String) =>
      val h1 = JPasswordHash.createHash(password)
      assert(PasswordHash.validatePassword(password, h1))
    }
  }

  test("hash generated from Scala should validate with Java") {
    forAll (identifier) { (password: String) =>
      val h1 = PasswordHash.createHash(password)
      assert(JPasswordHash.validatePassword(password, h1))
    }
  }

}

The conversion from Blogger to Octopress/Jekyll went a lot smoother than I expected it to. The DNS now seems to be working correctly, I’ve updated Google Analytics to use the new site, and I added some redirect pages that match the old site so searches can still find the old content.

I still have a few things I want to do.

  • Change the default Octopress favicon.
  • Add a top categories sidebar
  • Categorize old articles

As an aside, I’m really enjoying using Markdown to author blog posts. I’m using MakrdownPad 2 on Windows and it is very slick.

Mostly Blather is moving from Bloger to Github Pages.

I am using Octopress with the Octostrap3 theme. I imported the old blogger site with jekyll-import.

Some of the formatting of the old site has been lost, and there seems to be no good way of bringing the comments over. Expect my next post to be about how it all worked out.

Note: The old site is still available here.