Bip draft: Bitcoin Encrypted Backup#1951
Conversation
2a6e241 to
d9d02ff
Compare
|
thanks for the review! will address comments tmr! |
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 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. |
|
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. |
1e4ca34 to
3b6b6ad
Compare
|
Concept ACK |
|
(not yet finish addressing comments) |
|
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: 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. |
ab0d14d to
2ce692d
Compare
Hi @KeysSoze, this work seems more related/parallel to the But I've adopted a slightly different approach by simply using JSON. FYI we already implemented this wallet backup format in Liana wallet and I plan to work on a BIP proposal relatively soon. |
|
The PR is still draft. Are there things you're still working on? What's the Gathered open issues from the inlines threads:
Nit: there's quite a bit of trailing whitespace (which my editor then automatically tries to fix) Maybe this could replace VARIANT: #### Content
`CONTENT` is a variable length field defining the type of `PLAINTEXT` being encrypted,
it follows this format:
`TYPE` (`LENGTH`) `DATA`
`TYPE`: 1-byte unsigned integer identifying how to interpret `DATA`.
| Value | Definition |
|:-------|:---------------------------------------|
| 0x00 | Reserved |
| 0x01 | BIP Number (big-endian uint16) |
| 0x02 | Vendor-Specific Opaque Tag |
`LENGTH`: variable-length integer representing the length of `DATA` in bytes.
For all `TYPE` values except `0x01`, `LENGTH` MUST be present.
`DATA`: variable-length field whose encoding depends on `TYPE`.
For `TYPE` values defined above:
- 0x00: parsers MUST reject the payload.
- 0x01: `LENGTH` MUST be omitted and `DATA` is a 2-byte big-endian unsigned integer representing the BIP number that defines it.
- 0x02: `DATA` MUST be `LENGTH` bytes of opaque, vendor-specific data.
For all `TYPE` values except `0x01`, parsers MUST reject `CONTENT` if `LENGTH` exceeds the remaining payload bytes.
Parsers MUST skip unknown `TYPE` values less than `0x80`, by consuming `LENGTH` bytes of `DATA`.
For unknown `TYPE` values greater than or equal to `0x80`, it MUST stop parsing `CONTENT`.It might add one extra byte for the BIP case, but that's negligible compared to the length of a typical descriptor. And it reduces complexity. The Let's also add quick section to encourage base64 encoding: ### Text Representation
Implementations SHOULD encode and decode the backup using Base64 (RFC 4648).[^psbt-base64]
[^psbt-base64]: **Why Base64?**
PSBT (BIP174) is commonly exchanged as a Base64 string, so wallet software likely already supports this representation.(the footnote format is the same as in BIP3, I think we should use it for all rationale bits) |
|
@murchandamus or other editor: I think this has progressed enough to be BIP number worthy. It would make it easier to generate stable test vectors. |
|
@Sjors thanks for the comments, will address during the week end or next week.
I'm working on another BIP draft for the payload of a wallet backup, i'd like to undraft them together, as they are quite related: the payload is expected to be encrypted with this spec... In the meantime, I've "played" with a C implementation of this BIP draft, I wanted to check how hard it should be to implement in bitcoin core and I figure out something: it seems there is actually no dependency in core for AES-GCM-256, while there is already usage of CHACHA20 so i'm wondering if we should not use CHACHA20 as default encryption algo? (I'll cross-post to delving) |
|
@pythcoiner using In theory we don't need the
For Bitcoin Core you can use c++, no need to torture yourself. But if it also works in C that makes it easier for hardware wallets to have low level support - not sure if they needed, but still. You could also try with embedded Rust and MicroPython. Perhaps an extension of the protocol could have hardware wallet sign off on the descriptor / policy, by appending |
bfdf6f7 to
ab5d450
Compare
yes, I've dropped it |
not felt the torture part 😄 the idea was more, all languages can bind to C, it's not always the case for c++ (or at least less easy) and maybe it worth to have a single implem to maintain |
ab5d450 to
f73a0d5
Compare
|
@Sjors I think all comments has been addressed, not yet entirely finnish updating the rust implementation. There is still some double trailing spaces, necessary for formating. |
f73a0d5 to
160c34a
Compare
|
This proposal makes multiple references to BIP 380 as defining wallet descriptors. This is incorrect - BIP 380 defines output script descriptors. Since we may have a need to define wallet descriptors as specific format in future (including, for example, a wallet birthday) I believe these references should be corrected. |
|
I vibe coded an implementation on top of Bitcoin Core: Sjors/bitcoin#109 It's nice to see how we can mostly reuse existing tooling. It still adds over 1000 lines of non-test code though. Doing so brought up some issues to reconsider:
/ Current implementation (14 lines):
uint256 ComputeDecryptionSecret(const std::vector<uint256>& keys)
{
HashWriter hasher{};
hasher << std::span{reinterpret_cast<const uint8_t*>(BIP_DECRYPTION_SECRET_TAG.data()),
BIP_DECRYPTION_SECRET_TAG.size()};
for (const auto& key : keys) {
hasher << std::span{key.data(), 32};
}
return hasher.GetSHA256();
}
// With BIP340-style tags (could become):
uint256 ComputeDecryptionSecret(const std::vector<uint256>& keys)
{
HashWriter hasher = TaggedHash("BIP_XXXX_DECRYPTION_SECRET");
for (const auto& key : keys) hasher << key;
return hasher.GetSHA256();
}(that seems like a fairly trivial difference anyway) |
@craigraw Right, I'll change this
@Sjors Thanks for looking on this! I'm ok to change stuff if it make integration in core simpler |
5cfd5a3 to
7d4250c
Compare
7d4250c to
f807871
Compare
@Sjors I'm not sure it simplify the parsing for fixed length integers? |
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