mala::notes

Ch35t 0.1.9

or: a Fediverse thread that could have been a blog post.

After an almost 2-years hiatus, a new version of ch35t (0.1.9) is out. If you were not expecting this, just know I am more surprised than you!

I just couldn’t hear my son say he’s bored anymore, so I built a riddle for him. Well, the intention was a scavenger hunt, but I had to downsize this to something I could finish in one day (but still hard enough so that I could create one more before he completed it). Preparing the riddle was easy, but it became an excuse to pick up ch35t again… And there went my Saturday.

If I had to change one thing from my old 356* hacking challenge website, that would be its centralized nature. Having a curated set of riddles was definitely a plus, but I was also a bottleneck to people’s creativity. Similarly, any website is a bottleneck for riddles: what if it goes down? What if someone wants to play them offline? Why should one be in control of anyone else’s riddles? Well, I guess you all get the advantages of decentralization around here…

Ch35t is called this way because “it’s a chest with a little bit of 3564020356 in it” 🙂. It is first and foremost a format, defined with a json schema, that one can use to formalize a riddle. There’s a “label” with name and author, a hint telling you how to find the chest’s key (the riddle answer), and then the chest’s payload, that you only get if you have the right key. Both hint and payload are data which can take any format. The payload is locked with the key via encryption.

What does a #ch35t look like? Check out the picture below, or http://3564020356.org/ch35t/examples/ for a few examples.

A screenshot from Firefox showing the content of the JSON file available at http://3564020356.org/ch35t/examples/deserve_b64.json. All fields are expanded showing a “label” with a “name”, a “hint” with “origin” and “data”, and a payload with “data” and a “method”, whose “name” is “md5”.

What riddles can you create with it? The simplest ones hold a plain text question and the md5-encrypted answer you need to find. But you can also use eg. a base64-encoded zip file for your hint, and AES to encrypt another file using the riddle’s answer as a key. This is already enough to encode almost all 356* riddles as ch35ts, so that anyone will be able to play with them even when the site is long forgotten.

Ch35t is also a python library that parses its own format. Until yesterday, it came with a CLI client to read a json, validate it, show all information from a chest (including decoding different hint formats), and unlock it with a key. For my son’s riddle, I just built a marimo client that provides a nice browser UI. I made sure all python deps are supported by pyodide, so the client becomes a portable static HTML file + JavaScript. This way, my son just needs to connect to a URL to play.

“All this effort and you still connect to a website? How’s that decentralized?”

Well, I have now become just one endpoint: anyone can (statically) host the marimo client. Or you can build another client in any language and as long as it supports the standard, the riddles will still work. The riddles themselves can be shared as plain text in a post, a json file on a pendrive, a URL. Once one has the json, they can play offline (unless the riddle requires one to check stuff on the Internet).

A screenshot from Firefox showing the URL http://3564020356.org/ch35t/wasm/. The page shows a text field called “URL” whose content is http://3564020356.org/ch35t/examples/deserve_b64.json. Then a title: “Deserve Me - A base64 variant”, followed by some encrypted text: MAL TIRRUEZF CR MAL RKZYIOL EX MAL OIY UAE RICF "MAL ACWALRM DYEUPLFWL CR ME DYEU MAIM UL IZL RKZZEKYFLF GH OHRMLZH". Below that, another text field called “PASSWORD”

This is the link to the marimo app. The riddle you’ll find is the one that gives you access to my old website, in case you are curious to check it out 🙂. If you change the URL to another valid JSON (see the ch35t/examples dir) a new riddle will load. You can already create your own riddle in #ch35t format, provide its URL here, and play it. There are still good chances that something will break 😇 so please lmk if it does and I’ll fix it. Or you can, the code is all there! 😜

Oh yes, the code: it’s at https://github.com/aittalam/ch35t.

If you want to build your own client using the library, you can install it with a pip install ch35t and test its primitives with the CLI client. The documentation is sh1t ATM because tbh I was not expecting to have something running by the end of the weekend 😂 but I’ll improve it soon. The code too: I still have to bring in digital signatures to verify riddle authenticity and more data formats to support natively.

In the meantime… have phun 🙂