Host rules
The host does most of the work. A device can be dishonest, so every rule that matters for the protection is enforced by the host. These are the main ones. The full rules are in the protocol BIP, under Host randomness, Attempts and failures, and step 5.
rho
- Draw a new
rhofor every attempt, and for every message and key within it, from a secure random source. Never derive it from something else. - Never log it, publish it, share it or write it to durable storage, during or after signing. Erase it when the attempt ends.
- Keep
R0_bytesin memory withrho. A restart ends the attempt. - Use a link that keeps
rhofrom third parties. Anyone who learnsrhocan recover the key from a backdoored device’s signature. QR codes and files don’t meet this on their own, and the drafts don’t define a transport that does.
The checks
Before sending rho, check that R0_bytes is a valid point and store it. After step 4, check, using only your own values and the stored R0_bytes:
R0_bytesparses as a point.t = hash(R0_bytes, rho)is belown.W = R0 + t * Gis not the point at infinity.- The signature’s
rmatchesW. - The signature verifies for your own
pkandm.
For ECDSA, also require low s, and check that the verification point equals W or -W. Use nothing the device sent other than the signature. Don’t forward R0_bytes.
Attempts
An attempt is one run of the protocol with one set of rho values. Before sending hc, record durably that an attempt is open for that device. That way a crash can’t hide a failure.
An attempt ends as completed, abandoned or failed. It is abandoned only if the user stops or changes the request before rho is sent, for a reason that has nothing to do with the device. Anything else that ends it unsuccessfully is a failure.
Counting failures
Timeouts, errors, refusals, malformed responses, a changed R0_bytes, failed checks and host restarts all count as failure events. Don’t try to tell a transport fault from a refusal, because a device can make one look like the other.
- Keep a durable failure count per device. Identify the device by the keys in your own wallet data, never by an identifier the device reports.
- Add one at the first failure event in an attempt, and at most once per attempt, in the same atomic write as the attempt’s state. A later success doesn’t undo it.
- An attempt still open at startup counts as failed.
- Reset the count only when the user asks, with a clear statement of what is being cleared.
Retries
Within an attempt you can retry a few times. Three retries each for steps 2 and 4 is the suggested default.
- You can repeat step 2 with the same
hc. IfR0_bytescomes back different, the attempt fails, because a second value is a second choice of nonce. - After a failure past step 2, repeat steps 3 and 4 with the same
rho, rather than starting a new attempt. A new attempt gives the device a fresh choice.
Warnings
If the count has gone up since the user last acknowledged a warning, warn the user before starting another attempt with that device. Say that an attempt failed and that repeated failures can mean a malicious device. Changing the message, reconnecting or restarting doesn’t clear this.
Don’t start a new attempt silently after a failure, and don’t change the fee or coins by yourself because of one, because an observer can see a changed transaction. If a device can’t do anti-exfil signing, don’t fall back to ordinary signing unless the user decides to, knowing they lose the protection.