1
0
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:
pythcoiner
2025-08-22 11:59:20 +02:00
committed by Murch
parent 5253e9a294
commit 199c7beb44
8 changed files with 1380 additions and 0 deletions

373
bip-encrypted-backup.md Normal file
View 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

View File

@@ -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"
}
]

View 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"
}
]

View 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"
}
]

View 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="
}
]

View 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"
]
}
]

File diff suppressed because one or more lines are too long

View 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
}
]