Releases: InKasWeRust/KasSigner
KasSigner v1.0.3 (esp32-s3: M5Stack Lite, Waveshare Touch LCD2)
KasSigner v1.0.3
Reproducible Build Hashes
App-only images (firmware verification, developer builds):
Waveshare: 8cf7087123d046df86658201cc326d10ef00466ba3fd23b1903d9243931fd8cb
M5Stack: 0bea58b92d6a9bbd715ff4efc25efd1e0d0e225da363b15e73d4c018bdce341d
Full-flash images (bootloader + partition table + app — ready to flash):
Waveshare: 5583dec5f9c2d848d1b25d28a3897c2a22a1e3c7ae2fa0a1fa0edebb25d9914d
M5Stack: 1b8ccfa84759d427a64bc4f02bd695bda7d8736404bb86256d2d35fec374e397
Anyone can reproduce all four hashes:
git clone https://github.com/InKasWeRust/KasSigner.git && cd KasSigner
git checkout v1.0.3
docker build --platform linux/amd64 -f Dockerfile.base -t kassigner-toolchain:v2 .
docker build --platform linux/amd64 -t kassigner-build .
docker run --rm kassigner-buildThe developer's Schnorr signature lives inside the binary but does not change the build hash. The device verifies it at boot against DEV_PUBKEY in the source code. The signing key is held offline.
Verify Code Segments
To confirm a downloaded .bin runs the same code as your own build:
cargo run --manifest-path tools/Cargo.toml --bin kassigner-verify -- downloaded.bin my-docker-build.binIf the code segments match, both binaries execute identical instructions.
Flashing Pre-built Binaries
Option A — Full-flash image (recommended for new users)
No Rust toolchain needed. Download kassigner-waveshare-full.bin or kassigner-m5stack-full.bin from the assets below. Install esptool and flash:
pip3 install esptool
# Waveshare
python3 -m esptool --port <waveshare-port> --baud 460800 write_flash 0x0 kassigner-waveshare-full.bin
# M5Stack
python3 -m esptool --port <m5stack-port> --baud 460800 write_flash 0x0 kassigner-m5stack-full.binThe full-flash images include the ESP-IDF bootloader, partition table (16MB flash, ~15.6MB app partition), and the signed firmware — everything needed to boot from a blank chip.
Option B — App-only image (for developers)
If you already have a bootloader and partition table on the device (from a previous cargo run source build), you can flash just the app image at offset 0x10000:
# Waveshare
python3 -m esptool --port <waveshare-port> --baud 460800 write_flash 0x10000 kassigner-waveshare.bin
# M5Stack
python3 -m esptool --port <m5stack-port> --baud 460800 write_flash 0x10000 kassigner-m5stack.binReplace the port with your device's serial port (ls /dev/cu.usb* on macOS, ls /dev/ttyACM* /dev/ttyUSB* on Linux). Requires esptool (pip install esptool).
What's New
Firmware
- ReviewTx page rendering fix — tapping to advance TX review pages now correctly triggers a screen redraw (previously pages stayed stuck on the summary)
- TX parse error screen — when a scanned transaction exceeds
MAX_INPUTS(8), the signer now shows "Too many UTXOs / Consolidate first" with an error beep; tap to dismiss and return to main menu (previously failed silently) - TX-too-large pre-check — the signing step's size estimator now shows "Too many inputs! / Consolidate UTXOs first" with an error beep and tap-to-dismiss (previously the message was overwritten immediately)
draw_tx_error_screen()— new two-line error display method with "Tap to continue" hint and back button
KasSee Web
- Address reuse prevention — funded addresses show an orange "funded" badge, session-tracked spent addresses show a gray "used" badge;
showReceiveauto-skips funded and used addresses to present the first clean address - Explorer links — every address in the address list and verify screen has a ↗ link to the Kaspa block explorer
- Address history toggle — optional detection of historically used addresses via a self-hosted kaspa-rest-server (off by default; public APIs do not support this)
- UTXO consolidation with selection — UTXO screen now shows selectable checkboxes (max 8 per batch); "Consolidate N Selected" button builds a transaction merging only the chosen UTXOs into one output
- Send UTXO selection limit — manual UTXO selection for sends now enforces a max-8 limit matching the signer's
MAX_INPUTS - KRC-20 / KRC-721 display cleanup — removed token icons and NFT thumbnails (which caused CSP violations via inline
onerrorhandlers and 404s for missing PNGs); tokens now show name + balance only - KNS domains — reverse lookup from a hardcoded table; matching domains displayed in the Tokens screen under a "KNS Domains" section
- QR cycle pause fix — stale
setIntervaltimer cleared at the start ofdisplayKsptQr, preventing overlapping intervals that made the pause button ineffective - CSP update —
connect-src https:added to support user-provided custom REST server URLs
Code Quality
- Clippy zero warnings for both bootloader and KasSee WASM
Full changelog: CHANGELOG.md
KasSee Web: kassigner.org
KasSigner v1.0.2 (esp32-s3: M5stack Lite, WaveShare touch LCD2)
KasSigner v1.0.2
Reproducible Build Hashes
App-only images (firmware verification, developer builds):
Waveshare: ed14db9360e9ac939b363348184e681deffc956197948e40b783738ea3a1c4bb
M5Stack: 922b91ec0b411e7bbf8a2dfaca49b4848db2b0ecb653b6ed639cac7a48083eb4
Full-flash images (bootloader + partition table + app — ready to flash):
Waveshare: ffa6a9efc8343f49f0a91d17a2e63155ae103099f68a90b2ff69ec1d42e90254
M5Stack: a543f500311fb569fc6396af2712dd67f47f4cf1171dccf9df903ad6bc8a34bc
Anyone can reproduce all four hashes:
git clone https://github.com/InKasWeRust/KasSigner.git && cd KasSigner
git checkout v1.0.2
docker build --platform linux/amd64 -f Dockerfile.base -t kassigner-toolchain:v2 .
docker build --platform linux/amd64 -t kassigner-build .
docker run --rm kassigner-buildThe developer's Schnorr signature lives inside the binary but does not change the build hash. The device verifies it at boot against
DEV_PUBKEYin the source code. The signing key is held offline.
Verify Code Segments
To confirm a downloaded .bin runs the same code as your own build:
cargo run --manifest-path tools/Cargo.toml --bin kassigner-verify -- downloaded.bin my-docker-build.binIf the code segments match, both binaries execute identical instructions.
Flashing Pre-built Binaries
Option A — Full-flash image (recommended for new users)
No Rust toolchain needed. Download kassigner-waveshare-full.bin or kassigner-m5stack-full.bin from the assets below. Install esptool and flash:
pip install esptool
# Waveshare
python3 -m esptool --port <waveshare-port> --baud 460800 write_flash 0x0 kassigner-waveshare-full.bin
# M5Stack
python3 -m esptool --port <m5stack-port> --baud 460800 write_flash 0x0 kassigner-m5stack-full.binThe full-flash images include the ESP-IDF bootloader, partition table (16MB flash, ~15.6MB app partition), and the signed firmware — everything needed to boot from a blank chip.
Option B — App-only image (for developers)
If you already have a bootloader and partition table on the device (from a previous cargo run source build), you can flash just the app image at offset 0x10000:
# Waveshare
python3 -m esptool --port <waveshare-port> --baud 460800 write_flash 0x10000 kassigner-waveshare.bin
# M5Stack
python3 -m esptool --port <m5stack-port> --baud 460800 write_flash 0x10000 kassigner-m5stack.binReplace the port with your device's serial port (
ls /dev/cu.usb*on macOS,ls /dev/ttyACM* /dev/ttyUSB*on Linux). Requiresesptool(pip install esptool).
What's New
- Full-flash images — merged
.binfiles (bootloader + partition table + app) that flash at0x0with a single command. No toolchain required. - kassigner-verify — new tool to compare code segments between signed and unsigned builds
- gen_hash.rs —
FIRMWARE_SIGNEDalwaystrueso signed/unsigned builds produce identical code segments
Camera Pipeline
- cam_dma — new DMA-based 480×480 YUV422 capture for Waveshare, replacing DvpCamera
- OV2640 runtime auto-detect — Waveshare probes sensor ID at boot; OV2640 wide-angle supported alongside OV5640
- CST816D touch sensitivity — threshold tuned to reject ghost touches from ambient light/EMI
QR Decoder
- rqrr no_std fork — replaced custom per-platform decoders with
rqrr_nostd, a no_std zero-dependency fork of rqrr 0.10.1 - V1–V40, all ECC levels, full Reed-Solomon error correction
- Single-pass accept — no voting or multi-pass heuristics needed
- Unified
rqrr_decode()for both platforms
Features
- kpub multi-frame QR export — choose 2/3/4 frames, auto-cycle or manual, save/import to SD
- Signed QR frame size choice — single vs multi-frame signed KSPT export
- Multisig address SD save — with optional encryption
- SD overwrite confirmation — prompts before overwriting existing files
- Account-level PSKT signing fallback — tries account xonly pubkey when address key doesn't match
- Multi-frame QR buffers expanded — 2KB→5KB, 8→20 slots for larger payloads
KasSee Web
- Donate card rebuilt with inline styles
- Broadcast → Donate flow after successful TX
- UTXO selection: sort in place, sweep takes top 5 by size
Code Quality
- Clippy zero warnings (
clippy::all) for both bootloader and KasSee WASM - 36 documented pedantic-tier
#[allow]directives for embedded patterns - Removed dead code and orphaned zero-width text stego constants
Infrastructure
- Version strings removed from filenames, titles, and docs — splash screen reads version dynamically from
CURRENT_VERSION - Docker tags use
:latest/:verifyinstead of versioned tags - PDF guides updated: User Guide (43p), Quick Start Guide (5p), KasSee Guide (8p)
rqrr_nostd/crate added to repository
Full changelog: CHANGELOG.md
KasSee Web: kassigner.org
KasSigner v1.0.1 — P2SH Multisig & KasSee Web
KasSigner v1.0.1
Air-gapped offline signing device for the Kaspa blockchain. ~45,000 lines of bare-metal no_std Rust on ESP32-S3.
Highlights
- P2SH multisig — first air-gapped multisig on Kaspa mainnet
- KasSee Web — browser-based watch-only companion wallet (Pure Rust → WASM), deployed at inkaswerust.github.io/KasSigner
- Critical signing fixes — sighash keyed Blake2b, BIP-340 tagged Schnorr challenge, change address chain search
- Docker toolchain v2 — Rust 1.85.0, espup 0.16.0, espflash 3.3.0
- One-step installer — macOS script: scan, install toolchain, build from source, flash
- Secure Boot V2 verified on eFuse hardware
Reproducible Build Hashes
Built from tag v1.0.1 using docker build --no-cache.
| Target | SHA-256 | Size |
|---|---|---|
| Waveshare | e453cbcb3af913284fd3ff68952640b00125b902abfe5af32862645fb8209ab1 |
818 KB |
| M5Stack | d0390ca473a8afb07a069e0a3e122b154f4acdd8f36519c8ec5d4b4aecf98fd9 |
831 KB |
# Verify yourself
docker build --platform linux/amd64 -f Dockerfile.base -t kassigner-toolchain:v2 .
docker build --platform linux/amd64 -t kassigner-build:v1.0.1 .
docker run --rm kassigner-build:v1.0.1Verified on Mainnet
| TX ID | Type |
|---|---|
8a6652fb... |
First P2SH multisig funding |
d1ffdb9f... |
First P2SH multisig spend (direct device-to-device) |
2b53e35a... |
Second funding (sorted keys verified) |
2b718bd5... |
Second P2SH spend (via KasSee relay) |
2faa58b2... |
First air-gapped broadcast (P2PK) |
277517da... |
Multi-UTXO across receive + change chains |
What's New — Device Firmware
Added
- P2SH script detection, redeem script field, v2 KSPT serializer/parser
- ShowQR signature status overlay — "PARTIAL 1/2" (orange) / "FULLY SIGNED 2/2" (teal)
- Multi-frame v2 KSPT detection in camera
- BIP85 auto-load + success sound
- SD backup delete with hold-to-confirm (4s)
- SD file list fingerprint matching ("Seed #1", "Seed #2")
- SD progress bars on decrypt and xprv import
- Pre-signing size check: rejects TX exceeding 5 inputs with warning
- One-step macOS installer (
KasSigner_Install_v1_0_1.sh)
Fixed
- Sighash: all sub-hashes now use keyed Blake2b-256 with
TransactionSigningHashdomain key - Output hash: added
script_len(u64 LE) prefix before script bytes - Schnorr challenge: switched to BIP-340 tagged hash
- Change address signing: searches both receive and change chains
- MAX_SCRIPT_SIZE bumped to 170 bytes (supports 5-of-5 multisig)
- QR frame payload reduced to 53 bytes for reliable device-to-device scanning
- Stego export loop fix, SD read screen labels, multisig slot label overlap
What's New — KasSee Web
Browser-based watch-only companion wallet. Pure Rust compiled to WASM.
- Import kpub via QR scan or paste
- Derive receive and change addresses, track UTXOs and balance
- Build unsigned KSPT transactions with fee estimation
- Send Max (sweep all UTXOs)
- Broadcast signed transactions
- P2SH multisig address creation and spend
- UTXO explorer with manual selection
- Address verification with QR + derivation path
- PWA installable on mobile
- Custom node connection (WebSocket)
Build Environment
| Component | Version |
|---|---|
| Docker base | kassigner-toolchain:v2 |
| Host Rust | 1.85.0 |
| espup | 0.16.0 |
| espflash | 3.3.0 |
| Base OS | Ubuntu 24.04 (x86_64) |
Security Layers
| Layer | Verified by |
|---|---|
| RSA-3072 Secure Boot | ESP32-S3 ROM (eFuse devices) |
| SHA-256 firmware hash | KasSigner app (every boot) |
| Schnorr signature | KasSigner app (production builds) |
| Docker reproducibility | Anyone (docker build --no-cache) |
Full Changelog
See CHANGELOG.md for the complete list of changes.
KasSigner v1.0 — First Air-Gapped Signing Device for Kaspa
KasSigner v1.0
Air-gapped offline signing device for the Kaspa blockchain. ~45,000 lines of bare-metal no_std Rust on ESP32-S3.
Highlights
- P2SH multisig — first air-gapped multisig on Kaspa mainnet
- KasSee companion wallet — watch-only CLI for kpub import, UTXO tracking, transaction building, and multisig coordination
- Two hardware targets — Waveshare ESP32-S3-Touch-LCD-2 and M5Stack CoreS3
- Docker reproducible builds with hash convergence
- Secure Boot V2 verified on eFuse hardware
Reproducible Build Hashes
Built from tag v1.0 using docker build --no-cache .
| Target | SHA-256 | Size |
|---|---|---|
| Waveshare | 36d638fc2c68f44a73118e86eecf45be5d780765c644688c6577a75780bbbde3 |
806 KB |
| M5Stack | 037cdeddfbc46f91df0405578eced2ba6c24b441e5b5e954a5ff0d0c0fd69f8d |
819 KB |
Verified on Mainnet
| TX ID | Type |
|---|---|
8a6652fb... |
First P2SH multisig funding |
d1ffdb9f... |
First P2SH multisig spend (direct device-to-device) |
2b53e35a... |
Second funding (sorted keys verified) |
2b718bd5... |
Second spend (via KasSee relay) |
Build from Source
See docs/BUILD_FLASH_GUIDE.md for complete instructions.
Docker reproducible build: docker build -t kassigner-build:v1.0 .
KasSee companion: cd kassee && cargo install --path .