Bip draft: Bitcoin Encrypted Backup #1951

pull pythcoiner wants to merge 4 commits into bitcoin:master from pythcoiner:encrypted_descriptor changing 1 files +231 −0
  1. pythcoiner commented at 6:47 am on September 4, 2025: none

    This is a bip for encrypted backup, an encryption scheme for bitcoin wallet related metadata.

    Mailing list post: https://groups.google.com/g/bitcoindev/c/5NgJbpVDgEc

  2. pythcoiner marked this as a draft on Sep 4, 2025
  3. pythcoiner force-pushed on Sep 4, 2025
  4. in bip-encrypted-backup.md:4 in d9d02ffc5b outdated
    0@@ -0,0 +1,268 @@
    1+```
    2+BIP: ?  
    3+Layer: Applications  
    4+Title: Bitcoin Encrypted Backup  
    


    Sjors commented at 7:45 am on September 4, 2025:

    How about: Compact encryption scheme for non-seed wallet data

    Or some other wording to make it clear this isn’t for storing keys.

  5. in bip-encrypted-backup.md:28 in d9d02ffc5b outdated
    24+lexicographically‑sorted public keys inside the descriptor or policy, so any party
    25+who already holds one of those keys can later decrypt the backup without extra secrets
    26+or round‑trips. The format uses AES-GCM-256 with a 96‑bit random nonce and a 128‑bit
    27+authentication tag to provide confidentiality and integrity.
    28+While initially designed for descriptors and policies, the same scheme encrypts labels
    29+and backup metadata, allowing a uniform, vendor‑neutral, and future‑extensible backup format.
    


    Sjors commented at 7:47 am on September 4, 2025:
    The abstract should also explicitly state that it’s not intended for storing private key material.
  6. in bip-encrypted-backup.md:53 in d9d02ffc5b outdated
    48+1. **Descriptors are hard to store offline.**  
    49+   Descriptor string representation can be far longer than a 12/24-word seed phrase.  
    50+Paper, steel, and other long-term analog media quickly become impractical for such
    51+lengths, or error-prone to transcribe.
    52+
    53+2. **Online redundancy carries risk.**  
    


    Sjors commented at 7:48 am on September 4, 2025:
    privacy risk
  7. in bip-encrypted-backup.md:64 in d9d02ffc5b outdated
    59+
    60+These constraints lead to an acute need for an **encrypted**, and
    61+ideally compact backup format that:
    62+
    63+* can be **safely stored in multiple places**, including untrusted on-line services,  
    64+* can be **decrypt only by intended holders** of specified public keys,  
    


    Sjors commented at 7:49 am on September 4, 2025:
    decrypted
  8. in bip-encrypted-backup.md:65 in d9d02ffc5b outdated
    60+These constraints lead to an acute need for an **encrypted**, and
    61+ideally compact backup format that:
    62+
    63+* can be **safely stored in multiple places**, including untrusted on-line services,  
    64+* can be **decrypt only by intended holders** of specified public keys,  
    65+* and keeps both **keys and plaintext** hidden from any party who lacks the
    


    Sjors commented at 7:50 am on September 4, 2025:
    I don’t understand what you mean with this last sentence. Also do “keys” mean private keys or public keys?

    pythcoiner commented at 4:59 am on September 5, 2025:
    I’ll drop this one, it’s redunndant with the previous one
  9. in bip-encrypted-backup.md:37 in d9d02ffc5b outdated
    33+This BIP is licensed under the BSD 2-Clause License.  
    34+Redistribution and use in source and binary forms, with or without modification, are
    35+permitted provided that the above copyright notice and this permission notice appear
    36+in all copies.
    37+
    38+### Motivation
    


    Sjors commented at 7:52 am on September 4, 2025:
    This section could be shorter imo. It feels a bit repetitive. You can also link to the Delving post for more background.
  10. in bip-encrypted-backup.md:116 in d9d02ffc5b outdated
    111+This specification applies to creating, encrypting and decrypting a *Bitcoin Encrypted Backup*
    112+of **public-key-only wallet material**, namely:
    113+
    114+- a **descriptor** (BIP-0380)  
    115+- a **wallet policy** (BIP-0388)  
    116+- **BIP-329 labels** (JSONL)  
    


    Sjors commented at 7:54 am on September 4, 2025:
    Imo the primary motivation for this proposal is to store a descriptor or policy (they’re interchangeable). Storing additional information is nice to have.
  11. in bip-encrypted-backup.md:120 in d9d02ffc5b outdated
    115+- a **wallet policy** (BIP-0388)  
    116+- **BIP-329 labels** (JSONL)  
    117+- **wallet-wide JSON backup metadata**  
    118+
    119+All four payloads are encrypted under the same key derivation rules detailed below.
    120+The scheme is **not** intended for descriptors or policies that contain private keys,
    


    Sjors commented at 7:56 am on September 4, 2025:
    Another way to put this is: private keys and seeds MUST be removed (neutered) from descriptors before storing them in this scheme.
  12. in bip-encrypted-backup.md:132 in d9d02ffc5b outdated
    127+
    128+### Secret generation
    129+
    130+* Let `p_1`, `p_2`, .., `p_n` be the public keys in the descriptor/wallet policy, in
    131+increasing lexicographical order.  
    132+* let `secret` = sha256("BEB_DECRYPTION_SECRET" ‖ `p1` ‖ `p2` ‖ ... ‖ `pn`)  
    


    Sjors commented at 7:57 am on September 4, 2025:
    Instead of BEB I would suggest BIP_XXX (replaced with the BIP number once assigned).

    pythcoiner commented at 5:38 am on September 5, 2025:
    I’ve written w/ BIPxxxx at first, but changes it to BEB then, as we are very likely to ship a feature using this scheme in Liana v13 (so likely before this get assigned a BIP #)…

    Sjors commented at 6:51 am on September 5, 2025:
    Liana could switch to the BIP number once assigned. When reading it could first check BEP and then BIP_XXXX. That also gives you the flexibility to make breaking changes to other parts of this spec without having to bump the version number.

    pythcoiner commented at 10:11 am on September 5, 2025:
    Agree, we are in control of what happen in Liana, but my concern is more about other implementations that will not be able to decrypt early version generated w/ Liana… Btw, we already plan to ship w/ version 0, that’s why this BIP draft define version 1…

    Sjors commented at 4:31 pm on September 5, 2025:
    I would probably just write a Gist documenting the Liana-specific v0 (other mights have tried your code as well), and then maybe link to it from a footnote in the BIP.
  13. in bip-encrypted-backup.md:21 in d9d02ffc5b outdated
    16+### Abstract
    17+
    18+This BIP defines a compact encryption scheme for **wallet descriptors** (BIP-0380),
    19+**wallet policies** (BIP-0388), **labels** (BIP-0329), and
    20+**wallet backup metadata** (json). The encrypted output—called a
    21+*bitcoin encrypted backup* (BEB), enables users to outsource long‑term storage to
    


    Sjors commented at 8:00 am on September 4, 2025:
    This scheme is generic enough that I don’t think it needs the word “bitcoin” in it. I also don’t think we need to pick a “marketing name”, something more boring like “BIP_XXX encrypted backup” should be fine.
  14. in bip-encrypted-backup.md:133 in d9d02ffc5b outdated
    128+### Secret generation
    129+
    130+* Let `p_1`, `p_2`, .., `p_n` be the public keys in the descriptor/wallet policy, in
    131+increasing lexicographical order.  
    132+* let `secret` = sha256("BEB_DECRYPTION_SECRET" ‖ `p1` ‖ `p2` ‖ ... ‖ `pn`)  
    133+* let `si` = sha256("BEB_INDIVIDUAL_SECRET" ‖ `pi`)  
    


    Sjors commented at 8:01 am on September 4, 2025:
    If it’s possible to use subscript in markdown then I would prefer to keep the original notation with small i. Otherwise let’s use an underscore, i.e. s_i
  15. in bip-encrypted-backup.md:169 in d9d02ffc5b outdated
    201+`COUNT`: 1-byte unsigned integer (1–255) indicating how many secrets are included.  
    202+`INDIVIDUAL_SECRET`: 32-byte serialization of the derived individual secret.
    203+
    204+#### Content
    205+
    206+`CONTENT`: 1-byte unsigned integer identifying what has been encrypted.
    


    Sjors commented at 8:07 am on September 4, 2025:
    I would prefer to keep this secret and have multiple pieces of content in a single backup. So my suggestion is to move this inside the encrypted payload and then allow for multiple content entries.

    pythcoiner commented at 9:51 am on September 4, 2025:

    and then allow for multiple content entries

    hum, no strong opinion on this, but if the purpose is to have a single encrypted file containing descriptor(380 or 388) + labels + wallet metadata then it should fit into 0x04 Wallet Backup (yeah I’ll have to write a formal spec)


    Sjors commented at 10:27 am on September 4, 2025:
    In the original delving post there’s no specification of the format at all. So you could also just say it should be JSON and leave it up to other BIPs or convention.

    pythcoiner commented at 5:55 am on September 5, 2025:
    Yeah this BIP draft differ a bit from the initial post in the fact it intentionally add some formating convention
  16. in bip-encrypted-backup.md:177 in d9d02ffc5b outdated
    209+|:-------|:---------------------------------------|
    210+| 0x00   | Undefined                              |
    211+| 0x01   | BIP-0380 Descriptor (string)           |
    212+| 0x02   | BIP-0388 Wallet policy (string)        |
    213+| 0x03   | BIP-0329 Labels (JSONL)                |
    214+| 0x04   | Wallet backup (JSON)                   |
    


    Sjors commented at 8:10 am on September 4, 2025:

    Maybe point out that unlisted types should still be decrypted and that new types may be added to the BIP.

    That said, a more generic approach would be to allow a bit more space for the type. E.g. a ~4 digit number that must represent a BIP number. Or a short string like “BIP-0329”. Both avoid the need to maintain a central register.

    Also, if you allow multiple pieces of content in a single encrypted blob, it’s useful to have a padding type.

  17. in bip-encrypted-backup.md:219 in d9d02ffc5b outdated
    251+### Future Extensions
    252+
    253+The version field enables possible future enhancements:
    254+
    255+- Additional encryption algorithms  
    256+- Support for threshold-based decryption
    


    Sjors commented at 8:11 am on September 4, 2025:
    • hide the number of participants
    • bech32m export (convenient for text based storage like an email to yourself, as well as for printing - if you’re patient)

    pythcoiner commented at 11:05 am on September 4, 2025:

    hide the number of participants

    hum, the number of participant can also be hidden (derivation path are optionals) and one can also add fake ones, how do you think we can enhance this further?


    Sjors commented at 11:07 am on September 4, 2025:
    It’s currently revealed by the number of c_i shares, so it would be a more complicated overhaul. I don’t think it’s urgent.

    pythcoiner commented at 11:10 am on September 4, 2025:
    right
  18. pythcoiner commented at 9:42 am on September 4, 2025: none
    thanks for the review! will address comments tmr!
  19. jonatack added the label New BIP on Sep 4, 2025
  20. Sjors commented at 12:52 pm on September 4, 2025: member

    Open questions

    • Deterministic nonce: Currently the nonce is generated randomly. Is it safe to produce a deterministic nonce, e.g. hash("NONCE" || plaintext || key_1 || … || key_n), or are there known security concerns with this approach?

    In general nonce reuse is unsafe because if you make multiple backups over time, e.g. as you add more transaction labels, you would be reusing the nonce with different message. By including the plaintext in the nonce, you do address that concern.

    However it still seems unwise to mess with cryptographic standards. It doesn’t seem worth the risk for saving 32 bytes on something that’s going to be at least a few hundred bytes for a typical multisig.

  21. shocknet-justin commented at 5:09 pm on September 4, 2025: none
    Concept ACK, seems adjacent to how some lightning tools enable users to recover SCB’s with just their seed to identify and decrypt the backup. Makes sense for descriptors to have something similar.
  22. pythcoiner force-pushed on Sep 5, 2025
  23. pythcoiner force-pushed on Sep 5, 2025
  24. pythcoiner force-pushed on Sep 5, 2025
  25. pythcoiner force-pushed on Sep 5, 2025
  26. pythcoiner force-pushed on Sep 5, 2025
  27. pythcoiner force-pushed on Sep 5, 2025
  28. bip encrypted_backup 3b6b6ad642
  29. pythcoiner force-pushed on Sep 5, 2025
  30. u 89205bf190
  31. u 3b713e33d2
  32. u 2ec6487d74
  33. Sjors commented at 6:59 am on September 5, 2025: member
    Concept ACK
  34. pythcoiner commented at 9:50 am on September 5, 2025: none
    (not yet finish addressing comments)
  35. in bip-encrypted-backup.md:20 in 2ec6487d74
    15+
    16+### Abstract
    17+
    18+This BIP defines a compact encryption scheme for **wallet descriptors** (BIP-0380),
    19+**wallet policies** (BIP-0388), **labels** (BIP-0329), and
    20+**wallet backup metadata** (json). The payload must not contains any private key material.
    


    torkelrogstad commented at 3:40 pm on September 8, 2025:
    contain, not contains
  36. KeysSoze commented at 9:57 pm on September 9, 2025: none

    Hi @pythcoiner,

    By coincidence, two weeks ago I started working on a proposal for a “Standard Encrypted Wallet Payload” to be placed inside an “Encrypted Envelope”. The “Wallet Payload” contains descriptors and metadata but can also act as a full wallet backup including transactions, UTXOs and addresses. The proposal is very much a work in progress.

    I only just found this discussion so am reading through it to compare it to my proposal. The descriptor backup in the “Wallet Payload” of my proposal seems to have some overlap with the BIP proposed here. If there is too much overlap I may reconsider progressing with my proposal.

    As mentioned, my proposal is very much a work in progress but the wallet payload proposal can be found here:

    https://gist.github.com/KeysSoze/7109a7f0455897b1930f851bde6337e3

    Maybe jump to the test vector section to see what a basic backup of a descriptor and some meta data would look like prior to encryption.

    https://gist.github.com/KeysSoze/7109a7f0455897b1930f851bde6337e3#test-vectors

    As my proposal is designed to be modular and extensible the encryption envelopes may be extended to offer Multiparty Encryption and Authentication. See:

    https://gist.github.com/KeysSoze/7109a7f0455897b1930f851bde6337e3#user-content-Expanding_the_Security_Model

    I have already started documenting an encryption envelope that uses AES-256-GCM and password protection:

    https://gist.github.com/KeysSoze/866d009ccd082edf6802df240154b20d

    I have not written a reference implementation yet but there are well established python and Rust libraries for CBOR and COSE that should make implementing the BIPs relatively simple.


github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bips. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2025-09-13 09:10 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me