dsisigner is a Nintendo DSi homebrew Bitcoin signing device. It is stateless, air-gapped, and communicates only through QR codes for PSBT signing workflows.
It is designed to look like an ordinary old handheld game. The root ROM is
currently named breakout.nds, the title is Breakout, and the app boots into a
playable Breakout-style game before signer mode is entered.
The goal is not to make a general-purpose hardware wallet. The goal is a verifiable, QR-only Bitcoin signer whose physical presence is less obvious in social and physical situations where a dedicated signing device can create risk.
The photos below show dsisigner running on real Nintendo DSi hardware. The QR data shown is dummy test data.
| Breakout decoy | Signer mode | QR-only output |
This is experimental pre-release software. Treat it as code for review and controlled testing unless you have independently reviewed the source, build process, and exact ROM artifact you plan to run.
- It handles Bitcoin seed material, passphrases, private keys, PSBTs, and signatures. Mistakes can lose funds.
- It is stateless by design. Seeds, passphrases, private keys, and PSBT signing secrets must not be written to SD, NAND, logs, screenshots, or settings.
- Communication is QR-only. WiFi, Bluetooth, sockets, HTTP clients, and other network paths are out of scope.
- DEBUG builds can write SD debug logs. Do not use DEBUG builds for production signing.
- Test with small amounts first, and verify every release artifact before use.
Do not trust the maintainer, a binary download, or a GitHub account by default. Trust should come from source review, local build checks, release signatures when available, and independent verification.
- Common second-hand hardware that does not obviously signal Bitcoin custody.
- Built-in cameras for QR scanning.
- Two screens and a touch panel for transaction review and input.
- Memory Pit boot flow works without permanent console modification.
- BlocksDS makes native DSi homebrew development practical.
- No need for a custom hardware supply chain.
For the full background, threat model, and hardware rationale, see docs/project-context.md.
Implemented or code-supported features include:
- BIP-39 mnemonic entry, generation, validation, and passphrase support
- SeedQR, CompactSeedQR, and plaintext mnemonic QR input
- Dice, camera entropy, coin flip, and final-word seed creation helpers
- BIP-32 derivation with BIP-44, BIP-49, BIP-84, BIP-86, and BIP-48 account support
- xpub, descriptor, account, and address QR display
- Address verification from scanned addresses
- PSBT v0 parsing, review, validation, and signing
- P2WPKH, P2WSH multisig, and P2TR key-path signing
- Change output verification with optional wallet descriptor import
- BC-UR, BBQR, Specter QR, and crypto-account decode paths
- Panic wipe and inactivity timeout wipe
Not supported:
- P2TR script-path signing
- MuSig or other multi-party signing protocols
- Networking
- Permanent secret storage
- DS-mode fallback
On real hardware, dsisigner is normally launched through the DSi Camera app using
the Memory Pit exploit. The ROM then starts as Breakout.
Signer mode is entered only from the Breakout Game Over or All Clear screen
by pressing this command one button at a time:
Up, Up, Down, Down, Left, Right, Left, Right, B, A, Start
See docs/boot-guide.md for the full real-hardware setup.
Prerequisites:
- Docker with Docker Compose V2
- Git submodules initialized
git submodule update --init --recursive
docker compose run --rm build make DEBUG=1
./tools/build.sh testdocker compose run --rm build make DEBUG=1 is the normal development build.
The helper script ./tools/build.sh build does not add DEBUG=1.
For a non-debug package:
./tools/build.sh clean
./tools/build.sh setup-pit nofacebook # or: facebook
./tools/build.sh packageThe package output is:
output/sd/
|-- boot.nds
`-- private/
`-- ds/
`-- app/
`-- 484E494A/
`-- pit.bin
If you previously built with DEBUG=1, clean first or use a fresh checkout so
stale debug objects cannot be reused in a release-style package.
- Release process and artifact expectations: docs/release.md
- Source checkout, submodule, build, and ROM hash checks: docs/verification.md
- Real hardware boot steps: docs/boot-guide.md
- Changelog: CHANGELOG.md
Signed release images and artifact attestations are planned but not yet available. Until they exist, SHA256 values are integrity checks, not maintainer identity proof.
- Contribution guide: CONTRIBUTING.md
- Vulnerability reporting: SECURITY.md
- Third-party license notices: THIRD_PARTY_NOTICES.md
- Project license: LICENSE
Security reports should use GitHub private vulnerability reporting. Do not include mnemonics, passphrases, xprvs, private keys, or sensitive PSBTs in public issues.
dsisigner is inspired by SeedSigner's stateless, air-gapped signing model and by the broader Bitcoin self-custody and homebrew communities. Development also used assistance from OpenAI Codex (GPT-5.5); released code and project decisions remain the maintainers' responsibility.