A while back I was trying to implement HTTP signatures to use with ActivityPub interactions with Mastodon. In Clojure. There is a go-to library for Clojure when it comes to crypto stuff, but I couldn’t get it to do the specific thing I needed: SHA-256 / RSA signatures. I looked at other options too, but as I’m not familiar with NaCl, that was just a confusing mess of wrappers around Java wrapped around C.
In the end I went with using Java interop to call Bouncy Castle stuff directly. I hate Java and interop in Clojure just feels wrong, but at least I could get it to work. Not to mention if something, Bouncy Castle is maintained. It wasn’t exactly a joyride, but it works. Check out the source if you’re interested (or want to use it). I didn’t make it stand-alone or put it up on Clojars (yet).
Java’s a pain in the neck to deal with. It’s strangled by its obsession with types and it struggles to break free every single line. Even in Clojure I had to type hint a lot of stuff to appease
lein check. I’m still sure that giving my code some weird stuff (even just an invalid string) could make the Java explode in the usual 300 lines of indecipherable stacktrace.
My goal was to wrap the Java as well as possible so that once I’m done I (and anyone else) won’t have to touch it again. Obviously there are improvements to be made, but it’s capable of fulfilling its purpose already (while I haven’t used it in a web service yet, it definitely worked on the REPL).
When I used Kotlin on Android, it was pleasant how it hid the getter-setter Java abominations behind more natural accessors. Sadly that doesn’t happen in Clojure, so we end up having to call
.getBytes instead of a more Clojure form of expression (though
doto is helpful).
Stuff that stalled me for surprising amounts of time were having to set the BC crypto provider and the ridiculous roundabout way of having to use multiple writers just to get strings out of it and vice versa. It was also interesting that while private keys can masquerade as keypairs, public keys can’t do that. Sure, it makes sense if I write it down like that, but it was really weird when I accidentally returned the key instead of the keypair object, and it’d break only in certain scenarios. I went with using explicitly private key objects because who knows what exactly is common between