82 lines
3.7 KiB
Markdown
82 lines
3.7 KiB
Markdown
# n_signer BLE Wearable Signer
|
|
|
|
**Status:** Concept — brainstorming. No plan yet.
|
|
|
|
A small, battery-powered wearable hardware signer that communicates with a host
|
|
over **Bluetooth Low Energy (BLE)**. The host sends JSON-RPC requests over a
|
|
BLE GATT characteristic; the signer shows an approval prompt on a tiny display;
|
|
the user taps a button to approve; the signed response goes back over BLE.
|
|
|
|
## Concept
|
|
|
|
```mermaid
|
|
flowchart LR
|
|
Host[Host: phone/laptop<br/>n_signer client] -->|BLE GATT| Signer[Wearable signer<br/>nRF52840 + OLED]
|
|
Signer -->|approve/deny button| User[User]
|
|
Signer -->|BLE GATT response| 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 BLE wire — even if BLE is sniffed, an attacker can't forge
|
|
requests without the caller's secp256k1 private key.
|
|
|
|
## Why BLE
|
|
|
|
- **Wearable form factor** — always with you (wristband, pendant, card)
|
|
- **No physical connection** — no USB cable, no host-side driver, no dongle
|
|
- **Universal host support** — phones, laptops, tablets all have BT
|
|
- **Low power** — nRF52840 draws ~5 mA active, ~1 µA sleep
|
|
|
|
## Hardware (preliminary)
|
|
|
|
| Component | Candidate | Notes |
|
|
|---|---|---|
|
|
| MCU | **nRF52840** (Nordic) | Cortex-M4 @ 64 MHz, 1 MB flash, 256 KB RAM, BT 5.0, hardware AES/ECC, USB device, NFC-A. ~$5-8. |
|
|
| Display | 0.96" or 1.3" SSD1306 OLED (I2C) or 1.02" e-paper | Small is fine — only shows "approve kind 1 from <caller>?" |
|
|
| Input | 2-3 tactile buttons (approve/deny/back) | No touch at this size |
|
|
| Power | 200 mAh coin cell or small LiPo | Weeks of battery life |
|
|
| Mnemonic entry | Buttons (scroll words), NFC from phone, or generate-on-device | The hard UX problem |
|
|
|
|
## Security considerations
|
|
|
|
- **BT stack attack surface:** BLE has a large stack (pairing, GATT, L2CAP, SMP).
|
|
A stack bug could allow code execution. Mitigations: use Nordic's audited
|
|
SoftDevice, disable unnecessary services, require LE Secure Connections pairing.
|
|
- **Radio range (~10 m):** an attacker in the same room could potentially
|
|
interact with the signer. The auth envelope + approval prompt protect against
|
|
this, but the radio is omnidirectional.
|
|
- **Pairing UX:** BT pairing can be frustrating. LE Secure Connections (Numeric
|
|
Comparison) is the most secure and user-friendly pairing method.
|
|
|
|
## Open questions
|
|
|
|
- **Mnemonic entry on a tiny screen:** scroll through 2048 BIP-39 words with
|
|
up/down buttons (like Coldcard)? Load via NFC from a phone? Generate on-device
|
|
and display for the user to write down?
|
|
- **PQ crypto on nRF52840:** 256 KB RAM is enough for ML-DSA-65 (~6 KB heap)
|
|
but SLH-DSA-128s is heavy. May need to limit the PQ algorithm set or stream
|
|
the keygen.
|
|
- **Display choice:** OLED (fast refresh, high power) vs e-paper (slow refresh,
|
|
zero power when static, persistent display).
|
|
- **Form factor:** wristband? pendant? card? What's the target use case —
|
|
daily signing, emergency key access, or a backup signer?
|
|
|
|
## Comparison to the IR air-gap signer
|
|
|
|
| | BLE wearable | IR air-gap |
|
|
|---|---|---|
|
|
| Air-gap | Medium (radio, ~10 m, omnidirectional) | High (light, line-of-sight, ~1 m) |
|
|
| Attack surface | Large (BT stack) | Small (no BT, dumb dongle) |
|
|
| Host compatibility | Universal (phones, laptops) | Requires USB dongle |
|
|
| Form factor | Wearable | Handheld (point at dongle) |
|
|
| Throughput | ~250 KB/s (BLE 5) | ~11 KB/s (raw IR) or ~400 KB/s (IrDA) |
|
|
| Novelty | Conventional | Novel (no hardware wallet uses IR) |
|
|
|
|
## Next steps
|
|
|
|
- Decide on the MCU (nRF52840 vs RP2040+BT-module)
|
|
- Decide on mnemonic entry method
|
|
- Decide on display (OLED vs e-paper)
|
|
- Write a port plan (similar to [`plans/teensy41_signer_port.md`](../../plans/teensy41_signer_port.md))
|