mirror of
https://github.com/bitcoin/bips.git
synced 2026-10-05 19:16:54 +00:00
bip encrypted_backup
This commit is contained in:
373
bip-encrypted-backup.md
Normal file
373
bip-encrypted-backup.md
Normal file
@@ -0,0 +1,373 @@
|
||||
```
|
||||
BIP: ?
|
||||
Layer: Applications
|
||||
Title: Compact encryption scheme for non-seed wallet data
|
||||
Authors: Pyth <pythcoiner@wizardsardine.com>
|
||||
Status: Draft
|
||||
Type: Specification
|
||||
Assigned: ?
|
||||
License: BSD-2-Clause
|
||||
Discussion: https://delvingbitcoin.org/t/a-simple-backup-scheme-for-wallet-accounts/1607
|
||||
https://groups.google.com/g/bitcoindev/c/5NgJbpVDgEc/m/TtGK9sF9BgAJ
|
||||
```
|
||||
|
||||
## Introduction
|
||||
|
||||
### Abstract
|
||||
|
||||
This BIP defines a compact encryption scheme for **output script descriptors** (BIP-0380),
|
||||
**wallet policies** (BIP-0388), **labels** (BIP-0329), and **wallet backup metadata** (draft [BIP](https://github.com/bitcoin/bips/pull/2130)).
|
||||
The payload must not contain any private key material.
|
||||
|
||||
Users can store encrypted backups on untrusted media or cloud services without leaking
|
||||
addresses, script structures, or cosigner counts. The encryption key derives from the
|
||||
lexicographically-sorted public keys in the descriptor, allowing any keyholder to decrypt
|
||||
without additional secrets.
|
||||
|
||||
Though designed for descriptors and policies, the scheme works equally well for labels
|
||||
and backup metadata.
|
||||
|
||||
### Copyright
|
||||
|
||||
This BIP is licensed under the BSD 2-Clause License.
|
||||
Redistribution and use in source and binary forms, with or without modification, are
|
||||
permitted provided that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
### Motivation
|
||||
|
||||
Losing the **wallet descriptor** (or **wallet policy**) is just as catastrophic as
|
||||
losing the seed itself. The seed lets you sign, but the descriptor maps you to your coins.
|
||||
For multisig or miniscript wallets, keys alone won't help: without the descriptor, you
|
||||
can't reconstruct the script.
|
||||
|
||||
Offline storage of descriptors has two practical obstacles:
|
||||
|
||||
1. **Descriptors are hard to store offline.**
|
||||
Descriptors can be much longer than a 12/24-word seed. Paper and steel backups
|
||||
become impractical or error-prone.
|
||||
|
||||
2. **Online redundancy carries privacy risk.**
|
||||
USB drives, phones, and cloud storage solve the length problem but expose your
|
||||
wallet structure. Plaintext descriptors leak your pubkeys and script details.
|
||||
Cloud storage is often unencrypted, and even cloud encryption could be compromised,
|
||||
depending on (often opaque) implementation details. Its security also reduces to
|
||||
that of the weakest device with cloud access. Each copy increases the attack surface.
|
||||
|
||||
This BIP therefore proposes an **encrypted**, compact backup format that:
|
||||
|
||||
* can be **safely stored in multiple places**, including untrusted online services,
|
||||
* can be **decrypted only by intended holders** of specified public keys,
|
||||
|
||||
See the original [Delving post](https://delvingbitcoin.org/t/a-simple-backup-scheme-for-wallet-accounts/1607/31)
|
||||
for more background.
|
||||
|
||||
### Expected properties
|
||||
|
||||
* **Encrypted**: safe to store with untrusted cloud providers or backup services
|
||||
* **Access controlled**: only designated cosigners can decrypt
|
||||
* **Easy to implement**: it should not require any sophisticated tools/libraries.
|
||||
* **Vendor-neutral**: works with any hardware signer
|
||||
|
||||
### Scope
|
||||
|
||||
This proposal targets output script descriptors (BIP-0380) and policies (BIP-0388), but the
|
||||
scheme also works for labels (BIP-0329) and other wallet metadata like
|
||||
[wallet backup metadata](https://github.com/bitcoin/bips/pull/2130).
|
||||
|
||||
Private key material MUST be removed before encrypting any payload.
|
||||
|
||||
## Specification
|
||||
|
||||
Note: in the followings sections, the operator ⊕ refers to the bitwise XOR operation.
|
||||
|
||||
### Secret generation
|
||||
|
||||
- Let $p_1, p_2, \dots, p_n$, be the public keys in the descriptor/wallet policy, in
|
||||
increasing lexicographical order. The scheme is defined for any $n \geq 1$,
|
||||
in particular it supports single-signature descriptors ($n = 1$). Each $p_i$
|
||||
is the x-only-normalized root public key of one *allowed* key expression
|
||||
(see [Descriptor key requirements](#descriptor-key-requirements)).
|
||||
- Let $s$ = sha256(sha256("BIPXXX_DECRYPTION_SECRET") | sha256("BIPXXX_DECRYPTION_SECRET") | $p_1$ | $p_2$ | ... | $p_n$)
|
||||
- Let $s_i$ = sha256(sha256("BIPXXX_INDIVIDUAL_SECRET") | sha256("BIPXXX_INDIVIDUAL_SECRET") | $p_i$)
|
||||
- Let $c_i$ = $s$ ⊕ $s_i$
|
||||
|
||||
Because $s$ and $s_i$ use distinct domain-separation tags, $s \neq s_i$ and
|
||||
therefore $c_i$ is never the all-zero string.
|
||||
|
||||
**Note:** To prevent attackers from decrypting the backup using publicly known
|
||||
keys, explicitly exclude any public keys with x coordinate
|
||||
`50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0` (the BIP341 NUMS
|
||||
point, used as a taproot internal key in some applications). Additionally, exclude any
|
||||
other publicly known keys.
|
||||
|
||||
Applications that exclude additional keys SHOULD document this, although decryption
|
||||
using these keys will simply fail. This does not affect decryption with the remaining
|
||||
keys.
|
||||
|
||||
### Descriptor key requirements
|
||||
|
||||
Only key expressions of the extended-public-key type with a trailing
|
||||
derivation step or wildcard contribute to $\{p_1, \dots, p_n\}$. Without
|
||||
that derivation, the xpub's root pubkey, used to seed $s$, would also be
|
||||
the on-chain pubkey of every spend, so observing one spend would let
|
||||
anyone recompute $s$ and decrypt the backup.[^trailing-derivation] The
|
||||
rule generalizes to any network prefix (`xpub`/`tpub`/`Vpub`/...).
|
||||
|
||||
[^trailing-derivation]: **Why require trailing derivation?**
|
||||
Any trailing derivation step, or the implicit child derivation forced by
|
||||
a wildcard, breaks the identity between the xpub root pubkey and the
|
||||
on-chain pubkey. Fixed-derivation expressions like `xpub.../0/5` are
|
||||
allowed because the on-chain key (`xpub/0/5`) already differs from the
|
||||
encryption seed (the xpub root). Literal pubkeys and bare xpubs are
|
||||
disallowed for the same reason: the literal value is exactly what goes
|
||||
on-chain, so $s$ would become recoverable from a single observed spend.
|
||||
|
||||
Allowed forms (origin information `[...]` is optional and orthogonal):
|
||||
|
||||
| Form | Example |
|
||||
|-------------------------------------------------------------|-------------------|
|
||||
| `<xpub>/<path>` (fixed derivation, no wildcard) | `xpub.../0/5` |
|
||||
| `<xpub>/*` (wildcard only) | `xpub.../*` |
|
||||
| `<xpub>/<path>/*` (fixed derivation followed by a wildcard) | `xpub.../0/*` |
|
||||
| `<xpub>/<a;b;...>` (multipath, no wildcard) | `xpub.../<0;1>` |
|
||||
| `<xpub>/<a;b;...>/*` (multipath followed by a wildcard) | `xpub.../<0;1>/*` |
|
||||
|
||||
Implementations:
|
||||
|
||||
- MUST exclude every other form (literal pubkeys, bare xpubs, ...) from
|
||||
$\{p_1, \dots, p_n\}$.
|
||||
- MUST refuse to encode a backup if the resulting set is empty.
|
||||
- SHOULD make the user aware of each excluded expression, since the
|
||||
cosigner holding that key will be unable to decrypt the backup with
|
||||
their key.
|
||||
|
||||
### Key Normalization
|
||||
|
||||
For each allowed expression, take the root extended public key (ignoring
|
||||
origin information, the trailing derivation path, the wildcard, and any
|
||||
multipath specifiers) and extract its x-coordinate. The result is the
|
||||
32-byte **x-only public key** $p_i$.[^x-only]
|
||||
|
||||
[^x-only]: **Why x-only keys?**
|
||||
X-only public keys are 32 bytes, a natural size for cryptographic operations.
|
||||
This format is also used in BIP340 (Schnorr signatures) and BIP341 (Taproot).
|
||||
|
||||
### Encryption
|
||||
|
||||
The format uses CHACHA20_POLY1305 (RFC 8439) as the encryption algorithm,
|
||||
with a 96-bit random nonce and a 128-bit authentication tag to provide confidentiality
|
||||
and integrity.
|
||||
|
||||
[^chacha-default]: **Why CHACHA20-POLY1305 ?**
|
||||
ChaCha20-Poly1305 is already used in Bitcoin Core (e.g., BIP324) and is widely
|
||||
available in cryptographic libraries. It performs well in software without
|
||||
hardware acceleration, making it suitable for hardware wallets and embedded devices.
|
||||
|
||||
* let $nonce$ = random(96 bits)
|
||||
* let $ciphertext$ = encrypt($payload$, $secret$, $nonce$)
|
||||
|
||||
### Decryption
|
||||
|
||||
In order to decrypt the payload of a backup, the owner of a certain public key p
|
||||
computes:
|
||||
|
||||
* let $s_i$ = sha256(sha256("BIPXXX_INDIVIDUAL_SECRET") ‖ sha256("BIPXXX_INDIVIDUAL_SECRET") ‖ $p$)
|
||||
* for each `individual_secret_i` generate `reconstructed_secret_i` =
|
||||
`individual_secret_i` ⊕ `si`
|
||||
* for each `reconstructed_secret_i` process $payload$ =
|
||||
decrypt($ciphertext$, $secret$, $nonce$)
|
||||
|
||||
Decryption will succeed if and only if **p** was one of the keys in the
|
||||
descriptor/wallet policy.
|
||||
|
||||
### Encoding
|
||||
|
||||
The encrypted backup must be encoded as follows:
|
||||
|
||||
`MAGIC` `VERSION` `DERIVATION_PATHS` `INDIVIDUAL_SECRETS` `ENCRYPTION`
|
||||
`ENCRYPTED_PAYLOAD`
|
||||
|
||||
#### Magic
|
||||
|
||||
`MAGIC`: 6 bytes which are ASCII/UTF-8 representation of **BIPXXX** (TBD).
|
||||
|
||||
#### Version
|
||||
|
||||
`VERSION`: 1 byte unsigned integer representing the format version. The current
|
||||
specification defines version `0x01`.
|
||||
|
||||
#### Derivation Paths
|
||||
|
||||
Note: the derivation-path vector should not contain duplicates.
|
||||
Derivation paths are optional; they can be useful to simplify the recovery process
|
||||
if one has used a non-common derivation path to derive his key.[^derivation-optional]
|
||||
|
||||
[^derivation-optional]: **Why are derivation paths optional?**
|
||||
When standard derivation paths are used, they are easily discoverable, making
|
||||
them straightforward to brute-force. Omitting them enhances privacy by reducing
|
||||
the information shared publicly about the descriptor scheme.
|
||||
|
||||
`DERIVATION_PATH` follows this format:
|
||||
|
||||
`COUNT`
|
||||
`CHILD_COUNT` `CHILD` `...` `CHILD`
|
||||
`...`
|
||||
`CHILD_COUNT` `CHILD` `...` `CHILD`
|
||||
|
||||
`COUNT`: 1-byte unsigned integer (0–255) indicating how many derivation paths are
|
||||
included.
|
||||
`CHILD_COUNT`: 1-byte unsigned integer (1–255) indicating how many children are in
|
||||
the current path.
|
||||
`CHILD`: 4-byte big-endian unsigned integer representing a child index per BIP-32.
|
||||
|
||||
#### Individual Secrets
|
||||
|
||||
At least one individual secret must be supplied.[^no-fingerprints]
|
||||
|
||||
[^no-fingerprints]: **Why no fingerprints in plaintext encoding?**
|
||||
Including fingerprints would leak direct information about the descriptor
|
||||
participants, which compromises privacy.
|
||||
|
||||
The `INDIVIDUAL_SECRETS` section follows this format:
|
||||
|
||||
`COUNT`
|
||||
`INDIVIDUAL_SECRET`
|
||||
`INDIVIDUAL_SECRET`
|
||||
|
||||
`COUNT`: 1-byte unsigned integer (1–255) indicating how many secrets are included.
|
||||
`INDIVIDUAL_SECRET`: 32-byte serialization of the derived individual secret.
|
||||
|
||||
Note: the individual secrets vector should not contain duplicates. Implementations
|
||||
MAY deduplicate secrets during encoding or parsing.
|
||||
|
||||
#### Encryption
|
||||
|
||||
`ENCRYPTION`: 1-byte unsigned integer identifying the encryption algorithm.
|
||||
|
||||
| Value | Definition |
|
||||
|:-------|:---------------------------------------|
|
||||
| 0x00 | Reserved |
|
||||
| 0x01 | CHACHA20_POLY1305 |
|
||||
|
||||
#### Payload Size Limits
|
||||
|
||||
CHACHA20_POLY1305 (per RFC 8439) supports plaintext up to 2^38 - 64 bytes.
|
||||
Implementations MAY impose stricter limits based on platform constraints
|
||||
(e.g., limiting to 2^32 - 1 bytes on 32-bit architectures).
|
||||
|
||||
Implementations MUST reject empty payloads.
|
||||
|
||||
#### Ciphertext
|
||||
|
||||
`CIPHERTEXT` is the encrypted data resulting from encryption of `PAYLOAD` with algorithm
|
||||
defined in `ENCRYPTION` where `PAYLOAD` is encoded following this format:
|
||||
|
||||
`CONTENT` `PLAINTEXT`
|
||||
|
||||
#### Integer Encodings
|
||||
|
||||
All variable-length integers are encoded as
|
||||
[compact size](https://en.bitcoin.it/wiki/Protocol_documentation#Variable_length_integer).
|
||||
|
||||
#### 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`, parsers MUST stop parsing
|
||||
`CONTENT`.[^type-upgrade]
|
||||
|
||||
[^type-upgrade]: **Why the 0x80 threshold?**
|
||||
The `TYPE >= 0x80` rule means we're not stuck with the current TLV encoding.
|
||||
It has a nice upgrade property: you can still encode backward compatible stuff
|
||||
at the start.
|
||||
|
||||
#### Encrypted Payload
|
||||
|
||||
`ENCRYPTED_PAYLOAD` follows this format:
|
||||
|
||||
`NONCE` `LENGTH` `CIPHERTEXT`
|
||||
|
||||
`NONCE`: 12-byte (96-bit) nonce.
|
||||
`LENGTH`: variable-length integer representing ciphertext length.
|
||||
`CIPHERTEXT`: variable-length ciphertext.
|
||||
|
||||
Note: `CIPHERTEXT` is followed by the end of the `ENCRYPTED_PAYLOAD` section.
|
||||
Compliant parsers MUST stop reading after consuming `LENGTH` bytes of ciphertext;
|
||||
additional trailing bytes are reserved for vendor-specific extensions and MUST
|
||||
be ignored.
|
||||
|
||||
### 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.
|
||||
|
||||
## Rationale
|
||||
|
||||
See footnotes throughout the specification for design rationale.
|
||||
|
||||
### Future Extensions
|
||||
|
||||
The version field enables possible future enhancements:
|
||||
|
||||
- Additional encryption algorithms
|
||||
- Support for threshold-based decryption
|
||||
- Hiding number of participants
|
||||
- bech32m export
|
||||
|
||||
### Implementation
|
||||
|
||||
- Rust [implementation](https://github.com/pythcoiner/bitcoin-encrypted-backup)
|
||||
|
||||
### Test Vectors
|
||||
|
||||
[key_types.json](./bip-encrypted-backup/test_vectors/keys_types.json) contains test
|
||||
vectors for key serialisations.
|
||||
[content_type.json](./bip-encrypted-backup/test_vectors/content_type.json) contains test
|
||||
vectors for contents types serialisations.
|
||||
[derivation_path.json](./bip-encrypted-backup/test_vectors/derivation_path.json) contains
|
||||
test vectors for derivation paths serialisations.
|
||||
[individual_secrets.json](./bip-encrypted-backup/test_vectors/individual_secrets.json)
|
||||
contains test vectors for individual secrets serialization.
|
||||
[encryption_secret.json](./bip-encrypted-backup/test_vectors/encryption_secret.json)
|
||||
contains test vectors for generation of encryption secret.
|
||||
[chacha20poly1305_encryption.json](./bip-encrypted-backup/test_vectors/chacha20poly1305_encryption.json)
|
||||
contains test vectors for ciphertexts generated using CHACHA20-POLY1305.
|
||||
[encrypted_backup.json](./bip-encrypted-backup/test_vectors/encrypted_backup.json)
|
||||
contains test vectors for generation of complete encrypted backup.
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
// TBD
|
||||
@@ -0,0 +1,37 @@
|
||||
[
|
||||
{
|
||||
"description": "Basic encryption with short plaintext",
|
||||
"nonce": "000102030405060708090a0b",
|
||||
"plaintext": "48656c6c6f",
|
||||
"secret": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"ciphertext": "7df9cb9a0ac5851cc054b14d05f781127b2b0d31fa"
|
||||
},
|
||||
{
|
||||
"description": "Empty plaintext should fail",
|
||||
"nonce": "000102030405060708090a0b",
|
||||
"plaintext": "",
|
||||
"secret": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"ciphertext": null
|
||||
},
|
||||
{
|
||||
"description": "Encryption with zeroed nonce should fail",
|
||||
"nonce": "000000000000000000000000",
|
||||
"plaintext": "00000000000000000000000000000000",
|
||||
"secret": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"ciphertext": null
|
||||
},
|
||||
{
|
||||
"description": "Encryption with all FFs",
|
||||
"nonce": "ffffffffffffffffffffffff",
|
||||
"plaintext": "ffffffffffffffffffffffffffffffff",
|
||||
"secret": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
"ciphertext": "22d8bfc313e141bd692c82cec7785b29a0e5d5014c0d3b2d3a8b00548cd8d221"
|
||||
},
|
||||
{
|
||||
"description": "Longer plaintext",
|
||||
"nonce": "0f1e2d3c4b5a69788796a5b4",
|
||||
"plaintext": "546869732069732061206c6f6e67657220706c61696e746578742074686174207368756c6420626520656e637279707465642070726f7065726c792e",
|
||||
"secret": "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef",
|
||||
"ciphertext": "2af094190e2b43a02b8dd6bfc25a8833f84f81bc6f690d75f0214e466ef392616c4644bee65118c444a926e1e365b3a7ba0509a5636524eb4e5722f5926938f32e4df79237acb6dd4a6ccbc4"
|
||||
}
|
||||
]
|
||||
67
bip-encrypted-backup/test_vectors/content_type.json
Normal file
67
bip-encrypted-backup/test_vectors/content_type.json
Normal file
@@ -0,0 +1,67 @@
|
||||
[
|
||||
{
|
||||
"description": "Bip 380",
|
||||
"valid": true,
|
||||
"content": "01017c"
|
||||
},
|
||||
{
|
||||
"description": "Bip 388",
|
||||
"valid": true,
|
||||
"content": "010184"
|
||||
},
|
||||
{
|
||||
"description": "Bip 329",
|
||||
"valid": true,
|
||||
"content": "010149"
|
||||
},
|
||||
{
|
||||
"description": "Bip 999",
|
||||
"valid": true,
|
||||
"content": "0103e7"
|
||||
},
|
||||
{
|
||||
"description": "Bip max",
|
||||
"valid": true,
|
||||
"content": "01ffff"
|
||||
},
|
||||
{
|
||||
"description": "Bip min",
|
||||
"valid": true,
|
||||
"content": "010000"
|
||||
},
|
||||
{
|
||||
"description": "Propietary 00010203",
|
||||
"valid": true,
|
||||
"content": "020400010203"
|
||||
},
|
||||
{
|
||||
"description": "TYPE 0x00 is reserved",
|
||||
"valid": false,
|
||||
"content": "00"
|
||||
},
|
||||
{
|
||||
"description": "Invalid BIP (insufficient bytes)",
|
||||
"valid": false,
|
||||
"content": "0100"
|
||||
},
|
||||
{
|
||||
"description": "Invalid proprietary (missing data)",
|
||||
"valid": false,
|
||||
"content": "0201"
|
||||
},
|
||||
{
|
||||
"description": "Invalid proprietary (LENGTH exceeds payload)",
|
||||
"valid": false,
|
||||
"content": "020500"
|
||||
},
|
||||
{
|
||||
"description": "TYPE >= 0x80 stops parsing",
|
||||
"valid": false,
|
||||
"content": "ff"
|
||||
},
|
||||
{
|
||||
"description": "TYPE >= 0x80 stops parsing",
|
||||
"valid": false,
|
||||
"content": "ff000000"
|
||||
}
|
||||
]
|
||||
146
bip-encrypted-backup/test_vectors/derivation_path.json
Normal file
146
bip-encrypted-backup/test_vectors/derivation_path.json
Normal file
@@ -0,0 +1,146 @@
|
||||
[
|
||||
{
|
||||
"description": "Empty derivation paths",
|
||||
"paths": [],
|
||||
"expected": "00"
|
||||
},
|
||||
{
|
||||
"description": "Single path with one child: m/0",
|
||||
"paths": ["m/0"],
|
||||
"expected": "010100000000"
|
||||
},
|
||||
{
|
||||
"description": "Single path with hardened child: m/44'",
|
||||
"paths": ["m/44'"],
|
||||
"expected": "01018000002c"
|
||||
},
|
||||
{
|
||||
"description": "Standard BIP-84 path: m/84'/0'/0'",
|
||||
"paths": ["m/84'/0'/0'"],
|
||||
"expected": "0103800000548000000080000000"
|
||||
},
|
||||
{
|
||||
"description": "Mixed hardened and normal: m/0/1'/2/3'",
|
||||
"paths": ["m/0/1'/2/3'"],
|
||||
"expected": "010400000000800000010000000280000003"
|
||||
},
|
||||
{
|
||||
"description": "Multiple paths: m/0/1'/2/3' and m/84'/0'/0'/2'",
|
||||
"paths": ["m/0/1'/2/3'", "m/84'/0'/0'/2'"],
|
||||
"expected": "0204000000008000000100000002800000030480000054800000008000000080000002"
|
||||
},
|
||||
{
|
||||
"description": "Path with large indices: m/2147483647'/2147483646",
|
||||
"paths": ["m/2147483647'/2147483646"],
|
||||
"expected": "0102ffffffff7ffffffe"
|
||||
},
|
||||
{
|
||||
"description": "Single child path: m/1",
|
||||
"paths": ["m/1"],
|
||||
"expected": "010100000001"
|
||||
},
|
||||
{
|
||||
"description": "Path with max normal index: m/2147483647",
|
||||
"paths": ["m/2147483647"],
|
||||
"expected": "01017fffffff"
|
||||
},
|
||||
{
|
||||
"description": "Path with multiple normal indices: m/0/1/2/3/4",
|
||||
"paths": ["m/0/1/2/3/4"],
|
||||
"expected": "01050000000000000001000000020000000300000004"
|
||||
},
|
||||
{
|
||||
"description": "Path with all hardened: m/0'/1'/2'",
|
||||
"paths": ["m/0'/1'/2'"],
|
||||
"expected": "0103800000008000000180000002"
|
||||
},
|
||||
{
|
||||
"description": "Two different single-child paths: m/0 and m/1",
|
||||
"paths": ["m/0", "m/1"],
|
||||
"expected": "0201000000000100000001"
|
||||
},
|
||||
{
|
||||
"description": "BIP-44 account 0: m/44'/0'/0'",
|
||||
"paths": ["m/44'/0'/0'"],
|
||||
"expected": "01038000002c8000000080000000"
|
||||
},
|
||||
{
|
||||
"description": "BIP-49 account 0: m/49'/0'/0'",
|
||||
"paths": ["m/49'/0'/0'"],
|
||||
"expected": "0103800000318000000080000000"
|
||||
},
|
||||
{
|
||||
"description": "Single path with 255 children (maximum depth, success)",
|
||||
"paths": ["m/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0"],
|
||||
"expected": "01ff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
{
|
||||
"description": "256 paths should fail (exceeds u8::MAX)",
|
||||
"paths": [
|
||||
"m/0", "m/1", "m/2", "m/3", "m/4", "m/5", "m/6", "m/7", "m/8", "m/9",
|
||||
"m/10", "m/11", "m/12", "m/13", "m/14", "m/15", "m/16", "m/17", "m/18", "m/19",
|
||||
"m/20", "m/21", "m/22", "m/23", "m/24", "m/25", "m/26", "m/27", "m/28", "m/29",
|
||||
"m/30", "m/31", "m/32", "m/33", "m/34", "m/35", "m/36", "m/37", "m/38", "m/39",
|
||||
"m/40", "m/41", "m/42", "m/43", "m/44", "m/45", "m/46", "m/47", "m/48", "m/49",
|
||||
"m/50", "m/51", "m/52", "m/53", "m/54", "m/55", "m/56", "m/57", "m/58", "m/59",
|
||||
"m/60", "m/61", "m/62", "m/63", "m/64", "m/65", "m/66", "m/67", "m/68", "m/69",
|
||||
"m/70", "m/71", "m/72", "m/73", "m/74", "m/75", "m/76", "m/77", "m/78", "m/79",
|
||||
"m/80", "m/81", "m/82", "m/83", "m/84", "m/85", "m/86", "m/87", "m/88", "m/89",
|
||||
"m/90", "m/91", "m/92", "m/93", "m/94", "m/95", "m/96", "m/97", "m/98", "m/99",
|
||||
"m/100", "m/101", "m/102", "m/103", "m/104", "m/105", "m/106", "m/107", "m/108", "m/109",
|
||||
"m/110", "m/111", "m/112", "m/113", "m/114", "m/115", "m/116", "m/117", "m/118", "m/119",
|
||||
"m/120", "m/121", "m/122", "m/123", "m/124", "m/125", "m/126", "m/127", "m/128", "m/129",
|
||||
"m/130", "m/131", "m/132", "m/133", "m/134", "m/135", "m/136", "m/137", "m/138", "m/139",
|
||||
"m/140", "m/141", "m/142", "m/143", "m/144", "m/145", "m/146", "m/147", "m/148", "m/149",
|
||||
"m/150", "m/151", "m/152", "m/153", "m/154", "m/155", "m/156", "m/157", "m/158", "m/159",
|
||||
"m/160", "m/161", "m/162", "m/163", "m/164", "m/165", "m/166", "m/167", "m/168", "m/169",
|
||||
"m/170", "m/171", "m/172", "m/173", "m/174", "m/175", "m/176", "m/177", "m/178", "m/179",
|
||||
"m/180", "m/181", "m/182", "m/183", "m/184", "m/185", "m/186", "m/187", "m/188", "m/189",
|
||||
"m/190", "m/191", "m/192", "m/193", "m/194", "m/195", "m/196", "m/197", "m/198", "m/199",
|
||||
"m/200", "m/201", "m/202", "m/203", "m/204", "m/205", "m/206", "m/207", "m/208", "m/209",
|
||||
"m/210", "m/211", "m/212", "m/213", "m/214", "m/215", "m/216", "m/217", "m/218", "m/219",
|
||||
"m/220", "m/221", "m/222", "m/223", "m/224", "m/225", "m/226", "m/227", "m/228", "m/229",
|
||||
"m/230", "m/231", "m/232", "m/233", "m/234", "m/235", "m/236", "m/237", "m/238", "m/239",
|
||||
"m/240", "m/241", "m/242", "m/243", "m/244", "m/245", "m/246", "m/247", "m/248", "m/249",
|
||||
"m/250", "m/251", "m/252", "m/253", "m/254", "m/255"
|
||||
],
|
||||
"expected": null
|
||||
},
|
||||
{
|
||||
"description": "Path with 256 children should fail (exceeds u8::MAX)",
|
||||
"paths": ["m/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0"],
|
||||
"expected": null
|
||||
},
|
||||
{
|
||||
"description": "255 paths should succeed (maximum allowed)",
|
||||
"paths": [
|
||||
"m/0", "m/1", "m/2", "m/3", "m/4", "m/5", "m/6", "m/7", "m/8", "m/9",
|
||||
"m/10", "m/11", "m/12", "m/13", "m/14", "m/15", "m/16", "m/17", "m/18", "m/19",
|
||||
"m/20", "m/21", "m/22", "m/23", "m/24", "m/25", "m/26", "m/27", "m/28", "m/29",
|
||||
"m/30", "m/31", "m/32", "m/33", "m/34", "m/35", "m/36", "m/37", "m/38", "m/39",
|
||||
"m/40", "m/41", "m/42", "m/43", "m/44", "m/45", "m/46", "m/47", "m/48", "m/49",
|
||||
"m/50", "m/51", "m/52", "m/53", "m/54", "m/55", "m/56", "m/57", "m/58", "m/59",
|
||||
"m/60", "m/61", "m/62", "m/63", "m/64", "m/65", "m/66", "m/67", "m/68", "m/69",
|
||||
"m/70", "m/71", "m/72", "m/73", "m/74", "m/75", "m/76", "m/77", "m/78", "m/79",
|
||||
"m/80", "m/81", "m/82", "m/83", "m/84", "m/85", "m/86", "m/87", "m/88", "m/89",
|
||||
"m/90", "m/91", "m/92", "m/93", "m/94", "m/95", "m/96", "m/97", "m/98", "m/99",
|
||||
"m/100", "m/101", "m/102", "m/103", "m/104", "m/105", "m/106", "m/107", "m/108", "m/109",
|
||||
"m/110", "m/111", "m/112", "m/113", "m/114", "m/115", "m/116", "m/117", "m/118", "m/119",
|
||||
"m/120", "m/121", "m/122", "m/123", "m/124", "m/125", "m/126", "m/127", "m/128", "m/129",
|
||||
"m/130", "m/131", "m/132", "m/133", "m/134", "m/135", "m/136", "m/137", "m/138", "m/139",
|
||||
"m/140", "m/141", "m/142", "m/143", "m/144", "m/145", "m/146", "m/147", "m/148", "m/149",
|
||||
"m/150", "m/151", "m/152", "m/153", "m/154", "m/155", "m/156", "m/157", "m/158", "m/159",
|
||||
"m/160", "m/161", "m/162", "m/163", "m/164", "m/165", "m/166", "m/167", "m/168", "m/169",
|
||||
"m/170", "m/171", "m/172", "m/173", "m/174", "m/175", "m/176", "m/177", "m/178", "m/179",
|
||||
"m/180", "m/181", "m/182", "m/183", "m/184", "m/185", "m/186", "m/187", "m/188", "m/189",
|
||||
"m/190", "m/191", "m/192", "m/193", "m/194", "m/195", "m/196", "m/197", "m/198", "m/199",
|
||||
"m/200", "m/201", "m/202", "m/203", "m/204", "m/205", "m/206", "m/207", "m/208", "m/209",
|
||||
"m/210", "m/211", "m/212", "m/213", "m/214", "m/215", "m/216", "m/217", "m/218", "m/219",
|
||||
"m/220", "m/221", "m/222", "m/223", "m/224", "m/225", "m/226", "m/227", "m/228", "m/229",
|
||||
"m/230", "m/231", "m/232", "m/233", "m/234", "m/235", "m/236", "m/237", "m/238", "m/239",
|
||||
"m/240", "m/241", "m/242", "m/243", "m/244", "m/245", "m/246", "m/247", "m/248", "m/249",
|
||||
"m/250", "m/251", "m/252", "m/253", "m/254"
|
||||
],
|
||||
"expected": "ff0100000000010000000101000000020100000003010000000401000000050100000006010000000701000000080100000009010000000a010000000b010000000c010000000d010000000e010000000f0100000010010000001101000000120100000013010000001401000000150100000016010000001701000000180100000019010000001a010000001b010000001c010000001d010000001e010000001f0100000020010000002101000000220100000023010000002401000000250100000026010000002701000000280100000029010000002a010000002b010000002c010000002d010000002e010000002f0100000030010000003101000000320100000033010000003401000000350100000036010000003701000000380100000039010000003a010000003b010000003c010000003d010000003e010000003f0100000040010000004101000000420100000043010000004401000000450100000046010000004701000000480100000049010000004a010000004b010000004c010000004d010000004e010000004f0100000050010000005101000000520100000053010000005401000000550100000056010000005701000000580100000059010000005a010000005b010000005c010000005d010000005e010000005f0100000060010000006101000000620100000063010000006401000000650100000066010000006701000000680100000069010000006a010000006b010000006c010000006d010000006e010000006f0100000070010000007101000000720100000073010000007401000000750100000076010000007701000000780100000079010000007a010000007b010000007c010000007d010000007e010000007f0100000080010000008101000000820100000083010000008401000000850100000086010000008701000000880100000089010000008a010000008b010000008c010000008d010000008e010000008f0100000090010000009101000000920100000093010000009401000000950100000096010000009701000000980100000099010000009a010000009b010000009c010000009d010000009e010000009f01000000a001000000a101000000a201000000a301000000a401000000a501000000a601000000a701000000a801000000a901000000aa01000000ab01000000ac01000000ad01000000ae01000000af01000000b001000000b101000000b201000000b301000000b401000000b501000000b601000000b701000000b801000000b901000000ba01000000bb01000000bc01000000bd01000000be01000000bf01000000c001000000c101000000c201000000c301000000c401000000c501000000c601000000c701000000c801000000c901000000ca01000000cb01000000cc01000000cd01000000ce01000000cf01000000d001000000d101000000d201000000d301000000d401000000d501000000d601000000d701000000d801000000d901000000da01000000db01000000dc01000000dd01000000de01000000df01000000e001000000e101000000e201000000e301000000e401000000e501000000e601000000e701000000e801000000e901000000ea01000000eb01000000ec01000000ed01000000ee01000000ef01000000f001000000f101000000f201000000f301000000f401000000f501000000f601000000f701000000f801000000f901000000fa01000000fb01000000fc01000000fd01000000fe"
|
||||
}
|
||||
]
|
||||
67
bip-encrypted-backup/test_vectors/encrypted_backup.json
Normal file
67
bip-encrypted-backup/test_vectors/encrypted_backup.json
Normal file
@@ -0,0 +1,67 @@
|
||||
[
|
||||
{
|
||||
"description": "Single key, no derivation paths, BIP380 content",
|
||||
"version": 1,
|
||||
"encryption": 1,
|
||||
"content": "01017c",
|
||||
"keys": [
|
||||
"02e6642fd69bd211f93f7f1f36ca51a26a5290eb2dd1b0d8279a87bb0d480c8443"
|
||||
],
|
||||
"derivation_paths": [],
|
||||
"plaintext": "00",
|
||||
"nonce": "a1b2c3d4e5f607080910a1b2",
|
||||
"expected": "424950585858010001ff34b3411f78127b71ca2e3cc60d0fd71350ee557c37d71f4d81fb913461ae0001a1b2c3d4e5f607080910a1b2151d8f44dba6f420976b9343f792b4bd58c06289d234",
|
||||
"trailing": "deadbeef00ff",
|
||||
"expected_base64": "QklQWFhYAQAB/zSzQR94Entxyi48xg0P1xNQ7lV8N9cfTYH7kTRhrgABobLD1OX2BwgJEKGyFR2PRNum9CCXa5ND95K0vVjAYonSNA=="
|
||||
},
|
||||
{
|
||||
"description": "Two keys, 1 derivation paths, BIP380 content",
|
||||
"version": 1,
|
||||
"encryption": 1,
|
||||
"content": "01017c",
|
||||
"keys": [
|
||||
"02e6642fd69bd211f93f7f1f36ca51a26a5290eb2dd1b0d8279a87bb0d480c8443",
|
||||
"0384526253c27c7aef56c7b71a5cd25bebb66dddda437826defc5b2568bde81f07"
|
||||
],
|
||||
"derivation_paths": [
|
||||
"m/48'/1'/0'/2'"
|
||||
],
|
||||
"plaintext": "wsh(or_d(pk([9d69155f/48'/1'/0'/2']tpubDDxT9mkZzWwkKwpGT5fY6iiM9muYTPkTx6Eig8dpHR7TChuGGCWYAHVmpW1ciido5RiFWwjzYsF1GZHkEHg2nrYp3zNtx3QQRkznyLhQ77x/<0;1>/*),and_v(v:pkh([9d69155f/48'/1'/0'/2']tpubDDxT9mkZzWwkKwpGT5fY6iiM9muYTPkTx6Eig8dpHR7TChuGGCWYAHVmpW1ciido5RiFWwjzYsF1GZHkEHg2nrYp3zNtx3QQRkznyLhQ77x/<2;3>/*),older(52596))))#gx5f42wh",
|
||||
"nonce": "0102030405060708090a0b0c",
|
||||
"expected": "42495058585801010480000030800000018000000080000002024900d4ef9021cb059b8fb35c6de9b6db91949a328527ede0645be237899100bd5e3eb8a36f7bf32e02810c14666476f2b28a15cd499c30f8f98e926639a0765c010102030405060708090a0b0cfd63012f51db36ae620d6522a86e4ce7d9daff2f50826aae70c1d3707d18b8075543da1848ad904b11be465e768d8b1ea74a1b21f21f882262bd0d5f7165991720c1836f1bce2dec7ba3813fc1c0bc6404a0fd6228e239f8bddd398c32f8274f9de0f0b5662854ce900d7d5b14a16605eb2a49d031b98513b73777685693b45b17e08a60e095b66403efcc7036cd82a8d675362eab43bcdecb158e8b0dcca476173345d189c2277dc25b9851b2be92c7ef8b69a565af1ccf9726e322db2b8d5266a5df4296527c716b8ba004fb1408cbd7cc7a18575286e6f03e1793b25eea11223fd6cc7a497d8328997b1eb770fcc8125e60511eefb8232b780d80f1d71e9e937627dfb62cd6c5807b35e7d7bb9aaf18d5a46c6ea271f2be26bd1cc35bb2b70cc1930ad5f472b1bf0d7b3bed3dfe358a69beabdafd6316968c530237f21e1c89662ada34d666735f791db5eb68ee29d2d06f42421ec311d6284f5be9850d63e0cfd6cfe207",
|
||||
"expected_base64": "QklQWFhYAQEEgAAAMIAAAAGAAAAAgAAAAgJJANTvkCHLBZuPs1xt6bbbkZSaMoUn7eBkW+I3iZEAvV4+uKNve/MuAoEMFGZkdvKyihXNSZww+PmOkmY5oHZcAQECAwQFBgcICQoLDP1jAS9R2zauYg1lIqhuTOfZ2v8vUIJqrnDB03B9GLgHVUPaGEitkEsRvkZedo2LHqdKGyHyH4giYr0NX3FlmRcgwYNvG84t7HujgT/BwLxkBKD9YijiOfi93TmMMvgnT53g8LVmKFTOkA19WxShZgXrKknQMbmFE7c3d2hWk7RbF+CKYOCVtmQD78xwNs2CqNZ1Ni6rQ7zeyxWOiw3MpHYXM0XRicInfcJbmFGyvpLH74tppWWvHM+XJuMi2yuNUmal30KWUnxxa4ugBPsUCMvXzHoYV1KG5vA+F5OyXuoRIj/WzHpJfYMomXset3D8yBJeYFEe77gjK3gNgPHXHp6TdifftizWxYB7NefXu5qvGNWkbG6icfK+Jr0cw1uytwzBkwrV9HKxvw17O+09/jWKab6r2v1jFpaMUwI38h4ciWYq2jTWZnNfeR2162juKdLQb0JCHsMR1ihPW+mFDWPgz9bP4gc="
|
||||
},
|
||||
{
|
||||
"description": "Three keys, multiple derivation paths, BIP329 content",
|
||||
"version": 1,
|
||||
"encryption": 1,
|
||||
"content": "010149",
|
||||
"keys": [
|
||||
"02e6642fd69bd211f93f7f1f36ca51a26a5290eb2dd1b0d8279a87bb0d480c8443",
|
||||
"0384526253c27c7aef56c7b71a5cd25bebb66dddda437826defc5b2568bde81f07",
|
||||
"03c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5"
|
||||
],
|
||||
"derivation_paths": [
|
||||
"m/84'/0'/0'",
|
||||
"m/0/1'/2/3'"
|
||||
],
|
||||
"plaintext": "{\"type\":\"tx\",\"ref\":\"f91d0a8a78462bc59398f2c5d7a84fcff491c26ba54c4833478b202796c8aafd\",\"label\":\"Transaction\",\"origin\":\"wpkh([d34db33f/84'/0'/0'])\"}\n{\"type\":\"addr\",\"ref\":\"bc1q34aq5drpuwy3wgl9lhup9892qp6svr8ldzyy7c\",\"label\":\"Address\"}\n{\"type\":\"pubkey\",\"ref\":\"0283409659355b6d1cc3c32decd5d561abaac86c37a353b52895a5e6c196d6f448\",\"label\":\"Public Key\"}\n{\"type\":\"input\",\"ref\":\"f91d0a8a78462bc59398f2c5d7a84fcff491c26ba54c4833478b202796c8aafd:0\",\"label\":\"Input\"}\n{\"type\":\"output\",\"ref\":\"f91d0a8a78462bc59398f2c5d7a84fcff491c26ba54c4833478b202796c8aafd:1\",\"label\":\"Output\",\"spendable\":false}\n{\"type\":\"xpub\",\"ref\":\"xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8\",\"label\":\"Extended Public Key\"}\n{\"type\":\"tx\",\"ref\":\"f546156d9044844e02b181026a1a407abfca62e7ea1159f87bbeaa77b4286c74\",\"label\":\"Account #1 Transaction\",\"origin\":\"wpkh([d34db33f/84'/0'/1'])\"}",
|
||||
"nonce": "deadbeefcafebabe12345678",
|
||||
"expected": "4249505858580102040000000080000001000000028000000303800000548000000080000000032424c7f03a4b1ec573f64738c2a61ac0a9480750f6a641ff8dd1e85acf5b8008331aabbcc51126eeeaf8f870c92bdae98a5688af3a1d9ce71004980b7f6af6e96e5f3aab8b6dfe2f8c09da023a29f797d8333736fb7b7c64958d0ff4109ba93a01deadbeefcafebabe12345678fd9c03f6ebb8e2e9c02c5194e453edd274ec677e0dea5f18cda3e00f7cc4e8c8d4821bda377728eb2f6d2f69eef72070a2a7bc01cc720bb989346102076d475cab2802f1e3766526d2c0bfd257a8e424045cd91356e8789458d06aa055fe2ed0c42fb338b43ae394ae3f9807e1840171965708c89e3b42e68dc4bf84c51bcc8738475e8325e07398753327c1afa6a96032cf73b9387c0f4cb6825adf383c8135b63394b1372fb2752c5297a595099d91c59f25ad6e0d136013ce64d67a53fc88861bf1f558fc2c775644fba1bba9efd23f562f6edb9a2cb476c40cc2ae3f006d3f839a9607271b6eed6f58efcf435eb0cf79c12b5f3c4160f8c3de8e9e311c7698090be2c8e2a3ef702daf88612179e21ee4ac401cab342f7a1d1c141eed8f1a7c60d6dd34324ed6bd07e03ae596d7c04350698ce4592660b841aadf5c2a372b0fc57539094bc0af80febc92aa10578c0b35efd164f4c94217d2e0de72461bdea40d881858eb4b16f1c361fa98cfe0fcbc83787c492238ea745a84265e907c8a07d98852fef62a2a360b75c8b700b24d503a0e54260a1a94e0a980d69aa76e34ba8c304f85e0e7f4cfa3cf3c0c4ac8ddad1548bf20dabd4b316ed53903701677e78d3cfd46980acfe482110be8be64a27ce1dd4d7502338d087e9b86b7ca6144fc81a2a7b806a4e397dfb8d8ad9ea54130d9b46d2cd9002e372094399078e0bce1af9f2dfb5a69a16ec88e53ec9c6f34d784596afcece4d8abd33e937d9ea4ddf170088270cc4f59f68b978368833dc7713b0351da5f690991c841f17c42e7b4d89c35a821e110c4b2a9a1f0cfebd14cfb39d938569614ee62bb488049c6b7ed636dd90cfb00170dd80f4a6e6c9a45a3bed0fa1340ecddb538bb888fdaaa1680d711d6f94297a9f7ed3401cecb25b6779b4ba5415a343a95597cb85b074d8e19def182d8581fb7b4bc716ba887af1bd51a10c699f6ddfdb5439c7eac02d9220a0417489a79bbc6da4d10325317a6630da9303c433f261e0d36f977cea8113c7e4581e5d27f6607be0f9f7058fd6730d64377b7d1e70f4858974896e3ae9fbde9fb6eb66be4d0c36544cf8cfb80166875f1672f5aa4991951248414a54457e3f3bea0a2953d27de6d0a299cc06471d9f331ace87937b96547e7bcfa7ae972fd9e08cfa69fae42fe786f1cb1d5ee0bc3bbd9277f38b290eb2033f39dc65bfc963c60d3f01d493ab7546cd72504303f68bd5e376d2b6a2dc59d4c3cfbef490d1cdcb73065f756620528bb0bd92301a26f53f0c1ae61962416c746d1b3b38fd202",
|
||||
"expected_base64": "QklQWFhYAQIEAAAAAIAAAAEAAAACgAAAAwOAAABUgAAAAIAAAAADJCTH8DpLHsVz9kc4wqYawKlIB1D2pkH/jdHoWs9bgAgzGqu8xREm7ur4+HDJK9rpilaIrzodnOcQBJgLf2r26W5fOquLbf4vjAnaAjop95fYMzc2+3t8ZJWND/QQm6k6Ad6tvu/K/rq+EjRWeP2cA/bruOLpwCxRlORT7dJ07Gd+DepfGM2j4A98xOjI1IIb2jd3KOsvbS9p7vcgcKKnvAHMcgu5iTRhAgdtR1yrKALx43ZlJtLAv9JXqOQkBFzZE1boeJRY0GqgVf4u0MQvszi0OuOUrj+YB+GEAXGWVwjInjtC5o3Ev4TFG8yHOEdegyXgc5h1MyfBr6apYDLPc7k4fA9MtoJa3zg8gTW2M5SxNy+ydSxSl6WVCZ2RxZ8lrW4NE2ATzmTWelP8iIYb8fVY/Cx3VkT7obup79I/Vi9u25ostHbEDMKuPwBtP4OalgcnG27tb1jvz0NesM95wStfPEFg+MPejp4xHHaYCQviyOKj73Atr4hhIXniHuSsQByrNC96HRwUHu2PGnxg1t00Mk7WvQfgOuWW18BDUGmM5FkmYLhBqt9cKjcrD8V1OQlLwK+A/rySqhBXjAs179Fk9MlCF9Lg3nJGG96kDYgYWOtLFvHDYfqYz+D8vIN4fEkiOOp0WoQmXpB8igfZiFL+9ioqNgt1yLcAsk1QOg5UJgoalOCpgNaap240uowwT4Xg5/TPo888DErI3a0VSL8g2r1LMW7VOQNwFnfnjTz9RpgKz+SCEQvovmSifOHdTXUCM40IfpuGt8phRPyBoqe4BqTjl9+42K2epUEw2bRtLNkALjcglDmQeOC84a+fLftaaaFuyI5T7JxvNNeEWWr87OTYq9M+k32epN3xcAiCcMxPWfaLl4Nogz3HcTsDUdpfaQmRyEHxfELntNicNagh4RDEsqmh8M/r0Uz7Odk4VpYU7mK7SIBJxrftY23ZDPsAFw3YD0pubJpFo77Q+hNA7N21OLuIj9qqFoDXEdb5Qpep9+00Ac7LJbZ3m0ulQVo0OpVZfLhbB02OGd7xgthYH7e0vHFrqIevG9UaEMaZ9t39tUOcfqwC2SIKBBdImnm7xtpNEDJTF6ZjDakwPEM/Jh4NNvl3zqgRPH5FgeXSf2YHvg+fcFj9ZzDWQ3e30ecPSFiXSJbjrp+96ftutmvk0MNlRM+M+4AWaHXxZy9apJkZUSSEFKVEV+PzvqCilT0n3m0KKZzAZHHZ8zGs6Hk3uWVH57z6euly/Z4Iz6afrkL+eG8csdXuC8O72Sd/OLKQ6yAz853GW/yWPGDT8B1JOrdUbNclBDA/aL1eN20rai3FnUw8++9JDRzctzBl91ZiBSi7C9kjAaJvU/DBrmGWJBbHRtGzs4/SAg=="
|
||||
},
|
||||
{
|
||||
"description": "Single key, proprietary content (3 bytes)",
|
||||
"version": 1,
|
||||
"encryption": 1,
|
||||
"content": "0204deadbeef",
|
||||
"keys": [
|
||||
"02e6642fd69bd211f93f7f1f36ca51a26a5290eb2dd1b0d8279a87bb0d480c8443"
|
||||
],
|
||||
"derivation_paths": [],
|
||||
"plaintext": "706c61696e74657874",
|
||||
"nonce": "000102030405060708090a0b",
|
||||
"expected": "424950585858010001ff34b3411f78127b71ca2e3cc60d0fd71350ee557c37d71f4d81fb913461ae0001000102030405060708090a0b2803da142accb6215cecfe50629224496c4d35cfc7ee64e906e77cc3398689748c325907c7d5dafef3",
|
||||
"expected_base64": "QklQWFhYAQAB/zSzQR94Entxyi48xg0P1xNQ7lV8N9cfTYH7kTRhrgABAAECAwQFBgcICQoLKAPaFCrMtiFc7P5QYpIkSWxNNc/H7mTpBud8wzmGiXSMMlkHx9Xa/vM="
|
||||
}
|
||||
]
|
||||
89
bip-encrypted-backup/test_vectors/encryption_secret.json
Normal file
89
bip-encrypted-backup/test_vectors/encryption_secret.json
Normal file
@@ -0,0 +1,89 @@
|
||||
[
|
||||
{
|
||||
"description": "Single public key",
|
||||
"keys": [
|
||||
"02e6642fd69bd211f93f7f1f36ca51a26a5290eb2dd1b0d8279a87bb0d480c8443"
|
||||
],
|
||||
"decryption_secret": "a37acb446622cf11ffe44e1f17892d7b330b721b992513f680a52b128fb181b1",
|
||||
"individual_secrets": [
|
||||
"ff34b3411f78127b71ca2e3cc60d0fd71350ee557c37d71f4d81fb913461ae00"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Two public keys",
|
||||
"keys": [
|
||||
"02e6642fd69bd211f93f7f1f36ca51a26a5290eb2dd1b0d8279a87bb0d480c8443",
|
||||
"0384526253c27c7aef56c7b71a5cd25bebb66dddda437826defc5b2568bde81f07"
|
||||
],
|
||||
"decryption_secret": "154eaceae97b166f15a1d37fbc6d9477b1cf067c60352909a97f32b432412f0c",
|
||||
"individual_secrets": [
|
||||
"5e3eb8a36f7bf32e02810c14666476f2b28a15cd499c30f8f98e926639a0765c",
|
||||
"4900d4ef9021cb059b8fb35c6de9b6db91949a328527ede0645be237899100bd"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Three public keys",
|
||||
"keys": [
|
||||
"02e6642fd69bd211f93f7f1f36ca51a26a5290eb2dd1b0d8279a87bb0d480c8443",
|
||||
"0384526253c27c7aef56c7b71a5cd25bebb66dddda437826defc5b2568bde81f07",
|
||||
"03c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5"
|
||||
],
|
||||
"decryption_secret": "6f54d3b9bc4bfb8464d6985318aff845aa0d14e1df0f580edd204888c4bad958",
|
||||
"individual_secrets": [
|
||||
"2424c7f03a4b1ec573f64738c2a61ac0a9480750f6a641ff8dd1e85acf5b8008",
|
||||
"6e5f3aab8b6dfe2f8c09da023a29f797d8333736fb7b7c64958d0ff4109ba93a",
|
||||
"331aabbcc51126eeeaf8f870c92bdae98a5688af3a1d9ce71004980b7f6af6e9"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Three public keys bis (different sorting)",
|
||||
"keys": [
|
||||
"03c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5",
|
||||
"02e6642fd69bd211f93f7f1f36ca51a26a5290eb2dd1b0d8279a87bb0d480c8443",
|
||||
"0384526253c27c7aef56c7b71a5cd25bebb66dddda437826defc5b2568bde81f07"
|
||||
],
|
||||
"decryption_secret": "6f54d3b9bc4bfb8464d6985318aff845aa0d14e1df0f580edd204888c4bad958",
|
||||
"individual_secrets": [
|
||||
"2424c7f03a4b1ec573f64738c2a61ac0a9480750f6a641ff8dd1e85acf5b8008",
|
||||
"6e5f3aab8b6dfe2f8c09da023a29f797d8333736fb7b7c64958d0ff4109ba93a",
|
||||
"331aabbcc51126eeeaf8f870c92bdae98a5688af3a1d9ce71004980b7f6af6e9"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Three public keys ter (different sorting)",
|
||||
"keys": [
|
||||
"0384526253c27c7aef56c7b71a5cd25bebb66dddda437826defc5b2568bde81f07",
|
||||
"03c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5",
|
||||
"02e6642fd69bd211f93f7f1f36ca51a26a5290eb2dd1b0d8279a87bb0d480c8443"
|
||||
],
|
||||
"decryption_secret": "6f54d3b9bc4bfb8464d6985318aff845aa0d14e1df0f580edd204888c4bad958",
|
||||
"individual_secrets": [
|
||||
"2424c7f03a4b1ec573f64738c2a61ac0a9480750f6a641ff8dd1e85acf5b8008",
|
||||
"6e5f3aab8b6dfe2f8c09da023a29f797d8333736fb7b7c64958d0ff4109ba93a",
|
||||
"331aabbcc51126eeeaf8f870c92bdae98a5688af3a1d9ce71004980b7f6af6e9"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Keys processed in sorted order",
|
||||
"keys": [
|
||||
"0384526253c27c7aef56c7b71a5cd25bebb66dddda437826defc5b2568bde81f07",
|
||||
"02e6642fd69bd211f93f7f1f36ca51a26a5290eb2dd1b0d8279a87bb0d480c8443"
|
||||
],
|
||||
"decryption_secret": "154eaceae97b166f15a1d37fbc6d9477b1cf067c60352909a97f32b432412f0c",
|
||||
"individual_secrets": [
|
||||
"5e3eb8a36f7bf32e02810c14666476f2b28a15cd499c30f8f98e926639a0765c",
|
||||
"4900d4ef9021cb059b8fb35c6de9b6db91949a328527ede0645be237899100bd"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Duplicate keys should be handled",
|
||||
"keys": [
|
||||
"02e6642fd69bd211f93f7f1f36ca51a26a5290eb2dd1b0d8279a87bb0d480c8443",
|
||||
"02e6642fd69bd211f93f7f1f36ca51a26a5290eb2dd1b0d8279a87bb0d480c8443"
|
||||
],
|
||||
"decryption_secret": "a37acb446622cf11ffe44e1f17892d7b330b721b992513f680a52b128fb181b1",
|
||||
"individual_secrets": [
|
||||
"ff34b3411f78127b71ca2e3cc60d0fd71350ee557c37d71f4d81fb913461ae00"
|
||||
]
|
||||
}
|
||||
]
|
||||
554
bip-encrypted-backup/test_vectors/individual_secrets.json
Normal file
554
bip-encrypted-backup/test_vectors/individual_secrets.json
Normal file
File diff suppressed because one or more lines are too long
47
bip-encrypted-backup/test_vectors/keys_types.json
Normal file
47
bip-encrypted-backup/test_vectors/keys_types.json
Normal file
@@ -0,0 +1,47 @@
|
||||
[
|
||||
{
|
||||
"description": "Xpub with origin and multipath wildcard",
|
||||
"key": "[58b7f8dc/48'/1'/0'/2']tpubDEPBvXvhta3pjVaKokqC3eeMQnszj9ehFaA2zD5nSdkaccwGAizu8jVB2NeSpvmP2P52MBoZvNCixqXRJnTyXx51FQzARR63tjxQSyP3Btw/<0;1>/*",
|
||||
"expected": "ebd252ca0877aae09b9d058219682775aa3cbcd049c12f07832f2cf6a3b51708"
|
||||
},
|
||||
{
|
||||
"description": "Xpub with single-path wildcard",
|
||||
"key": "[58b7f8dc/48'/1'/0'/2']tpubDEPBvXvhta3pjVaKokqC3eeMQnszj9ehFaA2zD5nSdkaccwGAizu8jVB2NeSpvmP2P52MBoZvNCixqXRJnTyXx51FQzARR63tjxQSyP3Btw/0/*",
|
||||
"expected": "ebd252ca0877aae09b9d058219682775aa3cbcd049c12f07832f2cf6a3b51708"
|
||||
},
|
||||
{
|
||||
"description": "Xpub with bare wildcard (no preceding path)",
|
||||
"key": "[58b7f8dc/48'/1'/0'/2']tpubDEPBvXvhta3pjVaKokqC3eeMQnszj9ehFaA2zD5nSdkaccwGAizu8jVB2NeSpvmP2P52MBoZvNCixqXRJnTyXx51FQzARR63tjxQSyP3Btw/*",
|
||||
"expected": "ebd252ca0877aae09b9d058219682775aa3cbcd049c12f07832f2cf6a3b51708"
|
||||
},
|
||||
{
|
||||
"description": "Xpub with fixed deep derivation, no wildcard",
|
||||
"key": "[58b7f8dc/48'/1'/0'/2']tpubDEPBvXvhta3pjVaKokqC3eeMQnszj9ehFaA2zD5nSdkaccwGAizu8jVB2NeSpvmP2P52MBoZvNCixqXRJnTyXx51FQzARR63tjxQSyP3Btw/0/5",
|
||||
"expected": "ebd252ca0877aae09b9d058219682775aa3cbcd049c12f07832f2cf6a3b51708"
|
||||
},
|
||||
{
|
||||
"description": "Xpub with multipath, no wildcard",
|
||||
"key": "[58b7f8dc/48'/1'/0'/2']tpubDEPBvXvhta3pjVaKokqC3eeMQnszj9ehFaA2zD5nSdkaccwGAizu8jVB2NeSpvmP2P52MBoZvNCixqXRJnTyXx51FQzARR63tjxQSyP3Btw/<0;1>",
|
||||
"expected": "ebd252ca0877aae09b9d058219682775aa3cbcd049c12f07832f2cf6a3b51708"
|
||||
},
|
||||
{
|
||||
"description": "Bare xpub (no derivation, no wildcard); DISALLOWED",
|
||||
"key": "[d4ab66f1/48'/1'/1'/2']tpubDFTxBKyUCgkwp5enwZh3t2FJ5AMJqmCWoh1NRT13qNYQb1iKTUrAG6u5gpsDYhG8cZGXouYWuQtzcuSVjPStTc4dwU6JqPMFtgaLGvSQXhi",
|
||||
"expected": null
|
||||
},
|
||||
{
|
||||
"description": "Compressed literal pubkey; DISALLOWED",
|
||||
"key": "02ebd252ca0877aae09b9d058219682775aa3cbcd049c12f07832f2cf6a3b51708",
|
||||
"expected": null
|
||||
},
|
||||
{
|
||||
"description": "X-only literal pubkey; DISALLOWED",
|
||||
"key": "ebd252ca0877aae09b9d058219682775aa3cbcd049c12f07832f2cf6a3b51708",
|
||||
"expected": null
|
||||
},
|
||||
{
|
||||
"description": "Uncompressed literal pubkey; DISALLOWED",
|
||||
"key": "04ebd252ca0877aae09b9d058219682775aa3cbcd049c12f07832f2cf6a3b517089e956909c4c07e8529f45f3ff8904d28df5a181619e21bdf748a896322530039",
|
||||
"expected": null
|
||||
}
|
||||
]
|
||||
Reference in New Issue
Block a user