Skip to content

Commit 1c3c74b

Browse files
committed
descriptor: allow hex private keys for ct() blinding keys
1 parent 6ca519c commit 1c3c74b

File tree

2 files changed

+84
-41
lines changed

2 files changed

+84
-41
lines changed

src/ctest/test_descriptor.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1657,6 +1657,14 @@ static const struct descriptor_test {
16571657
"descriptor errchk - ELIP 150 blinding key with multipath",
16581658
"ct(mainnet_xpub/<0;1>,elpkh(key_4))",
16591659
WALLY_NETWORK_LIQUID, 0, 0, 0, NULL, 0, NULL, ""
1660+
}, {
1661+
"descriptor errchk - ELIP 150 short hex key",
1662+
"ct(fc9a38e765d955e9b0bcc18fa9ae81b0c893e2dd1ef5542a9c73780a086b90,elwpkh(key_4))",
1663+
WALLY_NETWORK_LIQUID, 0, 0, 0, NULL, 0, NULL, ""
1664+
}, {
1665+
"descriptor errchk - ELIP 150 long hex key",
1666+
"ct(0202fc9a38e765d955e9b0bcc18fa9ae81b0c893e2dd1ef5542a9c73780a086b90,elwpkh(key_4))",
1667+
WALLY_NETWORK_LIQUID, 0, 0, 0, NULL, 0, NULL, ""
16601668
}
16611669
#endif /* BUILD_ELEMENTS */
16621670
};
@@ -2064,6 +2072,18 @@ static const struct address_test {
20642072
WALLY_NETWORK_LIQUID,
20652073
0, 0, 0,
20662074
ADDR("lq1qq2r0pdvcknjpwev96qu9975alzqs78cvsut5ju82t7tv8d645dgmwknpl78t02k2xqgdh9ltmfmpy9ssk7qfvtk83xqzx62q4")
2075+
}, {
2076+
"address - ELIP 150 View Descriptor 2",
2077+
"ct(c25deb86fa11e49d651d7eae27c220ef930fbd86ea023eebfa73e54875647963,elwpkh(021a8fb6bd5a653b021b98a2a785725b8ddacfe3687bc043aa7f4d25d3a48d40b5))#c2kx9zll",
2078+
WALLY_NETWORK_LIQUID,
2079+
0, 0, 0,
2080+
ADDR("lq1qq265u4g3k3m3qpyxjwpdrtnm293wuxgvs9xzmzcs2ck0mv5rx23w4d7xfsednsmmxrszfe7s9rs0c6cvf3dfytxax3utlmm46")
2081+
}, {
2082+
"address - ELIP 150 Non-View Descriptor 2",
2083+
"ct(0286fc9a38e765d955e9b0bcc18fa9ae81b0c893e2dd1ef5542a9c73780a086b90,elwpkh(021a8fb6bd5a653b021b98a2a785725b8ddacfe3687bc043aa7f4d25d3a48d40b5))#m5mvyh29",
2084+
WALLY_NETWORK_LIQUID,
2085+
0, 0, 0,
2086+
ADDR("lq1qq265u4g3k3m3qpyxjwpdrtnm293wuxgvs9xzmzcs2ck0mv5rx23w4d7xfsednsmmxrszfe7s9rs0c6cvf3dfytxax3utlmm46")
20672087
}, {
20682088
"address - slip77 (ELIP 150 Valid Descriptor 5)",
20692089
"ct(slip77(slip77_key),elpkh(key_4))#hw2glz99",

src/descriptor.c

Lines changed: 64 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -587,7 +587,8 @@ static void node_free(ms_node *node)
587587
node_free(child);
588588
child = next;
589589
}
590-
if (node->kind & (KIND_RAW | KIND_ADDRESS) || node->kind == KIND_PUBLIC_KEY || node->kind == KIND_PRIVATE_KEY)
590+
if (node->kind & (KIND_RAW | KIND_ADDRESS) ||
591+
node->kind == KIND_PUBLIC_KEY || node->kind == KIND_PRIVATE_KEY)
591592
clear_and_free((void*)node->data, node->data_len);
592593
clear_and_free(node, sizeof(*node));
593594
}
@@ -2249,58 +2250,80 @@ static int analyze_address(ms_ctx *ctx, const char *str, size_t str_len,
22492250
return ret;
22502251
}
22512252

2252-
/* take the possible hex data in node->data, if it is a valid pubkey
2253+
/* take the possible hex data in node->data, if it is a valid key then
22532254
* convert it to an allocated binary buffer and make this node a key node
22542255
*/
2255-
static int analyze_pubkey_hex(ms_ctx *ctx, ms_node *node,
2256-
uint32_t flags, bool *is_hex)
2257-
{
2258-
unsigned char pubkey[EC_PUBLIC_KEY_UNCOMPRESSED_LEN];
2259-
size_t pubkey_len;
2260-
bool allow_xonly, make_xonly = false;
2261-
2262-
*is_hex = wally_hex_n_to_bytes(node->data, node->data_len,
2263-
pubkey, sizeof(pubkey), &pubkey_len) == WALLY_OK;
2264-
if (!*is_hex || pubkey_len > sizeof(pubkey))
2265-
return WALLY_OK; /* Not hex, or too long */
2266-
2267-
if (wally_ec_public_key_verify(pubkey, pubkey_len) != WALLY_OK &&
2268-
wally_ec_xonly_public_key_verify(pubkey, pubkey_len) != WALLY_OK)
2269-
return WALLY_OK; /* Not a valid pubkey */
2270-
2271-
make_xonly = node->parent &&
2272-
(node->parent->kind == KIND_DESCRIPTOR_RAW_TR ||
2273-
node->parent->kind == KIND_DESCRIPTOR_TR);
2274-
allow_xonly = make_xonly || flags & WALLY_MINISCRIPT_TAPSCRIPT;
2275-
if (pubkey_len == EC_PUBLIC_KEY_UNCOMPRESSED_LEN && allow_xonly)
2276-
return WALLY_OK; /* Uncompressed key not allowed here */
2277-
if (pubkey_len == EC_XONLY_PUBLIC_KEY_LEN && !allow_xonly)
2278-
return WALLY_OK; /* X-only not allowed here */
2279-
if (pubkey_len != EC_XONLY_PUBLIC_KEY_LEN) {
2280-
if (flags & WALLY_MINISCRIPT_TAPSCRIPT)
2281-
return WALLY_OK; /* Only X-only pubkeys allowed under tapscript */
2282-
if (make_xonly) {
2283-
/* Convert to x-only */
2284-
--pubkey_len;
2285-
memmove(pubkey, pubkey + 1, pubkey_len);
2256+
static int analyze_key_hex(ms_ctx *ctx, ms_node *node,
2257+
uint32_t flags, bool is_ct_key, bool *is_hex)
2258+
{
2259+
unsigned char key[EC_PUBLIC_KEY_UNCOMPRESSED_LEN], *key_p = key;
2260+
size_t key_len;
2261+
bool allow_xonly, make_xonly = false, is_private = false;
2262+
2263+
*is_hex = wally_hex_n_to_bytes(node->data, node->data_len,
2264+
key, sizeof(key), &key_len) == WALLY_OK;
2265+
if (!*is_hex)
2266+
return WALLY_OK; /* Not a hex string */
2267+
2268+
if (key_len == EC_PRIVATE_KEY_LEN && is_ct_key) {
2269+
if (wally_ec_private_key_verify(key, key_len) != WALLY_OK)
2270+
return WALLY_OK; /* Not a valid private key */
2271+
is_private = true;
2272+
} else if (key_len == EC_XONLY_PUBLIC_KEY_LEN) {
2273+
if (wally_ec_xonly_public_key_verify(key, key_len) != WALLY_OK)
2274+
return WALLY_OK; /* Not a valid x-only key */
2275+
} else if (key_len == EC_PUBLIC_KEY_LEN ||
2276+
key_len == EC_PUBLIC_KEY_UNCOMPRESSED_LEN) {
2277+
if (wally_ec_public_key_verify(key, key_len) != WALLY_OK)
2278+
return WALLY_OK; /* Not a valid compressed/uncompressed pubkey */
2279+
} else
2280+
return WALLY_OK; /* Not a pubkey */
2281+
2282+
if (!is_private) {
2283+
/* Ensure the pubkey is allowed in this context/convert as needed */
2284+
make_xonly = node->parent &&
2285+
(node->parent->kind == KIND_DESCRIPTOR_RAW_TR ||
2286+
node->parent->kind == KIND_DESCRIPTOR_TR);
2287+
allow_xonly = make_xonly || flags & WALLY_MINISCRIPT_TAPSCRIPT;
2288+
if (key_len == EC_PUBLIC_KEY_UNCOMPRESSED_LEN && allow_xonly)
2289+
return WALLY_OK; /* Uncompressed key not allowed here */
2290+
if (key_len == EC_XONLY_PUBLIC_KEY_LEN && !allow_xonly)
2291+
return WALLY_OK; /* X-only not allowed here */
2292+
if (key_len != EC_XONLY_PUBLIC_KEY_LEN) {
2293+
if (flags & WALLY_MINISCRIPT_TAPSCRIPT)
2294+
return WALLY_OK; /* Only X-only pubkeys allowed under tapscript */
2295+
if (make_xonly) {
2296+
/* Convert to x-only */
2297+
--key_len;
2298+
++key_p;
2299+
}
22862300
}
22872301
}
22882302

2289-
if (!clone_bytes((unsigned char **)&node->data, pubkey, pubkey_len))
2303+
if (!clone_bytes((unsigned char **)&node->data, key_p, key_len))
22902304
return WALLY_ENOMEM;
2291-
node->data_len = pubkey_len;
2305+
node->data_len = key_len;
22922306

2293-
if (pubkey_len == EC_PUBLIC_KEY_UNCOMPRESSED_LEN) {
2307+
if (is_ct_key)
2308+
ctx->features |= WALLY_MS_IS_ELIP150;
2309+
if (is_private) {
2310+
node->kind = KIND_PRIVATE_KEY;
2311+
node->flags |= (WALLY_MS_IS_PRIVATE | WALLY_MS_IS_RAW);
2312+
return WALLY_OK;
2313+
}
2314+
node->kind = KIND_PUBLIC_KEY;
2315+
if (is_ct_key)
2316+
return WALLY_OK;
2317+
if (key_len == EC_PUBLIC_KEY_UNCOMPRESSED_LEN) {
22942318
node->flags |= WALLY_MS_IS_UNCOMPRESSED;
22952319
ctx->features |= WALLY_MS_IS_UNCOMPRESSED;
22962320
}
2297-
if (pubkey_len == EC_XONLY_PUBLIC_KEY_LEN) {
2321+
if (key_len == EC_XONLY_PUBLIC_KEY_LEN) {
22982322
node->flags |= WALLY_MS_IS_X_ONLY;
22992323
ctx->features |= WALLY_MS_IS_X_ONLY;
23002324
}
2301-
ctx->features |= WALLY_MS_IS_RAW;
2302-
node->kind = KIND_PUBLIC_KEY;
23032325
node->flags |= WALLY_MS_IS_RAW;
2326+
ctx->features |= WALLY_MS_IS_RAW;
23042327
return ctx_add_key_node(ctx, node);
23052328
}
23062329

@@ -2357,8 +2380,8 @@ static int analyze_miniscript_key(ms_ctx *ctx, uint32_t flags,
23572380
node->data_len -= size;
23582381
}
23592382

2360-
/* Check for a hex public key */
2361-
ret = analyze_pubkey_hex(ctx, node, flags, &is_hex);
2383+
/* Check for a hex public key (hex private keys allowed for ct() only) */
2384+
ret = analyze_key_hex(ctx, node, flags, is_ct_key, &is_hex);
23622385
if (ret == WALLY_OK && is_hex)
23632386
return WALLY_OK;
23642387

0 commit comments

Comments
 (0)