blog.mikro2nd.net

Into the Kingdom of Bouncy Castle; Here Be Dragons

Wikid Exploration the First

After a bit of downtime over the holiday season, it's back to work on the Wikid Project.

Having got as far as making a working (albeit very bare bones) wiki platform, it's now time to start looking at some of the explorations I had in mind in starting the journey. My first use-case is this:

I keep a mass/mess of personal notes in my own notebook ("2nd Brain" if you like, though I dislike the term) where Zim Desktop Wiki is my tool of choice (and has been for over 5 years so far). The trouble is that some of the pages are things I want to share over in my web garden. Well, initially that's easy enough, since Zim can export/copy text in that Fucking Horrible Markdown language, for import into the Hugo engine that currently powers the garden. The trouble is that web-garden pages are not dead and done once they're written. They're living, breathing, evolving precious flowers. But as soon as I edit one of those articles -- whether I edit in the Garden or in my Zim notebook -- they're out of synch. Likely forever. And that's a major inconvenience.

So what I want is for my local wiki to be the True Source. This is where I create and edit the thousands of pages that make up my networked-exomemory. When I want to share a particular thought (wikipage) I'd like to just mark it as "Share this page with That Other Wiki Over There." That Other Wiki would be a public-facing instance that can receive the pages and allow the world to read them. i.e. It's a form of sharing that merely pushes a copy of a page from one wiki instance to another. (I have vague thoughts of including ActivityPub in that picture somewhere down the line. Another Exploration for another day.)

Later on I'll be Exploring more interesting and sophisticated sharing and collaboration models. This is the whole purpose of the Wikid project. Baby steps, remember.

Federation and the Spam Factories

All these ideas around sharing notes and ideas mean that we need some authentication and authorisation. We don't want the "AI" spam factories to spew their bile into our exobrain spaces, but we do want seamless and low friction ways of moving wiki pages between instances with ease and comfort. And that means we'll need some cryptography. Specifically, each Wikid instance (and Wikid clients) will need its own identity and a public/private keypair so that we can verify where new pages, new edits are coming from.

Let's imagine a case where I, in innocent good faith, authorise My Very Own Wiki to accept pages and such from Evil Wiki. At first they're quiet and behave reasonably well, but then something happens and they begin to hurl turds into my web-garden. All that's going to happen is I'll revoke their permissions (delete their keys from my wikid-instance's database of authorised providers) and defederate them. (And then remove the offending pages, of course.) It's nasty, but it's not going to be the end of the world.

So the next Small Step I can take is to cryptographically sign every outgoing bit of wikistuff to prove that it's coming from me, and to verify that every bit of incoming wikistuff is from someone I know (well, one of their Wikid instances really). I'm happy to make the initial introductions happen out-of-band (at least for now!) But this crypto stuff needs to get working sooner rather than later.

So into the Java Crypto Architecture we dive. I've done this before. For money, even. On Android, no less. And it's... mostly not a lot of fun.

Generating a keypair, using it to sign and verify messages... easy peasy.

Storing the keypair in a safe way? Ha! Fuggedaboutit!

What God Wants...

Of course one turns to the Java crypto KeyStore, since that's where the good stuff for storing secrets is supposedly abstracted; where the difficult, cryptographically sensitive stuff has supposedly been implemented by experts. Don't roll your own crypto, remember!

Only it turns out that storing a private key requires that you store it with a Certificate (strictly a Certificate Chain) that "guarantees" that the key really belongs to the entity who claims to own it and also carries a copy of the public key.

Evidently the Crypto Wizards who designed this stuff forgot that sometimes I just don't give a shit! I'm in a low-threat scenario where the consequences of a breach are not hugely significant, and quite easily remedied. But they require a Certificate holding the public key half of the keypair and I have no Certificate in sight.

Remember that we want installation of a Wikid instance to be a one click sort of thing so that mere mortals can use it, too. We definitely don't want to be applying to Certificate Authorities for Certificates, waiting until those arrive and then having to instal them in obscure places in our computer's filesystem. Much too high a hurdle!

Well, OK! I'll just roll a self-signed certificate.

No you won't.

There is no way in the JDK APIs to generate a new Certificate. None. You can create Certificate instances by slurping in a serialised certificate generated elsewhere and elsehow, but there is no way to create a new one (which I'd then sign with the same private key I'm trying to protect at rest).

Please, please, please don't make me use Bouncy Castle ever again! It's this sort of shit that caused me to leave the industry once before.

Enter the Realm of the Bouncy Castle

The Bouncy Castle home page: Welcome to the home of the Legion of the Bouncy Castle. A fun place to stay, if you've got some time to kill.

You have got to be kidding me. I had to use this stuff several and a half years ago, in an era when Android lacked any sane crypto APIs of its own as Google, in their wisdom, decided to leave those choices to the device vendors who all made wildly different choices. In consequence there was nothing an application developer could rely on, so we all ended up using the Android variant of Bouncy Castle when we had to do any cryptography. And on mobile platforms you always need to do cryptography.

Bouncy Castle: If you have to use this piece of shit, you might want to consider killing yourself as a fun alternative to the excruciating time you're going to have to spend in the Kingdom of the Bouncy Castle. Bouncy Castle is a perfect example of Poisoned OpenSource. (I'll come up with a better name one day and write more about what it means.)

But. BC can generate certificates all by itself, and, in particular, self-signed certificates. Oh god, this is going to make me bleed.

It means you're going to use BC-specific interfaces and such, and are stepping outside the confines of the standard Java Crypto Architecture.

Advice to Young Developers everywhere: Hide this shit behind interfaces of your own devising.

And Here We Are

Stokseel aleen op 'n Saterdagaand... I tremble in fear and trepidation but there seems to be no other reasonable choice. Into the Dragon's Lair I go...