Skip to content

BIP 353: Add a Security Considerations section - #2272

Closed
bitsagarob wants to merge 1 commit into
bitcoin:masterfrom
bitsagarob:2026-09-bip353-security-considerations
Closed

BIP 353: Add a Security Considerations section#2272
bitsagarob wants to merge 1 commit into
bitcoin:masterfrom
bitsagarob:2026-09-bip353-security-considerations

Conversation

@bitsagarob

@bitsagarob bitsagarob commented Sep 2, 2026

Copy link
Copy Markdown

BIP 353 has no Security Considerations section. This PR adds one covering four properties that are implied by the existing text but never stated, each of which an implementer can and does get wrong while conforming to every explicit MUST in the document.

  1. The validated record is the only record. The spec requires full DNSSEC validation but never says that the instructions paid must be the ones the proof covered. Validating a proof and then paying from a separate, unvalidated lookup of the same name conforms to the letter of the Resolution section and provides no security at all.

  2. Why validation cannot be delegated. The Resolution section already says clients MUST NOT trust a remote resolver, without saying why. The AD bit is covered by no signature. Stating that makes the requirement self-evidently a security requirement rather than one that looks like a performance preference an implementer may trade away.

  3. Fallback is a downgrade attack. Backwards Compatibility permits falling back to Lightning Address on resolution failure, and discusses that only as an IP-leak issue. DNSSEC provides no availability guarantee, so an attacker who can drop DNS chooses which scheme the payment is made under. The added text ties this to the existing ₿ display rule, which is the mechanism already in the spec for telling a user that a name was verified.

  4. Offline validation depends on state the device cannot refresh. Display and PSBT types describe offline validation of RFC 9102 proofs on external signing devices. Validating a proof requires a root trust anchor and a clock, and BIP 353 mentions neither; "trust anchor" does not appear in the document. On a signing device with no network and often no battery-backed clock, both are real constraints: the anchor is frozen at firmware build time against a root KSK that rolls over, and a device that takes the time from the host is having the proof and the time to check it against supplied by the same party. BLIP 32 has the same gap, so this is not an oversight peculiar to this document.

No existing requirement is changed and no on-wire behaviour is altered. Nothing here is generic DNSSEC hygiene; each item is a property of this specification that an implementation can fail while conforming.

The PR also adds the Changelog section and Version header that BIP 3 requires for changes after Complete status, which BIP 353 does not yet have. It is versioned 1.0.1 on the basis that this clarifies existing intent rather than extending the specification; happy to move it to 1.1.0 if you read the new normative language otherwise. The 1.0.0 date is inferred from the commit history, which is ambiguous between the Proposed ↦ Complete change and the later status corrections, so please correct it.

These came out of building and operating a BIP 353 resolver and name service and testing resolution across the implementations that ship it.

Covers four properties implied by the existing text but never stated:
that the instructions paid must be the ones the validated proof covered,
why DNSSEC validation cannot be delegated to a remote resolver, that
falling back to an unauthenticated scheme on resolution failure lets the
attacker choose the scheme, and that offline validation of RFC 9102
proofs depends on a root trust anchor and a clock the signing device
cannot refresh.

No existing requirement is changed and no on-wire behaviour is altered.

Also adds the Changelog section and Version header BIP 3 requires for
changes after Complete status.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@murchandamus

Copy link
Copy Markdown
Member

cc: @TheBlueMatt

@murchandamus murchandamus added Proposed BIP modification PR by non-owner to update BIP content Pending acceptance This BIP modification requires sign-off by the champion of the BIP being modified labels Sep 2, 2026
bitsagarob added a commit to bitsagarob/doomsigner that referenced this pull request Sep 3, 2026
…branches

The README was written when this was a DOOM easter egg on an unmodified wallet.
Both halves of that are stale, and one of them had become untrue.

Corrected, and each claim below was checked against the code rather than
remembered:

- **"The wallet underneath is unmodified" was false.** The build has been
  pointed at bitsagarob/seedsigner since 741373d. The README now says the app is
  modified, and spells out the two consequences: this image cannot reproduce an
  upstream release hash, and none of the silent payments work has been reviewed
  by anyone. docs/building.md gets the same note, because its reproducible-build
  quickstart is upstream's check and no longer applies here.

- **Reframed as a proof of concept for BIP-352 silent payments.** That is what it
  is for now; DOOM came first and is no longer the point.

- **Added the overview of what is new**, cross-linked to where the work actually
  lives: embit#145 for the cryptography, SeedSigner#769 and #949 for the address
  and send paths, 3rdIteration#143 for the time QR this image already reads,
  embit#102 / pydnssec-prover#2 / SeedSigner#798 for the BIP-353 half that is
  still blocked, and bitcoin/bips#2272. Every link was fetched and returns 200.

- **The switching docs were wrong in three ways.** It said the device "comes up
  running DOOM": it comes up in a chooser with Snake and DOOM. It described the
  three-button unlock without saying it is one-way, so a reader could not tell
  how to get back (you reboot). And it never mentioned that the browser simulator
  uses a different sequence entirely, five taps on KEY1, which does toggle both
  ways. All three are now stated, including that the device/simulator divergence
  is a divergence and not a design.

- On-chain proofs linked and re-verified live: both signet transactions still
  answer from the tx-proof endpoint, and the mainnet send is confirmed in block
  965081.

Also, per Rob: no feature branches. The app fork's `dev` now carries the silent
payments commits (fast-forward, nothing lost, and it picks up the 163 upstream
commits it was behind), the two feature branches are deleted, and build.sh plus
the workflow both target `dev`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

@TheBlueMatt TheBlueMatt left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is slop and it's not clear that this is adding anything.

@bitsagarob bitsagarob closed this Sep 3, 2026
@bitsagarob

Copy link
Copy Markdown
Author

Fair, closing. The one point I'd keep, that a signer shouldn't take the clock from the same host that supplies the proof, is a signer implementation issue and I'll raise it there.

@bitsagarob
bitsagarob deleted the 2026-09-bip353-security-considerations branch September 3, 2026 21:25
bitsagarob pushed a commit to bitsagarob/seedsigner that referenced this pull request Sep 4, 2026
Sparrow and Cake already write PSBT_OUT_DNSSEC_PROOF into the PSBT. Every
hardware signer shipping today throws it away, so the name the user typed is
checked by the machine that could lie about it and by nothing else.

This adds the validation, not yet the screens. It matters most for silent
payments: a BIP-352 output is derived from the recipient's keys and the sender's
inputs, so the sp1 string appears nowhere on chain and the review screen has no
address a human can compare against anything. A validated name is the only check
that exists at all.

Four things have to hold, and they are checked in this order on purpose:

1. The chain verifies from the DNS root trust anchor, using only bytes carried
   in the PSBT. Checked first, because "this proof is forged" must not be masked
   by "this device has no clock".
2. Exactly one TXT under <user>.user._bitcoin-payment.<domain> begins, case
   insensitively, with "bitcoin:". BIP-353 specifies two as invalid rather than
   as a preference: tolerate it and whoever can add a record to the zone picks
   which instructions you pay.
3. The instructions in that record are the instructions being paid. The proof
   itself does not give you this. A perfectly valid proof for someone else says
   nothing about the output in front of you unless something compares them, and
   this is the check nobody performs; it is one of the four gaps in
   bitcoin/bips#2272. Compared as keys against PSBT_OUT_SP_V0_INFO rather than
   as strings, with the network checked separately, since the keys are identical
   across chains.
4. The signatures are current. Measured RRSIG windows run 1.2 to 13 days and
   Cloudflare-hosted zones sit at the bottom, so a device with no clock cannot
   simply ignore this. Three outcomes stay distinct and are never collapsed into
   two: verified against a known time, expired, and no date available.

Tests run against the five proofs BIP-353 publishes, two of which are invalid
for two different reasons, plus live captures. Case 04 is a cryptographically
perfect chain that BIP-353 rejects, and case 05 is case 03 with one NSEC3
removed, which catches a validator that checks every signature present and never
notices a required denial of existence is absent.

The name format cost a bug worth recording: records live at
<user>.user._bitcoin-payment.<domain>, with a literal "user" label in the middle
that is easy to miss when reading the BIP quickly. Omitting it produces a
validator that resolves nothing while looking entirely correct.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Pending acceptance This BIP modification requires sign-off by the champion of the BIP being modified Proposed BIP modification PR by non-owner to update BIP content

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants