SeedSigner + BIP-353: Human-Readable Bitcoin Payments

Oct 2, 2025

Bitcoin’s address system has always presented a paradox. On one hand, addresses are designed for efficiency and compactness; on the other, their opaque encoding makes them nearly impossible to use directly without relying on copy-paste or QR codes. This usability gap has fueled proposals over the years to give Bitcoin payments a human-readable layer. From BIP-21/BIP-321 URIs to BIP-70’s payment protocol, and more recently LNURL and Lightning Address, the community has continued to experiment with bridging human interaction and cryptographic correctness.

BIP-353 “DNS Payment Instructions” is the latest step in this trajectory. It proposes a method to leverage the existing DNS infrastructure (specifically DNSSEC-secured records) as a globally deployed naming and authentication system for Bitcoin payment instructions. The result is the possibility to use a human-readable name (HRN), like alice.example.com, to resolve to a valid Bitcoin payment request, secured by cryptographic proofs rather than simple trust in a DNS server.

For software wallets with network connectivity, integration of BIP-353 is relatively straightforward: resolve DNS records, verify DNSSEC, parse the payment instruction, and proceed. But the challenge becomes more interesting when we consider hardware wallets, especially air-gapped ones like SeedSigner .

Key Question: How can a constrained device, with no direct network access, participate in this resolution process while still ensuring the user gets strong assurances about the authenticity of the payment instructions?

This article explores that question. We will first examine the design of BIP-353, then review its implementation in embit (the library underlying SeedSigner) and finally analyze the architectural and UX challenges of bringing DNS Payment Instructions to a hardware wallet environment. Along the way, we’ll also consider alternative approaches to presenting these proofs to the user and balancing security with usability.

Background

The Problem with Raw Addresses

Bitcoin addresses, whether in base58 or bech32, are hostile to human interaction. They are long, random-looking strings with no semantic meaning. Even a single transcription error renders them invalid or, worse, redirects funds to the wrong destination. Wallets have mitigated this problem by relying on QR codes, address books, or copy-paste, but these are at best workarounds.

The deeper issue is that addresses do not map to identity or intent. A user cannot tell by inspection who controls bc1qxy2kgdygjrsqtzr3n0yrf243p83kkfj2hx0wlh. This lack of semantics means payments always require an out-of-band communication channel to convey “who you are paying”.

Prior Attempts at Human-Readable Payments

Several standards and protocols have tried to smooth over this gap:

Each of these solutions improved usability but either fell short on adoption or introduced new trust dependencies.

DNS and DNSSEC as a Naming Layer

DNS is already the Internet’s canonical namespace. Every major Bitcoin service, exchange, and merchant owns domains, often with DNSSEC deployed. DNSSEC provides a chain of cryptographic signatures from the root zone down to the domain, enabling clients to verify that a DNS record was indeed published by the domain owner and not tampered with in transit.

BIP-353 leverages this: payment instructions are published in DNS TXT records under the control of the domain owner. A wallet can query the DNS, fetch the TXT record, and verify the associated DNSSEC proofs. If the proof is valid, the wallet can trust that alice.example.com is indeed associated with the payment details specified.

Crucially, DNSSEC provides cryptographic authenticity for the mapping between a domain and its published payment instruction. The trust model shifts away from “trust your recursive resolver or HTTPS server” toward “trust the DNSSEC chain of trust anchored in the root zone.” This still involves third parties (registrars, TLD operators, and the root key maintainers) but the guarantees are verifiable, cacheable, and resistant to MITM attacks. Unlike HTTPS, where CAs can (sometimes silently ) issue certificates, DNSSEC proofs can be validated offline and are explicitly tied to the cryptographic root of DNS (the trust anchors controlled by IANA).

From DNS to Bitcoin: the bridge

At its core, BIP-353 proposes that:

This design provides a minimal but globally interoperable naming layer for Bitcoin, without introducing new infrastructure. It reuses what is already deployed at scale and combines it with existing Bitcoin URI.

BIP-353 Specification

BIP-353 is a thin resolution and authentication layer that connects human-readable names to existing Bitcoin URI semantics (BIP-21). The proposal can be understood in three components:

Human-Readable Name (HRN)

Payment Instruction Records

DNSSEC Proofs

Security Model

More details on the official BIP

Embit + SeedSigner + BIP-353 Integration

Below I lay out how the BIP-353 work landed in embit, why it was implemented the way it was, and the practical implications for hardware wallets that use embit as their Bitcoin toolkit (such as Krux and SpecterDIY ).

Short summary / takeaways

The PR implements BIP-353 support in embit by (1) adding a PSBT output field for RFC-9102 DNSSEC proofs, (2) adding parsing of BIP-21/BIP-321 URIs from TXT records, and (3) integrating the TheBlueMatt's dnssec-prover proof generator/validator (Rust) as a binary/uniffi binding so embit can verify RFC-9102 authentication chains offline.

The approach is explicitly about offline verification: proof material is created by an online machine (or a DoH-enabled helper), attached to the PSBT, and carried to the signer. The signer can validate the proof without performing DNS lookups itself. That is exactly what BIP-353 anticipates (RFC-9102 proofs in PSBT).

High-level architecture / UX runtime flow

(1) Proof generation (online helper): the wallet coordinator within an online machine queries DNS/DNSSEC and builds an RFC-9102 AuthenticationChain proof for user.user._bitcoin-payment.domain (as BIP-353 specifies). The proof is a serializable binary blob representing the full DNSSEC chain needed to validate the TXT RR(s).

Here a real-life example from Sparrow Wallet:

Sparrow Wallet Interface

(2) Embed in PSBT: the coordinator software writes the proof into the PSBT per-output field PSBT_OUT_DNSSEC_PROOF (format: 1-byte len + HRN string + RFC-9102 proof payload). The PSBT also contains outputs/amounts as usual.

(3) Transfer to signer: the PSBT (now carrying the proof) is moved to the air-gapped signer (in SeedSigner's case by QR).

(4) Signer validation (offline): on the hardware wallet, embit reads the PSBT, locates PSBT_OUT_DNSSEC_PROOF, and calls verify_dns_proof() to validate the RFC-9102 chain and to extract TXT records. Embit then filters the TXT records per BIP-353 rules (ignore non-bitcoin: entries; treat multiple bitcoin: TXT records at the same label as invalid). If validation passes and the TXT contains a BIP-21/BIP-321 URI, embit can parse it and present the canonical ₿user@domain and the underlying address/amount to the user.

The signer then presents both the canonical HRN (₿user@domain) and the underlying Bitcoin address/amount to the user.

Will Send Screen PSBT Summary Screen

Afterwards, verification should explicitly happen:

Verification Screen

This design decouples proof retrieval (online) from proof verification (offline), ensuring that a compromised wallet cannot silently substitute destinations. Even if Sparrow were “evil” and attempted to replace the intended address, SeedSigner independently validates the DNSSEC proof before displaying the recipient.

Open questions and tradeoffs

Bindings vs Porting

The PR currently relies on Rust dnssec-prover binaries with Python bindings (uniffi). This is robust and already audited, but awkward for highly constrained devices that try to avoid native dependencies. Also, although reproducibility can be maintained, mixing platforms and separate manual attestations are always added friction for the users (which are the developers of hardware wallets).

I created for this matter a pure-Python port pydnssec-prover but is newer and not battle-tested.

So it should be decided whether to standardize around the more robust but heavier Rust-based prover, or to invest in maturing the Python port so that it becomes reliable enough for long-term use on minimal hardware running MicroPython.

PSBT Size

DNSSEC proofs can be huge (tens of kilobytes) vs the typical PSBT size. BIP-353 intentionally uses PSBT as a “proof container.” For SeedSigner, which already handles large multipart QR codes, this isn’t actually a practical blocker, just a UX consideration (slightly more QR frames, slightly slower load).

Signature Timestamps & Offline Validation

DNSSEC proofs contain RRSIG validity windows. Normally, a wallet checks that the proof is valid “now”. But SeedSigner has no real-time clock, and there may be a potentially unlimited delay between when the wallet coordinator adds the proof and when the hardware wallet actually signs. This raises an important question: what happens if a proof that was valid at the time of PSBT creation expires before the user eventually signs?

This is an unresolved tension in the model.

Some argue (see Keith Mukai & Matt Corallo debate on X ) that freshness is less important than correctness: a proof validates the binding HRN → URI at a point in time, even if it later expires. Others counter that allowing stale proofs weakens security guarantees: a compromised desktop could embed a malicious HRN with a just-valid proof, and the signer would still accept it long after expiry.

For SeedSigner, the pragmatic choice may be:

UX Safeguard Example 1 UX Safeguard Example 2

External Verification Screen

While this can add redundancy, it has limits: malware could tamper with both the PSBT and the verification site, and manual comparison is tedious. A simpler approach, such as confirming the current date when showing validity ranges, offers similar security with less friction. Third-party checks may be useful for high-value cases but should remain optional.

Conclusion

BIP-353 represents a natural evolution in Bitcoin’s long effort to reconcile hard cryptography with UX. By anchoring payment instructions in DNSSEC proofs, it transforms opaque addresses into verifiable, human-readable names that can be checked offline, without introducing new infrastructure. Constrained, offline, air-gapped hardware wallets must provide strong security guarantees while operating with minimal assumptions about time, network, or trust.

The SeedSigner and embit integration demonstrates that this is not only possible but practical: proofs can be generated online, transported via PSBT, and verified offline in a reproducible way. Yet important tradeoffs remain: how to handle proof size, whether to rely on Rust bindings or pure-Python verifiers, and how to communicate DNSSEC validity windows without confusing or overburdening the user. These are not unsolvable problems, but they demand careful design choices that balance technical rigor with real-world UX.

In the bigger picture, BIP-353 pushes Bitcoin payments closer to be both secure and intuitive: users can pay [email protected] with cryptographic confidence, not blind trust. The road ahead is less about whether the standard works and more about how to refine its deployment so that everyday users, even on the most constrained devices, can rely on it safely. If the community can resolve these remaining questions, BIP-353 may finally deliver what earlier proposals could not: a naming layer for Bitcoin that is simple, universal, and verifiably secure.

References

s/o to @kdmukai , @TheBlueMatt , @notTanveer , B4OS.dev among others <3