Karl Hans Janke Kollaborativ
Heute die Welt, morgen das Sonnensystem!

sep 2009

The Skein hash function in 256 lines of C

Note: I'm going to switch this thing over to English now, because I expect to ask some non-Germans for feedback in the future. I might also translate some old posts.

teichufer.klein.jpg
A view across the lake at HAR 2009 towards the CCC's geodesic party tent. Me and friends camped just about outside the right edge of the picture.

So here's the latest installment of my exploits into the forbidden realm of implementing cryptographic primitives.

After building my little crypto chat experiment last month, one thing sorely missing was message authentication (from p2p.c):

printf("receiving packets on port %d\n", LOCALPORT);
printf("CAUTION: Message senders can be spoofed.\n");

The obvious solution to this problem are message authentication codes, particularly because the diffie-hellman setup already yields shared secrets between any two parties. A typical way to construct MACs is to take a cryptographic hash function and compute its value over a combination of the message and the secret (the standard construction of this kind is called HMAC). So I set out to find a nice little hash function which could be easily and elegantly implemented. Unfortunately, the obvious candidates didn't quite satisfy me. I kept looking and eventually ended up with the promising description of Skein:

Skein is a new family of cryptographic hash functions. Its design combines speed, security, simplicity, and a great deal of flexibility in a modular package that is easy to analyze.

Without much regret, I commited the next step up on the ladder of serious crimes in the construction of crypto systems: I set out to use an unproven algorithm. Hooray! >:)

Incidentally, one very nice feature of Skein is that it already offers a mechanism to turn it into a keyed hash function. If my understanding is correct, this is essentially due to the fact that Skein is actually derived from a block cipher (actually called Threefish ;)). I have yet to implement this MAC mode, but it's basically a detail once the rest is set up.

As of yesterday, the code finally produces the correct output on the official one-byte test vector. Feel free to try it on the longer ones. What took me so long? First, there was HAR. I had it pretty much complete at that point, except for one of those nasty segfault bugs. When I took a good hard look at things again this week, it turned out to be an overlong memset() corrupting my stack. God, I love those! ;)

There are some limitations to the code at this point:

Appendix: skein.c