Air-gapped FROST threshold signing device https://privkeyio.github.io/keep-esp32/
  • C 66.1%
  • Rust 14.4%
  • Python 11.3%
  • Shell 5.2%
  • CMake 2.2%
  • Other 0.8%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Kyle 🐆 b00f7387f7
Add KFP v2 transport, announce proof and NIP-44 primitives to frost_tr (#180)
* Add KFP v2 transport, announce proof and NIP-44 primitives to frost_tr

* Randomize and verify proofs, bound NIP-44 memory and add the vector generator

* Refuse overlapping NIP-44 buffers and check the proof against the stored share

* State which overlaps seal and open refuse

* Move the KFP vector generator under test and stop tracking its lockfile
2026-10-08 10:18:35 -04:00
.github Sign with frost_tr and move the device to protocol 2 (#178) 2026-10-07 10:51:04 -04:00
components Add KFP v2 transport, announce proof and NIP-44 primitives to frost_tr (#180) 2026-10-08 10:18:35 -04:00
docs Sign under keep's BIP-32 child keys and tr() output keys (#179) 2026-10-08 02:10:49 -04:00
fuzz Sign with frost_tr and move the device to protocol 2 (#178) 2026-10-07 10:51:04 -04:00
main Sign under keep's BIP-32 child keys and tr() output keys (#179) 2026-10-08 02:10:49 -04:00
scripts Sign with frost_tr and move the device to protocol 2 (#178) 2026-10-07 10:51:04 -04:00
test Add KFP v2 transport, announce proof and NIP-44 primitives to frost_tr (#180) 2026-10-08 10:18:35 -04:00
.clang-format Add static analysis CI workflow (#111) 2026-01-18 17:00:36 -05:00
.dockerignore Sign with frost_tr and move the device to protocol 2 (#178) 2026-10-07 10:51:04 -04:00
.gitignore Sign with frost_tr and move the device to protocol 2 (#178) 2026-10-07 10:51:04 -04:00
CMakeLists.txt Rename firmware from frost-participant to keep 2026-01-06 19:37:16 -04:00
dependencies.lock Pin libnostr-c v0.2.2 and noscrypt v0.1.15 (#165) 2026-10-04 23:30:03 -04:00
Dockerfile.reproducible Add the frost_tr Rust component and check it at boot (#177) 2026-10-06 23:03:31 -04:00
Doxyfile Add Doxygen documentation for public APIs (#55) 2026-01-11 19:51:30 -05:00
Justfile Sign with frost_tr and move the device to protocol 2 (#178) 2026-10-07 10:51:04 -04:00
LICENSE Switch license from AGPL-3.0 to MIT (#139) 2026-03-04 21:30:55 -05:00
partitions.csv Add DKG checkpoint/resume (#123) 2026-01-19 20:39:35 -05:00
partitions.secureboot.csv Add ESP-IDF Secure Boot v2 support (#130) 2026-01-22 15:08:44 -05:00
README.md Sign with frost_tr and move the device to protocol 2 (#178) 2026-10-07 10:51:04 -04:00
REPRODUCIBILITY.md Add Justfile and Docker reproducible build (#132) 2026-01-22 15:27:00 -05:00
REUSE.toml Switch license from AGPL-3.0 to MIT (#139) 2026-03-04 21:30:55 -05:00
sdkconfig.defaults Guard taps on new screens and test the device UI end to end (#173) 2026-10-05 20:04:15 -04:00
sdkconfig.defaults.secureboot Add ESP-IDF Secure Boot v2 support (#130) 2026-01-22 15:08:44 -05:00
sdkconfig.defaults.ui-test Guard taps on new screens and test the device UI end to end (#173) 2026-10-05 20:04:15 -04:00
SECURITY.md Sign under keep's BIP-32 child keys and tr() output keys (#179) 2026-10-08 02:10:49 -04:00

keep-esp32

Air-gapped FROST threshold signing device for Keep.

About

keep-esp32 is an ESP32-S3 firmware that turns a devkit into an air-gapped hardware signer. It stores FROST threshold key shares, signs via USB serial JSON-RPC, and never exposes private keys. The device supports Bitcoin PSBT signing and Warden policy enforcement.

Features

  • FROST Threshold Signatures — FROST(secp256k1, Taproot) with the Zcash Foundation's frost-secp256k1-tr, the implementation keep uses
  • Bitcoin PSBT — Parse PSBTs and compute Taproot sighashes (BIP-174, BIP-341)
  • Policy Enforcement — Warden-signed policy bundles with Schnorr signature verification
  • Air-Gapped — No network, USB serial JSON-RPC only
  • Secure Storage — Direct partition-backed share storage (persists across firmware updates)
  • Multi-Group — Store up to 8 signing shares for different groups

Quick Start

Web Flasher (Easiest)

Flash firmware directly from your browser — no tools required:

Open Web Flasher

Requires Chrome or Edge.

Manual Flash

pip install esptool

Download the latest keep-merged.bin from Releases:

esptool.py --chip esp32s3 --port /dev/ttyACM0 write_flash 0x0 keep-merged.bin
cargo install --git https://github.com/privkeyio/keep keep-cli
keep frost hardware ping --device /dev/ttyACM0

Hardware

  • ESP32-S3 with USB Serial JTAG support
  • 8MB Flash, 8MB PSRAM recommended
  • Tested on ESP32-S3-DevKitC-1-N8R8

Development

scripts/build-frost-tr.sh --docker   # Rust FROST component, needs Docker
source ~/esp/esp-idf/export.sh
idf.py build
idf.py -p /dev/ttyACM0 flash monitor

Or with just:

just build
just flash-monitor
just test

See docs/USAGE.md for full CLI usage, JSON-RPC API reference, Bitcoin PSBT signing and policy enforcement.

Security

Air-gapped by design — no WiFi, no Bluetooth, no network stack. Communication is USB serial only. FROST shares are stored in a dedicated flash partition and persist across firmware updates. The device never holds a full private key. See docs/SECURITY.md for details.

Reproducible Builds

just docker-build
just verify-release v0.2.0

See docs/REPRODUCIBILITY.md for verification instructions.

License

MIT