Branca and yak shaving

A while ago I wrote about the alternatives to JWT tokens. One of the them was Branca. It’s a base62-encoded, XChaCha20-Poly1305 encrypted token with an abritrary payload. Before writing the post, I thought out it would be nice to have a Branca library for Clojure and that’s something I’ve occassionally worked on since then.

First I wrote base62 encoder and decoder and published them as a tiny library called clj-base62. That was easy enough. Then I needed to implement the encryption part.

First I looked at using caesium, a Clojure binding for libsodium. It looked great except for one thing: it does not come with native libsodium binaries (the .so/.dll/.dylib files). You’ll have to install them yourself and this makes using it a hurdle.

Then I looked at using Google’s Tink which has pure-Java implementation of the required algorithms. It is also opinionated about key management. The opinions seem very smart, but it also makes it hard to just pass in a string as an encryption key. Passing in a string seems like not so great idea, but I’d like my library to be interoperable with the other Branca libraries that do exactly that.

I also couldn’t build tinkey, Tink’s key management tool, on my personal laptop. It requires a specific version of Bazel that was not available via NixOS’s package collection.

Finally I tried using Lazysodium. Like caesium, it’s a Java binding for libsodium, but unlike caesium, it comes with the binaries. I quickly implemented token encryption and decryption - and realized that my code refuses to decode tokens produced by branca-js and vice versa.

I was using Lazysodium’s Lazy interface. It operates on strings, which seemed weird to me, until I realized that it’s not just byte arrays disguised as strings – it’s hex strings (strings of ASCII hexademical digits). So now I still need to either add some byte-arrays-to-hex-strings conversions or use Lazysodium’s Native interface, which is very C-like but which operates on byte arrays. Then I’m hopefully done.

I thought implementing Branca tokens in Clojure would be a quick two-evening job. Alas.

Comments or questions? Tweet to me or send me an e-mail.