A Bitcoin cold-storage HD wallet that runs on a Nintendo DS / DS Lite. Air-gapped by construction (no WiFi, no USB, no network stack anywhere in the code path). Generates seeds, derives addresses, displays receive QR codes, and signs PSBTs.
Status: Phase 0 (foundation only). This release ships the cryptographic substrate every later phase relies on — SHA-256, SHA-512, RIPEMD-160, HMAC-SHA256, HMAC-SHA512, PBKDF2-HMAC-SHA512 — all gated through an on-device self-test ROM that verifies them against published RFC / NIST / BIP test vectors. The wallet itself does not exist yet. Don't try to put coins on this.
See DESIGN.md for the full architecture and phase plan
(threat model, derivation paths, PSBT round-trip, encrypted SRAM seed,
PIN flow, etc.).
A $20 used DS Lite plus a $15 flashcart makes a cryptographically reasonable, fully air-gapped cold wallet. The hardware is mature, the form factor (dual screen + buttons + clamshell) suits the workflow, it boots in two seconds, the battery lasts ten hours, and nothing about it phones home.
For the full threat model see DESIGN.md. Short version:
this lands somewhere between a paper wallet (worse hardware) and a
purpose-built hardware wallet with a secure element (better physical
hardening). Roughly comparable to running Electrum on an air-gapped
laptop, but on a $35 device that looks like a toy.
This is the Phase 0 self-test ROM. Drop it on your flashcart, boot it, and it runs the foundation crypto layer against known-answer vectors. Verifies:
| Algorithm | Vector source |
|---|---|
| SHA-256 | NIST FIPS 180-4 §B.1 ("abc") |
| SHA-512 | NIST FIPS 180-4 §C.1 ("abc") |
| RIPEMD-160 | Bosselaers/Preneel reference ("abc") |
| HMAC-SHA256 | RFC 4231 §4.2 test case 1 |
| HMAC-SHA512 | RFC 4231 §4.2 test case 1 |
| PBKDF2-HMAC-SHA512 | BIP-39 Trezor reference vector #1 (2048 iterations) |
The PBKDF2 vector is the gate that matters most — it's the BIP-39 mnemonic-to-seed function, and a passing result here proves the foundation is ready for the BIP-32 master node derivation that arrives in Phase 1.
The top screen shows what's being tested; the bottom screen prints a
PASS/FAIL line per algorithm and a final result: N/M PASS.
| Phase | Scope | Status |
|---|---|---|
| 0 | Crypto foundation + self-test ROM | This release |
| 1 | BIP-39 wordlist, BIP-32 derivation, secp256k1, address display | pending |
| 2 | Software QR generator, receive flow on bottom screen | pending |
| 3 | PSBT parser, ECDSA signing, multi-frame QR ingest/output | pending |
| 4 | Encrypted SRAM seed, PIN entry, mnemonic confirmation flow | pending |
| 5 | Constant-time hardening, packaging, brick-resist tests | pending |
Each phase is its own commit + tag. Phase 0 is v0.1.0-phase0.
Pre-built nds-wallet.nds (Phase 0 self-test ROM) is checked into the
repo root and attached to the v0.1.0-phase0 release.
- DSi / 3DS: drop on SD card, launch via TWiLight Menu++
- Original DS / DS Lite: copy to a DLDI-patched flashcart (R4, EZ-Flash, etc.)
- Emulators: melonDS, DeSmuME, no$gba
Two layers, matching the family convention:
-
Boot self-test on hardware — the ROM itself is the self-test; running it prints PASS/FAIL per algorithm on the bottom screen.
-
Host KAT harness in
tests/— identical vectors, compiled with native gcc against the samesource/sha256.c,sha512.c,ripemd160.c,hmac.c,pbkdf2.cthat go into the .nds. Returns exit 1 on any failure.cd tests && make check
CI runs both layers on every push.
Requires devkitPro's nds-dev meta-package (devkitARM + libnds).
make # builds nds-wallet.nds
make clean
Windows convenience:
.\build.bat
DESIGN.md full architecture / threat model / phase plan
source/
main.c dual-screen self-test driver
sha256.c sha512.c vendored from hash-bench-nds (verbatim)
ripemd160.c
hmac.c generic HMAC over any one-shot hash function
pbkdf2.c PBKDF2-HMAC-SHA512 (parameterized iterations)
include/ hashes.h, hmac.h, pbkdf2.h
tests/ host-runnable KAT harness
.github/workflows/ CI
Makefile devkitARM + libnds Makefile
build.bat Windows convenience wrapper
nds-wallet.nds prebuilt Phase 0 ROM (committed)
Phase 0 closes when the self-test ROM passes on real hardware and CI is green on the published commit. The DESIGN.md "Open questions for the next session" block is the formal hand-off note for Phase 1.
Released under the MIT License.