The IBM Selectric-251
There was once a science fiction television series called "Fringe". In this show, otherworldly beings used a device to securely communicate: the IBM Selectric-251 Typewriter. In the show's canon, two typewriters were "quantum entangled" so that whatever you type into one of them, comes out the other without any possibility of interception & decryption.
A few months ago I was bedridden with fever, and it occurred to me that actually, the Selectric-251 was not a very well-conceived device. Besides the rather boring fact of "that's not how quantum entanglement works", it's not particularly secure. As a typewriter, all previous messages are just sitting there on paper (or on the ribbon too I suppose, if you're determined enough). Moreover, if you captured one of the typewriters, you could presumably impersonate the user without any special information. So like... not great endpoint security.
An important fact (or what seemed an important fact at the time re: fever dreams) was that there's nothing in particular about the Selectric-251 that couldn't be implemented in modern hardware for a modest cost. In fact, I could add several improvements. Consider the following list of features:
In Which we Convert Science Fiction to Science via the Mechanism of Influenza!
A few months ago I was bedridden with fever, and it occurred to me that actually, the Selectric-251 was not a very well-conceived device. Besides the rather boring fact of "that's not how quantum entanglement works", it's not particularly secure. As a typewriter, all previous messages are just sitting there on paper (or on the ribbon too I suppose, if you're determined enough). Moreover, if you captured one of the typewriters, you could presumably impersonate the user without any special information. So like... not great endpoint security.
An important fact (or what seemed an important fact at the time re: fever dreams) was that there's nothing in particular about the Selectric-251 that couldn't be implemented in modern hardware for a modest cost. In fact, I could add several improvements. Consider the following list of features:
- Two hardware devices tied together by a shared secret
- Must be able to find & communicate with each other online using only untrusted public servers
- Must use ephemeral keys, to avoid the issues of the Selectric-251, and must not store any messages
- Must allow a user secret, so that possession of the device is insufficient to impersonate the user
- Must allow convenient input methods & display
- I heard that quantum is old news now, it should be post-quantum
Choosing Technologies
After reading a few pages here, it should be clear to you that my madness mandates that I must create all the devices I conceive of. So let's think about what technology choices would make this a practical device. Or at least practical-adjacent.
MQTT is Pretty much Perfect
To find each other online, the devices will use MQTT and a two-part secret. The first part of the secret is simply a pre-shared key. The other half of the secret is a user specified string that should be different each time -- for example today's date with a phrase appended.
We connect to a public MQTT server and publish to a channel identified by the hash of those two secrets. This lets the devices find each other and initiate key exchange. There are really quite a few public MQTT servers available too!
Hardware and Key Exchange
Somewhat recently, an Arduino library for ML-KEM post-quantum key exchange was released (https://github.com/PratulDeshpande/PQCMicro). We can use this to generate & exchange ephemeral keys for each chat session. It's a bit of a pain due to large public-key sizes (800 bytes v.s 32 for ECC25519!), but this is easily manageable with modern microcontrollers.
I decided to go with the ESP32-S3 SuperMini. It's small, inexpensive, and has plenty of RAM to deal with ML-KEM. I am also not so great with high-level programming languages like C++, so the extra memory will leave me with less to worry about.
Once shared secret exchange is complete, we switch to AES-GCM to authenticate & encrypt messages for the chat session.
Input & Display
This one was always a bugbear whenever I tried to implement E2EE chat in hardware. A custom keyboard means no one will build it. An LCD screen adds significantly to the cost. Everyone has USB keyboards and screens already, but getting both working reliably with an MCU is fiddly and requires that users solder HDMI connectors to a custom PCB.
A good and simple solution somehow evaded me for over 2 years: We all have old computers, the ESP32S3 has WiFi. Just plug it in to an old computer that doesn't know the WiFi password. Now you can use whatever screen and keyboard you already use! In other words, we're implementing E2EE chat as a hardware peripheral.
Since the ESP32S3 has USB-to-serial capability, you can just plug it in to a USB port. A neat side effect, is that by adding a proper serial port, even very old computers will be able to use this peripheral! We can support all computer from the late 1960s right up until now.
This does mean we need to write an app & driver to use the peripheral, but I think that's acceptable.
Introducing the Selectric-256
I have named this device the Selectric-256, for two reasons:
- It uses 256-bit encryption
- In the television show Fringe, the story specifies that the typewrite model numbers in their world jumped from 245 to 255 with nothing in-between. So the 256 "doesn't exist" in the same way as the 251.
Once I chose the core technologies, the rest was not too hard. Getting the cryptography working reliably was a bit of a pain because I kept making mistakes on buffer sizes.
Then, there were 2 or 3 cases I caught where the server operator could collect metadata to re-identify the device users, or use various replay or denial-of-service attacks. Mitigating these was a bit of a pain, although pretty standard stuff (adding order to messages, sprinkle some nonces, adding HMAC-like signatures to key exchange).
Since it's an MCU, it's of course possible to flood it with messages faster than it can authenticate them. If you use a rate-limited free MQTT server it should be fine though. It also supports MQTT servers with username-password authentication. I didn't add TLS support though, it would have been a pain and the device doesn't rely on trusting the server anyway. Worth noting is you're using username-password authentication though, haha!
Overall the device works fine. I wrote a Python driver for it, but in principle a GUI should work fine.
Board design
Earlier, I mentioned that with an RS232 port, we could use this peripheral with a wide range of computers. Really, anything capable of 9600 baud should be fine!
It would need a board designed, so I threw something together, and sent it to the factory without checking it carefully enough. Oops.
It's a simple board, really just a MAX232 level converter that converts the TTL serial from the ESP32S3 to proper RS232 levels. However, I somehow managed to assign the MAX232 IC as being DIP-14, when in fact it is DIP-16. I assumed KiCAD would raise a DRC error due to this, but it did not!
So, my boards arrived with incorrectly assigned pins for the MAX232, and additionally, two fewer holes. I searched to see whether perhaps I had actually selected some 14-pin variant of the chip, and some kind of AI tool obscured the search results telling that no such thing existed and moreover that it was impossible because (blah blah blah).
Well, if no DIP-14 MAX232 chip exists, then I should endeavor to create one. Partly because I'm a cheapskate, and partly out of spite. Consider the following facts:
- Pins 8 and 9 on the MAX 232 aren't used in my design
- Pins past 7 are offset by two positions in my design, due to the wrong package
- MAX232 is old silicon, and so the die is probably very small, and nowhere near pins 8 & 9
There are more Things in Heaven and Earth, Gemini, than are Dreamt of in your Training Data
In other words, we can just cut part of the chip off. This is pretty easy with some wirecutters, then we sand the edge down to make it nice.
After that, we cut a few traces and add bodge wires to connect the pins of the MAX232 to the right places. Took about 20 minutes, but works fine and doesn't look terrible.
Summary
So now there IS a DIP-14 MAX232. The device works fine. I'll probably still order corrected boards, but shipping from China is not as cheap as it used to be. So I'm going to wait until I have 3-4 designs ready, and do them all at once.
As usual, if you want to actually build this thing, the files (including corrected board designs) are available. However, I'm trying out alternatives to GitHub these days. The updated source code for this one is here:
https://tangled.org/seanboyce.tngl.sh/Selectric-256