punchsig: cryptographic signatures, data diodes and trusted input
Look at this beauty. This box is a small USB dongle I built over the weekend with a bunch of junk electronics I had lying around. The dongle cryptographically signs short text inputs directly from your USB keyboard.
What is in this box? The dongle acts as an interposer: keyboard plugs into one side, computer into the other. It forwards keystrokes transparently, and can cryptographically sign text you type. To the computer, it just looks like a regular USB keyboard. Internally, the dongle has a “secure processor” which holds the signing keys and generates the ed25519 signature.
the twist #
So far, all pretty standard. The twist here is that the dongle’s secure processor is isolated by design – it’s airgapped in one direction. The dongle’s secure processor can send data to the computer, but not the other way around. This means the only input the security processor ever sees comes directly from the keyboard – which we assume to be trusted. Malware on the computer can’t talk to it at all. The unidirectional airgap is enforced by means of a “data diode”.
In the demo video you’ll see the message “abc” being signed. You type the message between F5
(start) and F6
(end). The signature gets appended directly after your message, prefixed with psig-
. This makes it easy to type directly into emails, chats, or whatever.
Example message:
Hi, hello world from punchsig! psig-1d70ddcfd35e35b78a5a4cbbf7844a7c405c1dac725c7bac48bd7093555cf7130e2a04d563aa0ace0b330c440601524d4c434ad3298ec02e862ef0750eee4c00
security #
How the sausage is made. Inside, this thing is made of two processors:
- The red side of things is connected to the keyboard, reads keystrokes, performs signing and forwards them to the blue board over a unidirectional serial link.
- The blue board just receives keystrokes over the serial link and forwards them to a PC. It emulates a USB HID keyboard.
This works differently from a YubiKey. With a YubiKey, the message to be signed comes from the computer — so malware could tamper with it before it’s signed. The user might notice the final message isn’t what they intended, but malware can still batch two signing requests: the real one and a sneaky extra on the side. While YubiKeys can require a user tap for confirmation, it’s easy for malware to fake an error and trick the user into tapping twice.
We go a bit further than the conventional wisdom of “keys are in hardware, they are inextractable”. Hardware dongles don’t live in a vacuum: they must get the input to sign from somewhere. In the majority of the cases, this means getting the input from a host computer. If this host computer is compromised, then malware can sign arbitrary messages. That’s bad. Even if malware can’t access key material, it can sign whatever they want. By forcing the
Are screens enough? One way of dealing with this is putting a screen on the signer. This provides “secure output”. The user is expected to verify what is on the screen vs a trusted reference. There are multiple sharp edges with this: a) how does the user know what a “trusted reference is? b) how is the user expected to be diligent and verify 128 bits (and not be lazy and verify “the few first and few last” bits)?
future #
The current implementation of punchsig is a prototype I built in a couple of hours – it does have rough edges and is not suitable for production. Directions for improvement:
- Implement proper key generation. Implement some kind of lightweight “console mode” to print public keys, generate new keys, etc
- Secure boot
- Firmware builds today are reproducibly by means of nix, but they lack documentation
- Implement forward-secure signatures. This would be nice to protect signatures against future compromise. Some scheme based on certs or Krawczyk’s trick would be relatively easy to implement.
- Implement an attestation CA for locally assembled punchsig
- Protect against replays. Today the user can type by themselves a timestamp. It would be great if this is better handled. One option is adding an RTC (but this adds components + a coin cell battery). A GPS module is another alternative.
- Improve reliability of the USB PIO stack. Not all keyboards enumerate yet.
hardware #
The two boards are based on Raspberry Pi Pico, connected like this.
code #
Firmware is pretty straighforward and largely taken from sample code. There is great code for the raspberry pi pico that implements USB HID host and client. There’s a very simple framing protocol that forwards the HID reports from one board to the other.
Source available at https://github.com/oreparaz/punchsig.
verification #
This is the javascript verification page I’ve been using for testing: https://www.reparaz.net/punchsig-verify. Some messages to try:
-
Yo, does this thing work? psig-f1424b7587150bb83ac8a895bb4f3424a6228b747083369638d5bfd7f24bd752f1fcbc3a140d431295ecdb163d224c608a0a7d633684a5cc23d1c1791821e30c
-
1, 2, 3, tango! psig-b6291b8c9724429822816e486cda12a690ba861ef7567769d4d24a9f42270941d40e9e4282ac0517bfce033c992a136603f1751ba8c77396a52e3e427fd6b206
-
ahem, aham, ahum psig-4ca4a688595e70b1907442c2541a2e11a51257344815acfaf7acde2eb437b06244dfb9b44939520a44a1436c77fc0f3800e4144d9e6a10d29ecd975cf2b4aa06
Parameters:
- All use the ed25519 testing public key
34bc5d83dd91bfa5df1ecada9630e3646fdb497afb4353d7d9f6ba2bb9ac41c0
. - All use the global context
punchsig v2025-05-18 context
. This is prepended to the message.
build #
Some pictures to inspire (or scare) you: the “case” is just a sandwich of styrofoam (terrible thermal properties (but the microcontrollers don’t get hot anyways), provide great physical durability).
There are just two boards that are embedded in the styrofoam:
Connected unidirectionally with 3 wires: