While examining Racket's built-in, continuation-based web application library, I noticed that by default, serialized continuations are sent to the HTTP client both unencrypted and unsigned. After a bit of browsing the manual, I discovered that there is some built-in support for signing serialized data using HMAC-SHA1. However, HMAC-SHA1, while not as insecure as a naive approach using plain SHA1, isn't the cryptographically strongest algorithm around. This encouraged me to write my own little library of cryptographic algorithms.

In addition to HMAC and Whirlpool, which were originally intended to be used as a drop-in replacement for Racket's HMAC-SHA1 function, this library provides implementations of Dan Bernstein's CubeHash hashing function and Salsa20 stream cipher.


You can require the PLaneT version directly from Racket:

(require (planet mbenkard/mulkrypt))

Development Access

If you want to hack Mulkrypt (there's an apparently incorrect implementation of Threefish in there; if you can fix it, that would be great!), you can fetch the Mercurial repository using the following command:

hg clone

(Mind the trailing slash. My web server is overly picky there.)

Implemented Algorithms

  • Cryptographic hashing: Whirlpool, CubeHash
  • Message authentication: HMAC
  • Stream ciphers: Salsa20

Implementation Features

  • No dependencies other than Racket's built-in libraries
  • Pure Racket (no use of C code or foreign libraries)
  • AGPLv3 license
  • Stream ciphers operate on (possibly infinite) sequences, including ports, and output (again, possibly infinite) sequences.


> (define fox-and-dog #"The quick brown fox jumps over the lazy dog")
> (printf "~x" (cubehash-512x fox-and-dog))
> (printf "~x" (whirlpool fox-and-dog))
> (printf "~x" (hmac cubehash-256 32 16 #"key" fox-and-dog))
> (sequence->list (salsa20 #"<<<<<key of 16 or 32 bytes.>>>>>"
(122 146 89 152 145 152 42 248 229 225 154 77 160 250 22 247 6 191 4 202 154 
 186 141 181 124 241 166 3 1 133 42 128 25 136 203 216 165 24 195 21 159 96 105)