Helper class to simplify the use of Bouncy Castle's scrypt implementation for salted password hashing.

Mark George authored on 2 Oct 2021
src Updated deps, upped work factor, add timing tests 3 years ago
.gitignore Initial commit. 5 years ago
README.md Update README.md 3 years ago
build.gradle Updated deps, upped work factor, add timing tests 3 years ago
README.md

BouncyScrypt

A facade for salted password hashing with scrypt using Bouncy Castle.

Generates output that is in a format similar to Modular Crypt Format (MCF). The output includes the following fields (separated by a $ character):

  • The work factors that were used bit-packed into a single Integer.
  • The Base64 encoded generated salt.
  • The Base64 encoded derived hash.

The result looks like:

$919553$mshp5K/vaKkdSzbRqqMTLwr76eSurBsTuVCIIDxuZEE6u093MHBk0Miaq3Qp/Vd7QdP/WeOglVg6W/omiNfC8g==$eV7FfnHnmwyCU8i4rAHQ6NO5RZp53/V1Wr3jsFCc1BqM6yvmGp6BfG7VFrmz21cFlzf4F/aPkgRuO5DRBHgIPQ==$

The salts are generated using Java's SHA1PRNG secure psuedo-random number generator.

The standard scrypt work factors are used:

  • N = 32768
  • r = 8
  • p = 1

Both the generated salt and the derived hash (dkLen) are 64 bytes. The generated output is 186 characters.

API

// generate a hash
public static CharBuffer hash(CharSequence password)

// check a password against a hash
public static boolean check(CharSequence mcfHash, CharSequence password)

Usage

The API uses CharSequence objects as input and CharBuffer objects as output. This gives us a couple of choices:

  • Use String objects for simplicity. The downside of String objects is that they are immutable meaning that we can't overwrite the sensitive data when we are finished with it.

  • Use char[] and CharBuffer objects so that we can overwrite the data when we are finished with it.

Simple mode (using Strings)

Generating a hash:

String password = "testing123";
String hash = ScryptHelper.hash(password).toString();

Checking a password against a hash:

boolean isValid = ScryptHelper.check(hash, password);

Paranoid mode (using char[] and CharBuffer objects)

Generating a hash:

char[] password = "testing123".toCharArray();
CharBuffer cb = CharBuffer.wrap(password);
CharBuffer hash = ScryptHelper.hash(cb);

Checking a hash against a password:

boolean isValid = ScryptHelper.check(hash, cb);

Overwriting the sensitive data once you have finished with it:

Arrays.fill(password, '0');
Arrays.fill(hash.array(), '0');

Disclaimer

I am not a cryptographer. Use at your own risk.

License

Copyright 2018, Mark George

FreeBSD License (BSD-2-Clause)

https://opensource.org/licenses/BSD-2-Clause