Skip to the content
nullroute

Signer profile

What an air-gapped signer should have to show you.

Air-gapped signers agree by convention on things no BIP writes down. The profile writes them down as requirements, each naming the check that decides it, and the conformance kit turns the testable ones into JSON vectors any signer can run.

State
Draft 0.1
Date
24 September 2026
Requirements
63 in 7 areas
Test cases
116 in 13 files
Adopted by
No one yet
Discussion
GitHub issues

Scope

Four questions a user cannot answer today.

  • Where did the seed come from?A rule for turning dice into a seed that anyone can repeat with coreutils, and the arithmetic for how many rolls are enough.
  • What will this signature authorise?What a signer must show before it signs, what counts as change, and which findings must disable signing until an explicit, single-use override.
  • Which software is asking for my passphrase?A number the user can recompute from source before entering a PIN, and what that number does and does not prove.
  • What hardware does the argument assume?Capabilities rather than models: a display only the signer drives, a way in that is not a network, and radios absent or with their drivers and firmware removed.

The kit

Expected values from outside the implementation.

None of these came from nullroute: review cases are PSBTs built and judged by Bitcoin Core, dice and manifests come from the BIP texts and coreutils, and the QR cases from reference encoders. Every file is pinned by a SHA256SUMS that coreutils can check.

Vector file and requirementsnullroute
bbqr-psbt
12 of 12
dice-accounting
25 of 25
dice-to-entropy
17 of 17
manifest-root
2 of 2
review-change
9 of 9
review-fee-and-amounts
7 of 7
review-input-amounts
7 of 7
review-ownership
5 of 5
review-sighash
13 of 13
review-timelocks
9 of 9
review-unknown-fields
2 of 2
sign-override
3 of 3
ur-psbt
5 of 5
116 cases in 13 files116 of 116

From this build’s make conformance. The second column is for your signer, and it stays empty until somebody runs the kit against one.

Coverage

Where nullroute meets it, and where it does not yet.

nullroute is held to the profile as one implementation among others, not as its reference. Most requirements are met; the rest wait on hardware or a manual procedure.

AreaRequirementsMetWith a caveatOpen
Entropy SP-ENT11911
Pre-signing review SP-REV211920
Signing SP-SIG1100
Attestation SP-ATT12921
Hardware SP-HW10244
Transport SP-TX7610
Dependencies SP-DEP1010

Not yet met without qualification

  • SP-ENT-8Met for sampling; screen copy manual
  • SP-ENT-11Manual
  • SP-REV-5Met in the headless render; unverified on the panel
  • SP-REV-21Met in tests; unverified on the panel
  • SP-ATT-1Met in tests; unverified on the panel
  • SP-ATT-10Met in tests; unverified on hardware
  • SP-ATT-12Manual
  • SP-HW-1Unverified until bring-up
  • SP-HW-2Met in the headless render; unverified on the panel
  • SP-HW-3Met against a software decoder; unverified with a camera
  • SP-HW-4Unverified until bring-up
  • SP-HW-5Unverified until bring-up
  • SP-HW-6Met in the image; unverified on the running device
  • SP-HW-8Met in the build; unverified on hardware
  • SP-HW-10Measured on Pi 4 per its spec
  • SP-TX-5Met for PSBT and transaction frames
  • SP-DEP-1Met for what nullroute implements; valid vectors outside that are asserted refused, each with its reason

Disagree

Positions others may reject.

A profile nobody has argued with is not yet worth adopting. These are the positions people who build signers and coordinators may reasonably dispute.

  • 100 rolls, not 99.Three signers accept 99, which is 255.911 bits. The profile asks for 100, and the cost is that a 99-roll seed from those devices cannot be reproduced here.
  • A segwit v0 input without its previous transaction blocks signing.Its amount is the coordinator’s word, and BIP-174 describes the attack that exploits it. The block can be lifted for one signature, never stored.
  • Schnorr signatures with aux_rand fixed to zero.BIP-340 notes that fresh randomness there increases protection against fault injection. The profile gives that up so anyone holding the seed can recompute every signature byte for byte.
  • Change is only what the signer can re-derive.Anything the PSBT merely claims is shown as a payment, with the claim reported.

If you build a signer or a coordinator, the most useful thing you can do is run the kit against it, or tell us which requirement is wrong. Open an issue.