150 lines
7.2 KiB
Markdown
150 lines
7.2 KiB
Markdown
# n_signer IR Air-Gap Signer
|
|
|
|
**Status:** Concept — brainstorming. No plan yet.
|
|
|
|
A hardware signer that communicates with the host via **infrared light** —
|
|
line-of-sight, short-range, physically directional. The signer never touches
|
|
the host electrically: no wire, no radio, no shared ground. The only channel
|
|
is modulated light through air. A small **USB receiver dongle** on the host
|
|
decodes the IR signal and presents it as a CDC-ACM serial port.
|
|
|
|
This is the strongest air-gap model in the n_signer family: the signer is
|
|
electrically isolated from the host, and the receiver dongle is a dumb
|
|
IR-to-serial bridge with no crypto, no keys, and ~200 lines of auditable
|
|
firmware.
|
|
|
|
## Concept
|
|
|
|
```mermaid
|
|
flowchart LR
|
|
Host[Host: laptop<br/>n_signer client] -->|USB CDC| Dongle[USB IR receiver dongle<br/>RP2040 + IR receiver]
|
|
Dongle -->|IR light<br/>line-of-sight| Signer[IR signer<br/>RP2040 + OLED + buttons]
|
|
Signer -->|approve/deny button| User[User]
|
|
Signer -->|IR light response| Dongle
|
|
Dongle -->|USB CDC| Host
|
|
```
|
|
|
|
The signer speaks the same algorithm-based API as the host and the CYD/Teensy
|
|
firmware ([`README.md`](../../README.md) §4). The auth envelope (kind 27235)
|
|
protects the IR wire. The receiver dongle is a transparent byte pipe — it has
|
|
no knowledge of the protocol, no keys, and no state beyond the IR-to-USB
|
|
bridge.
|
|
|
|
## Why IR
|
|
|
|
- **True air-gap** — the signer is electrically isolated from the host. No wire,
|
|
no radio, no shared ground. Host-side malware cannot reach the signer's
|
|
firmware through the communication channel.
|
|
- **Line-of-sight required** — you point the signer at the receiver. An attacker
|
|
would need to be in the same room, in the line of sight, with their own IR
|
|
transmitter. Much smaller attack surface than BT (which broadcasts
|
|
omnidirectionally to ~10 m).
|
|
- **Dumb dongle** — the USB receiver is a simple IR-to-serial bridge. ~200
|
|
lines of firmware, no crypto, no keys, fully auditable in an afternoon. If
|
|
compromised, it can only MITM the IR stream (which is already protected by the
|
|
auth envelope).
|
|
- **No BT stack** — much smaller firmware attack surface on the signer. No
|
|
pairing, no GATT, no L2CAP, no SMP.
|
|
- **Novel** — no hardware wallet uses IR for host communication. It's a
|
|
creative solution to the air-gap problem that avoids both the wire (USB) and
|
|
the radio (BT/NFC) attack surfaces.
|
|
|
|
## Hardware (preliminary)
|
|
|
|
### Signer
|
|
|
|
| Component | Candidate | Notes |
|
|
|---|---|---|
|
|
| MCU | **RP2040** (Raspberry Pi Pico) | $4, Cortex-M0+ @ 133 MHz, 264 KB SRAM, no WiFi/BT (perfect for air-gap). Enough RAM for secp256k1 + ed25519. ML-DSA-65 fits (~6 KB heap). |
|
|
| | or **nRF52840** | If you want NFC for mnemonic loading + lower power. |
|
|
| IR transceiver | **38 kHz IR LED + TSOP38238** (raw async, 115200 baud, ~$1) | Simplest. ~11 KB/s. Fine for Nostr events (~500 bytes). Slow for PQ sigs (3-8 KB → 0.3-0.7 s). |
|
|
| | or **TFBS4711 IrDA module** (~$2, up to 4 Mbps) | Faster (~400 KB/s) but harder to source + more complex protocol. |
|
|
| Display | 0.96" SSD1306 OLED (I2C, ~$2) or 1.54" e-paper | Small is fine — shows "approve kind 1 from <caller>?" |
|
|
| Input | 2-3 tactile buttons (approve/deny/back) | |
|
|
| Power | Coin cell or small LiPo | RP2040 + OLED + IR = very low power |
|
|
|
|
### USB receiver dongle
|
|
|
|
| Component | Candidate | Notes |
|
|
|---|---|---|
|
|
| MCU | **RP2040** (Pico) or **ATmega32U4** (Arduino Micro) | $4-8. Native USB device. |
|
|
| IR receiver | Matching TSOP38238 or IrDA module | Must match the signer's IR modulation. |
|
|
| USB | Native USB CDC-ACM | Presents as `/dev/ttyACM0` to the host. |
|
|
| Firmware | ~200 lines | Read IR → write USB CDC; read USB CDC → transmit IR. A dumb pipe. No crypto, no keys, no state. |
|
|
|
|
## Throughput
|
|
|
|
| IR mode | Baud | Throughput | sign_event (500 B req + 600 B resp) | ML-DSA-65 sign (3.3 KB sig) |
|
|
|---|---|---|---|---|
|
|
| Raw 38 kHz async | 115200 | ~11 KB/s | ~100 ms | ~300 ms |
|
|
| Raw 38 kHz async | 230400 | ~23 KB/s | ~50 ms | ~150 ms |
|
|
| IrDA | 4 Mbps | ~400 KB/s | ~3 ms | ~8 ms |
|
|
|
|
**Recommendation:** start with raw 38 kHz IR at 115200 baud (simplest, cheapest,
|
|
works with any IR LED + TSOP receiver). Upgrade to 230400 or IrDA if PQ
|
|
signature throughput is a bottleneck.
|
|
|
|
## Protocol
|
|
|
|
The IR link is **half-duplex** — the signer and receiver take turns
|
|
transmitting. The protocol is simple:
|
|
|
|
1. Host sends JSON-RPC request → USB CDC → dongle transmits IR.
|
|
2. Signer receives IR, parses the request, shows approval prompt.
|
|
3. User approves/denies.
|
|
4. Signer transmits IR response → dongle → USB CDC → host.
|
|
|
|
The 4-byte big-endian length-prefix framing (same as the CYD/feather) works
|
|
over IR as-is. The auth envelope protects against MITM on the IR stream.
|
|
|
|
## Security model
|
|
|
|
- **Electrical isolation:** the signer has no electrical connection to the host.
|
|
The IR link is a one-way-at-a-time optical channel.
|
|
- **Line-of-sight:** an attacker must be in the same room, in the line of sight,
|
|
with their own IR transmitter. The auth envelope + approval prompt protect
|
|
against a MITM even if the attacker intercepts the IR stream.
|
|
- **Dumb dongle:** the USB receiver has no crypto, no keys, no protocol
|
|
knowledge. It's a byte pipe. If compromised, it can only MITM the IR stream
|
|
(already protected by the auth envelope). The dongle's firmware is small
|
|
enough to audit in an afternoon.
|
|
- **No radio:** no BT, no WiFi, no NFC (unless you add NFC for mnemonic loading).
|
|
The signer emits no RF — only modulated IR light when actively transmitting.
|
|
|
|
## Open questions
|
|
|
|
- **IR modulation:** raw 38 kHz async (simplest) vs IrDA (faster, more complex)?
|
|
- **Mnemonic entry:** buttons (scroll BIP-39 words) vs NFC from phone vs
|
|
generate-on-device? On a 0.96" OLED, scrolling 2048 words is tedious but
|
|
secure.
|
|
- **PQ crypto on RP2040:** 264 KB SRAM is enough for ML-DSA-65 but SLH-DSA-128s
|
|
is tight. May need to limit the PQ algorithm set.
|
|
- **Dongle design:** separate RP2040 Pico, or integrate the IR receiver into a
|
|
custom PCB with a USB-A plug for a compact dongle?
|
|
- **Range:** raw IR with an IR LED + TSOP38238 reaches ~1-2 m line-of-sight.
|
|
Enough for "point at the dongle on your desk" but not across a room.
|
|
- **Bidirectional IR:** the signer needs both an IR LED (transmit) and a TSOP
|
|
receiver (receive). Two modules, or an IrDA transceiver module that does both?
|
|
|
|
## Comparison to the BLE wearable signer
|
|
|
|
| | IR air-gap | BLE wearable |
|
|
|---|---|---|
|
|
| Air-gap | **High (light, line-of-sight, ~1 m)** | Medium (radio, ~10 m, omnidirectional) |
|
|
| Attack surface | **Small (no BT, dumb dongle)** | Large (BT stack) |
|
|
| Host compatibility | Requires USB dongle | Universal (phones, laptops) |
|
|
| Form factor | Handheld (point at dongle) | Wearable |
|
|
| Throughput | ~11 KB/s (raw IR) or ~400 KB/s (IrDA) | ~250 KB/s (BLE 5) |
|
|
| Novelty | **Novel (no hardware wallet uses IR)** | Conventional |
|
|
| Cost | ~$10 signer + ~$8 dongle | ~$10-15 (nRF52840 + OLED) |
|
|
|
|
## Next steps
|
|
|
|
- Decide on IR modulation (raw 38 kHz vs IrDA)
|
|
- Decide on MCU (RP2040 vs nRF52840)
|
|
- Decide on mnemonic entry method
|
|
- Decide on display (OLED vs e-paper)
|
|
- Prototype the IR link: two RP2040 Picos + IR LEDs + TSOP38238, bidirectional
|
|
byte pipe at 115200 baud
|
|
- Write a port plan (similar to [`plans/teensy41_signer_port.md`](../../plans/teensy41_signer_port.md))
|