Skip to content

semillabitcoin/descriptor-cifrado

Repository files navigation

BED — Bitcoin Encrypted Backup

License: MIT

A small Rust + Svelte service that encrypts a Bitcoin multisig descriptor using any cosigner xpub, producing a .bed file (binary, ASCII-armored, or QR PNG) that can only be decrypted by someone holding that same xpub.

Implements the draft BIP "Bitcoin Encrypted Backup" (PR bitcoin/bips#1951) and is interoperable with Liana wallet v13+ via the bitcoin-encrypted-backup crate v0.0.2.

TL;DR

  1. Install on StartOS as the BED s9pk.
  2. Open the Tor onion or LAN .local URL the StartOS dashboard provides.
  3. Paste your descriptor → download the .bed (or armored block, or QR).
  4. Distribute one .bed copy per cosigner location.

Golden rule: The cardinal rule of BED — never co-locate a .bed file and a cosigner xpub of the same multisig. If an attacker finds both, they can decrypt the descriptor and learn your full wallet structure. See Threat Model for the complete model.

Usage

Encrypt a descriptor

  1. Open the Cifrar tab.
  2. Paste a multisig descriptor that uses the multipath wildcard <0;1>/*. Descriptors without this wildcard are rejected — see Common Pitfalls.
  3. Click Cifrar. The page returns three outputs simultaneously:
    • A binary .bed file (download).
    • An ASCII-armored block with -----BEGIN BITCOIN ENCRYPTED BACKUP----- headers, copyable to clipboard.
    • A QR PNG of the armored payload (download), if the payload fits within QR ECC-L capacity (~2,900 bytes).
  4. Optionally enable the history toggle. With history enabled the .bed is also saved to /data/encrypted/<YYYYMMDDTHHMMSSZ>-<8hex>.bed for later listing and deletion. Default is OFF — the cleartext descriptor and the .bed are returned to the browser and immediately forgotten.

Decrypt a .bed file

  1. Open the Descifrar tab.
  2. Either paste the armored block or upload the binary .bed file.
  3. Either paste the cosigner xpub (bare, e.g. xpub6...) or upload a file containing it.
  4. Click Descifrar. The recovered descriptor appears with a Copy-to-clipboard button. The descriptor is never persisted on disk.

Wallet exports beyond plain descriptors (since v0.3.0)

Beyond a bare descriptor string, BED also encrypts and decrypts two wallet-export formats round-trip byte-identical:

  • Liana JSON. Paste or load a Liana wallet export (the JSON file with the nested descriptor and metadata). BED detects it by the leading {, encrypts the JSON in full, and on decrypt returns the original JSON intact. Useful when you want a single .bed to reconstruct a Liana wallet (descriptor + metadata) instead of just the descriptor.
  • Sparrow Wallet BIP-329 JSONL. Paste or load a Sparrow labels export (multi-line JSONL where each line is {type, ref, label} per BIP-329). BED detects it by the leading { on the first line, encrypts the JSONL in full, and on decrypt returns the original labels intact — byte for byte, including line endings. The decrypt panel visually distinguishes Sparrow exports from classic / Liana payloads so you know which file to re-import where.

Both formats coexist with the classic descriptor flow. The encrypt file picker accepts .txt, .descriptor, .json, and .jsonl (drag-and-drop also supported).

Workflow example. Recover a multisig wallet from cold storage: recreate the wallet in Liana from the decrypted JSON (descriptor + metadata in one file), then import the decrypted Sparrow JSONL into Sparrow if you also keep label history. Two .bed files cover both the wallet structure and the label history.

Threat Model

What BED protects

  • Descriptor privacy. A .bed file reveals nothing about the wallet's structure, xpubs, derivation paths, or spending policy to an attacker who only has the file. AES-256-GCM authenticated encryption guarantees that any tampering is detected on decryption.
  • xpub distribution. Each cosigner can safely store a .bed backup without exposing the full wallet policy — they only need their own xpub to decrypt it. This enables redundant distribution of the descriptor (the only piece needed to fully recover a multisig wallet) without coupling that distribution to the privacy of the policy.
  • Cleartext-on-disk leakage. The cleartext descriptor never touches disk. It is wrapped in secrecy::SecretString from parse through encryption, zeroized after the operation, and excluded from logs by an explicit tracing skip-all guard. A CI test grep-asserts the descriptor string does not appear in any log output.

What BED does NOT protect against

Golden rule (repeated): The security model requires that you never co-locate a .bed file with any cosigner xpub of the same multisig. If an attacker finds both, they can decrypt the .bed and learn the full wallet structure. Each .bed copy must live in a different physical location than the xpub needed to decrypt it.

  • Compromise of the StartOS device during an active encrypt session. The descriptor passes through the device's memory in cleartext during encryption. If the device is compromised at that moment (malicious app, physical access, kernel-level attacker) the descriptor may be exposed. BED cannot protect against an attacker who controls the execution environment.
  • Loss of all cosigner xpubs simultaneously. If every xpub needed to decrypt is lost or destroyed, the .bed becomes undecryptable. BED provides redundancy for distribution, not a substitute for independent xpub backups.
  • An attacker who already holds one cosigner xpub. A .bed encrypted with xpub A can be decrypted by anyone holding xpub A. The model is sound only when each co-location (.bed + xpub_N) is in a different physical location.
  • Side-channel and traffic analysis. BED runs locally on StartOS over Tor or LAN. It does not defend against advanced traffic-analysis adversaries who already control the local network.
  • Hardware wallet support. USB device support is intentionally omitted (StartOS 0.4.0 does not pass USB into containers). Use a software wallet to extract the descriptor; sign with hardware after.

Model assumptions

  • The StartOS device is trusted during the session.
  • Each .bed copy lives in a different physical location than any xpub that could decrypt it.
  • The .bed file format integrity is guaranteed by AES-256-GCM authentication — any tampering is detected.
  • The cosigner xpub used to encrypt is not also the only one that decrypts; in a 2-of-3 multisig you typically encrypt one .bed per cosigner using a different cosigner's xpub each time.

Crypto Details

Property Value
Encryption AES-256-GCM
Magic header BEB (binary identifier)
KDF Per BIP draft (xpub-derived; see PR for details)
Spec bitcoin/bips PR #1951 — draft
Implementation bitcoin-encrypted-backup crate, pinned at v0.0.2 (rev cd7ee382bf5ca0798d4f81697e2f9efb5e32fe40)
Interop Liana wallet v13+ reads .bed files produced here, and BED reads .bed files produced by Liana
Descriptor requirement Must use the BIP-380 multipath wildcard <0;1>/*. Without it, spending from address 0 exposes the xpub on-chain and breaks the encryption model.

The .bed format is an external contract: BED will not break it without a new milestone. If a future BIP revision changes the format (e.g. ChaCha20-Poly1305 instead of AES-GCM), the old version is archived in CHANGELOG and a separate "BED v0.x archive" branch is kept available for decrypting legacy files.

Common Pitfalls

  1. Descriptor without <0;1>/*. BED rejects single-path descriptors with a typed validation error. Convert your descriptor to multipath form before encrypting.
  2. xpub vs descriptor-style format. The Decrypt tab expects a bare xpub (e.g. xpub6FHa3...). Descriptor-style xpubs with a [fingerprint/path] prefix or a /* suffix are rejected. Strip the prefix and suffix before pasting.
  3. QR size limit (~2,900 bytes ECC-L). Multisig descriptors with five or more cosigners may produce armored payloads that exceed the QR ECC-L capacity. Since v0.3.0 the QR panel degrades cleanly to "QR not available — payload too large"; binary and ASCII-armored downloads remain available for those cases. Use them with cold-storage paper for QR-bound transport.
  4. History mode default is OFF. The history toggle is opt-in. If you cifrar without enabling it, the .bed is returned to the browser and the server forgets it immediately. Enable the toggle explicitly if you want the file persisted to /data/encrypted/.

References

License

MIT. See LICENSE.

About

Encrypted Descriptor (BED) — encrypts Bitcoin multisig descriptors with AES-256-GCM using a cosigner xpub. BIP draft bitcoin/bips#1951 + Liana wallet interop.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors