During the past week, I was busy improving our token generation techniques. It ended up in a complete rewrite of our access token generation mechanism. Long story short, a few things to keep in mind when working with security:
UUID can hurt (see the standard, 6. Security Considerations)
Designed by NSA (beware, this is NOT the company behind the NSA Panel project). Collision-free, widely used, pick up this one if you're already bored with my article.
The winner of the 2012 NIST hash function competition, isn't derived from SHA-2.
It's relatively easy to set up a pre-SHA-3 algorithm (SO, tutorials, and a small amount of effort). Sadly the most popular crypto libraries providing SHA-3 implementation have almost no usable resources (at the time of writing this article). There are dozens of independent implementations of the SHA-3 algorithm, but you probably just don't have enough time to go through them and check their validity.
Show me the code, I'm in a hurry
The complete demo project can be found at https://github.com/akoskm/bouncy-castle-sha3.
I decided to go with Bouncy Castle, the library known for providing cryptographic API (includes SHA3 from version 1.48) for Java and C#.
org.bouncycastle.jcajce.provider.digest.SHA3.DigestSHA3 gives you a
DigestSHA3 instance, subclassing MessageDigest, which later can be used like:
DigestSHA3 md = new DigestSHA3(256); //same as DigestSHA3 md = new SHA3.Digest256(); md.update("secret".getBytes("UTF-8")); byte digest = md.digest();
There are other constructors like
Digest256, ... providing you a digest of different sizes (I tend to avoid such constructors in practice and use factory methods or function arguments to set a custom size).
Once you get the
byte you're almost done, the input is encrypted and the output is ready to use. Almost.
You probably want to store this hash in your DB or send it to your clients' browser, etc ..., so it would be nice if you could convert these bytes into String.
One thing, don't do this:
BigInteger bigInt = new BigInteger(1, digest); return bigInt.toString(16);
I prepared some unit tests to demonstrate the catch here. I used the example results from SHA-3 (bottom of the page), almost all of them passed, except the Keccak-512 with the empty string. During the conversion, it lost the leading 0, and instead of
Obviously, the conversion didn't work very well (if you know the exact reason, feel free to leave a comment below). Fortunately, Bouncy Castle already has a utility method that converts
byte  to
org.bouncycastle.util.encoders.Hex.toHexString(byte  data)
Your SHA-3 hash has been served, use it for the greater good!