common/blindedpath: expose API at a lower level.

We actually want lightningd to create these, since it wants to put the
path_id secret in the last element.  So best API is actually a generic
one, rather than separate APIs to create first and last ones.

And really, the more explicit initialization makes the users clearer.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell
2022-11-09 12:00:10 +10:30
committed by Christian Decker
parent 01a47720c3
commit 4cfd972407
7 changed files with 124 additions and 159 deletions

View File

@@ -107,15 +107,20 @@ static u8 *enctlv_from_encmsg_raw(const tal_t *ctx,
return ret; return ret;
} }
static u8 *enctlv_from_encmsg(const tal_t *ctx, u8 *encrypt_tlv_encrypted_data(const tal_t *ctx,
const struct privkey *blinding, const struct privkey *blinding,
const struct pubkey *node, const struct pubkey *node,
const struct tlv_encrypted_data_tlv *encmsg, const struct tlv_encrypted_data_tlv *encmsg,
struct privkey *next_blinding, struct privkey *next_blinding,
struct pubkey *node_alias) struct pubkey *node_alias)
{ {
struct privkey unused;
u8 *encmsg_raw = tal_arr(NULL, u8, 0); u8 *encmsg_raw = tal_arr(NULL, u8, 0);
towire_tlv_encrypted_data_tlv(&encmsg_raw, encmsg); towire_tlv_encrypted_data_tlv(&encmsg_raw, encmsg);
/* last hop doesn't care about next_blinding */
if (!next_blinding)
next_blinding = &unused;
return enctlv_from_encmsg_raw(ctx, blinding, node, take(encmsg_raw), return enctlv_from_encmsg_raw(ctx, blinding, node, take(encmsg_raw),
next_blinding, node_alias); next_blinding, node_alias);
} }
@@ -253,52 +258,3 @@ void blindedpath_next_blinding(const struct tlv_encrypted_data_tlv *enc,
blinding_next_pubkey(blinding, &h, next_blinding); blinding_next_pubkey(blinding, &h, next_blinding);
} }
} }
u8 *create_enctlv(const tal_t *ctx,
const struct privkey *blinding,
const struct pubkey *node,
const struct pubkey *next_node,
const struct short_channel_id *next_scid,
size_t padlen,
const struct pubkey *next_blinding_override,
const struct tlv_encrypted_data_tlv_payment_relay *payment_relay TAKES,
const struct tlv_encrypted_data_tlv_payment_constraints *payment_constraints TAKES,
const u8 *allowed_features TAKES,
struct privkey *next_blinding,
struct pubkey *node_alias)
{
struct tlv_encrypted_data_tlv *encmsg = tlv_encrypted_data_tlv_new(tmpctx);
if (padlen)
encmsg->padding = tal_arrz(encmsg, u8, padlen);
encmsg->next_node_id = cast_const(struct pubkey *, next_node);
encmsg->next_blinding_override = cast_const(struct pubkey *, next_blinding_override);
encmsg->payment_relay = tal_dup_or_null(encmsg, struct tlv_encrypted_data_tlv_payment_relay,
payment_relay);
encmsg->payment_constraints = tal_dup_or_null(encmsg, struct tlv_encrypted_data_tlv_payment_constraints,
payment_constraints);
encmsg->allowed_features = tal_dup_talarr(encmsg, u8, allowed_features);
return enctlv_from_encmsg(ctx, blinding, node, encmsg,
next_blinding, node_alias);
}
u8 *create_final_enctlv(const tal_t *ctx,
const struct privkey *blinding,
const struct pubkey *final_node,
size_t padlen,
const struct secret *path_id,
const u8 *allowed_features TAKES,
struct pubkey *node_alias)
{
struct tlv_encrypted_data_tlv *encmsg = tlv_encrypted_data_tlv_new(tmpctx);
struct privkey unused_next_blinding;
if (padlen)
encmsg->padding = tal_arrz(encmsg, u8, padlen);
if (path_id)
encmsg->path_id = (u8 *)tal_dup(encmsg, struct secret, path_id);
encmsg->allowed_features = tal_dup_talarr(encmsg, u8, allowed_features);
return enctlv_from_encmsg(ctx, blinding, final_node, encmsg,
&unused_next_blinding, node_alias);
}

View File

@@ -10,61 +10,29 @@ struct pubkey;
struct privkey; struct privkey;
struct secret; struct secret;
struct short_channel_id; struct short_channel_id;
struct tlv_encrypted_data_tlv;
struct tlv_encrypted_data_tlv_payment_constraints; struct tlv_encrypted_data_tlv_payment_constraints;
struct tlv_encrypted_data_tlv_payment_relay; struct tlv_encrypted_data_tlv_payment_relay;
/** /**
* create_enctlv - Encrypt an encmsg to form an enctlv. * encrypt_tlv_encrypted_data - Encrypt a tlv_encrypted_data_tlv.
* @ctx: tal context * @ctx: tal context
* @blinding: e(i), the blinding secret * @blinding: e(i), the blinding secret
* @node: the pubkey of the node to encrypt for * @node: the pubkey of the node to encrypt for
* @next_node: the pubkey of the next node, to place in enctlv * @tlv: the message to encrypt.
* @next_scid: the short_channel_id to the next node, to place in enctlv * @next_blinding: (out) e(i+1), the next blinding secret (optional)
* @padlen: if non-zero, the bytes of padding to add (also adds 2 byte padding hdr)
* @next_blinding_override: the optional blinding point to place in enctlv
* @payment_relay: optional payment_relay tlv
* @payment_constraints: optional payment_constraints tlv
* @allowed_features: optional allowed_features array
* @next_blinding: (out) e(i+1), the next blinding secret.
* @node_alias: (out) the blinded pubkey of the node to tell the recipient. * @node_alias: (out) the blinded pubkey of the node to tell the recipient.
* *
* Exactly one of next_node and next_scid must be non-NULL. * You create a blinding secret using randombytes_buf(), then call this
* Returns the enctlv blob, or NULL if the secret is invalid. * iteratively for each node in the path.
*/ */
u8 *create_enctlv(const tal_t *ctx, u8 *encrypt_tlv_encrypted_data(const tal_t *ctx,
const struct privkey *blinding, const struct privkey *blinding,
const struct pubkey *node, const struct pubkey *node,
const struct pubkey *next_node, const struct tlv_encrypted_data_tlv *tlv,
const struct short_channel_id *next_scid,
size_t padlen,
const struct pubkey *next_blinding_override,
const struct tlv_encrypted_data_tlv_payment_relay *payment_relay TAKES,
const struct tlv_encrypted_data_tlv_payment_constraints *payment_constraints TAKES,
const u8 *allowed_features TAKES,
struct privkey *next_blinding, struct privkey *next_blinding,
struct pubkey *node_alias) struct pubkey *node_alias)
NON_NULL_ARGS(2, 3, 11, 12); NON_NULL_ARGS(2, 3, 4, 6);
/**
* create_final_enctlv - Encrypt an encmsg to form the final enctlv.
* @ctx: tal context
* @blinding: e(i), the blinding secret
* @final_node: the pubkey of the node to encrypt for
* @padlen: if non-zero, the bytes of padding to add (also adds 2 byte padding hdr)
* @allowed_features: optional allowed_features array
* @path_id: secret to include in enctlv, if not NULL.
* @node_alias: (out) the blinded pubkey of the node to tell the recipient.
*
* If it fails, it means one of the privkeys is bad.
*/
u8 *create_final_enctlv(const tal_t *ctx,
const struct privkey *blinding,
const struct pubkey *final_node,
size_t padlen,
const struct secret *path_id,
const u8 *allowed_features TAKES,
struct pubkey *node_alias)
NON_NULL_ARGS(2, 3, 7);
/** /**
* unblind_onion - tweak onion epheremeral key so we can decode it with ours. * unblind_onion - tweak onion epheremeral key so we can decode it with ours.

View File

@@ -373,4 +373,3 @@ field_bad:
*failtlvtype); *failtlvtype);
return tal_free(p); return tal_free(p);
} }

View File

@@ -140,6 +140,7 @@ int main(int argc, char *argv[])
struct pubkey alice_id, bob_id, carol_id, dave_id, blinding_pub, override_blinding_pub, alias; struct pubkey alice_id, bob_id, carol_id, dave_id, blinding_pub, override_blinding_pub, alias;
struct secret self_id; struct secret self_id;
u8 *enctlv; u8 *enctlv;
struct tlv_encrypted_data_tlv *tlv;
common_setup(argv[0]); common_setup(argv[0]);
@@ -171,8 +172,10 @@ int main(int argc, char *argv[])
"\t},\n", "\t},\n",
type_to_string(tmpctx, struct pubkey, &bob_id)); type_to_string(tmpctx, struct pubkey, &bob_id));
enctlv = create_enctlv(tmpctx, &blinding, &alice_id, &bob_id, NULL, tlv = tlv_encrypted_data_tlv_new(tmpctx);
0, NULL, NULL, NULL, NULL, &blinding, &alias); tlv->next_node_id = &bob_id;
enctlv = encrypt_tlv_encrypted_data(tmpctx, &blinding, &alice_id, tlv,
&blinding, &alias);
printf("\t\"encrypted_recipient_data_hex\": \"%s\"\n" printf("\t\"encrypted_recipient_data_hex\": \"%s\"\n"
"},\n", "},\n",
tal_hex(tmpctx, enctlv)); tal_hex(tmpctx, enctlv));
@@ -201,8 +204,10 @@ int main(int argc, char *argv[])
type_to_string(tmpctx, struct pubkey, &carol_id), type_to_string(tmpctx, struct pubkey, &carol_id),
type_to_string(tmpctx, struct privkey, &override_blinding)); type_to_string(tmpctx, struct privkey, &override_blinding));
enctlv = create_enctlv(tmpctx, &blinding, &bob_id, &carol_id, NULL, tlv = tlv_encrypted_data_tlv_new(tmpctx);
0, &override_blinding_pub, NULL, NULL, NULL, tlv->next_node_id = &carol_id;
tlv->next_blinding_override = &override_blinding_pub;
enctlv = encrypt_tlv_encrypted_data(tmpctx, &blinding, &bob_id, tlv,
&blinding, &alias); &blinding, &alias);
printf("\t\"encrypted_recipient_data_hex\": \"%s\"\n" printf("\t\"encrypted_recipient_data_hex\": \"%s\"\n"
"},\n", "},\n",
@@ -231,8 +236,11 @@ int main(int argc, char *argv[])
type_to_string(tmpctx, struct pubkey, &dave_id), type_to_string(tmpctx, struct pubkey, &dave_id),
tal_hex(tmpctx, tal_arrz(tmpctx, u8, 35))); tal_hex(tmpctx, tal_arrz(tmpctx, u8, 35)));
enctlv = create_enctlv(tmpctx, &blinding, &carol_id, &dave_id, NULL, tlv = tlv_encrypted_data_tlv_new(tmpctx);
35, NULL, NULL, NULL, NULL, &blinding, &alias); tlv->padding = tal_arrz(tlv, u8, 35);
tlv->next_node_id = &dave_id;
enctlv = encrypt_tlv_encrypted_data(tmpctx, &blinding, &carol_id, tlv,
&blinding, &alias);
printf("\t\"encrypted_recipient_data_hex\": \"%s\"\n" printf("\t\"encrypted_recipient_data_hex\": \"%s\"\n"
"},\n", "},\n",
tal_hex(tmpctx, enctlv)); tal_hex(tmpctx, enctlv));
@@ -256,8 +264,11 @@ int main(int argc, char *argv[])
"\t},\n", "\t},\n",
type_to_string(tmpctx, struct secret, &self_id)); type_to_string(tmpctx, struct secret, &self_id));
enctlv = create_final_enctlv(tmpctx, &blinding, &dave_id, tlv = tlv_encrypted_data_tlv_new(tmpctx);
0, &self_id, NULL, &alias); tlv->path_id = tal_dup_arr(tlv, u8,
self_id.data, ARRAY_SIZE(self_id.data), 0);
enctlv = encrypt_tlv_encrypted_data(tmpctx, &blinding, &dave_id, tlv,
NULL, &alias);
printf("\t\"encrypted_recipient_data_hex\": \"%s\"\n", printf("\t\"encrypted_recipient_data_hex\": \"%s\"\n",
tal_hex(tmpctx, enctlv)); tal_hex(tmpctx, enctlv));

View File

@@ -154,6 +154,7 @@ int main(int argc, char *argv[])
struct privkey nodekey[4], blinding[4], override_blinding; struct privkey nodekey[4], blinding[4], override_blinding;
struct pubkey id[4], blinding_pub[4], override_blinding_pub, alias[4]; struct pubkey id[4], blinding_pub[4], override_blinding_pub, alias[4];
struct secret self_id; struct secret self_id;
struct tlv_encrypted_data_tlv *tlv[4];
u8 *enctlv[4]; u8 *enctlv[4];
u8 *onionmsg_tlv[4]; u8 *onionmsg_tlv[4];
u8 *omsg; u8 *omsg;
@@ -173,35 +174,54 @@ int main(int argc, char *argv[])
memset(&blinding[ALICE], 5, sizeof(blinding[ALICE])); memset(&blinding[ALICE], 5, sizeof(blinding[ALICE]));
pubkey_from_privkey(&blinding[ALICE], &blinding_pub[ALICE]); pubkey_from_privkey(&blinding[ALICE], &blinding_pub[ALICE]);
enctlv[ALICE] = create_enctlv(tmpctx, &blinding[ALICE], tlv[ALICE] = tlv_encrypted_data_tlv_new(tmpctx);
&id[ALICE], &id[BOB], NULL, tlv[ALICE]->next_node_id = &id[BOB];
0, NULL, NULL, NULL, NULL, enctlv[ALICE] = encrypt_tlv_encrypted_data(tmpctx,
&blinding[BOB], &alias[ALICE]); &blinding[ALICE],
&id[ALICE], tlv[ALICE],
&blinding[BOB],
&alias[ALICE]);
pubkey_from_privkey(&blinding[BOB], &blinding_pub[BOB]); pubkey_from_privkey(&blinding[BOB], &blinding_pub[BOB]);
/* We override blinding for Carol. */ /* We override blinding for Carol. */
memset(&override_blinding, 7, sizeof(override_blinding)); memset(&override_blinding, 7, sizeof(override_blinding));
pubkey_from_privkey(&override_blinding, &override_blinding_pub); pubkey_from_privkey(&override_blinding, &override_blinding_pub);
enctlv[BOB] = create_enctlv(tmpctx, &blinding[BOB],
&id[BOB], &id[CAROL], NULL, tlv[BOB] = tlv_encrypted_data_tlv_new(tmpctx);
0, &override_blinding_pub, NULL, NULL, NULL, tlv[BOB]->next_node_id = &id[CAROL];
&blinding[CAROL], &alias[BOB]); tlv[BOB]->next_blinding_override = &override_blinding_pub;
enctlv[BOB] = encrypt_tlv_encrypted_data(tmpctx,
&blinding[BOB],
&id[BOB], tlv[BOB],
&blinding[CAROL],
&alias[BOB]);
/* That replaced the blinding */ /* That replaced the blinding */
blinding[CAROL] = override_blinding; blinding[CAROL] = override_blinding;
blinding_pub[CAROL] = override_blinding_pub; blinding_pub[CAROL] = override_blinding_pub;
enctlv[CAROL] = create_enctlv(tmpctx, &blinding[CAROL], tlv[CAROL] = tlv_encrypted_data_tlv_new(tmpctx);
&id[CAROL], &id[DAVE], NULL, tlv[CAROL]->next_node_id = &id[DAVE];
35, NULL, NULL, NULL, NULL, tlv[CAROL]->padding = tal_arrz(tlv[CAROL], u8, 35);
&blinding[DAVE], &alias[CAROL]); enctlv[CAROL] = encrypt_tlv_encrypted_data(tmpctx,
&blinding[CAROL],
&id[CAROL], tlv[CAROL],
&blinding[DAVE],
&alias[CAROL]);
for (size_t i = 0; i < sizeof(self_id); i++) for (size_t i = 0; i < sizeof(self_id); i++)
self_id.data[i] = i+1; self_id.data[i] = i+1;
enctlv[DAVE] = create_final_enctlv(tmpctx, &blinding[DAVE], &id[DAVE], tlv[DAVE] = tlv_encrypted_data_tlv_new(tmpctx);
0, &self_id, NULL, &alias[DAVE]); tlv[DAVE]->path_id = tal_dup_arr(tlv[DAVE], u8,
self_id.data, ARRAY_SIZE(self_id.data),
0);
enctlv[DAVE] = encrypt_tlv_encrypted_data(tmpctx,
&blinding[DAVE],
&id[DAVE], tlv[DAVE],
NULL,
&alias[DAVE]);
pubkey_from_privkey(&blinding[DAVE], &blinding_pub[DAVE]); pubkey_from_privkey(&blinding[DAVE], &blinding_pub[DAVE]);
/* Create an onion which encodes this. */ /* Create an onion which encodes this. */

View File

@@ -285,6 +285,7 @@ static struct command_result *json_blindedpath(struct command *cmd,
struct blinded_path *path; struct blinded_path *path;
size_t nhops; size_t nhops;
struct json_stream *response; struct json_stream *response;
struct tlv_encrypted_data_tlv *tlv;
if (!param(cmd, buffer, params, if (!param(cmd, buffer, params,
p_req("ids", param_pubkeys, &ids), p_req("ids", param_pubkeys, &ids),
@@ -319,27 +320,31 @@ static struct command_result *json_blindedpath(struct command *cmd,
blinding_iter = first_blinding; blinding_iter = first_blinding;
for (size_t i = 0; i < nhops - 1; i++) { for (size_t i = 0; i < nhops - 1; i++) {
path->path[i] = tal(path->path, struct onionmsg_hop); path->path[i] = tal(path->path, struct onionmsg_hop);
tlv = tlv_encrypted_data_tlv_new(tmpctx);
tlv->next_node_id = &ids[i+1];
/* FIXME: Pad? */
path->path[i]->encrypted_recipient_data path->path[i]->encrypted_recipient_data
= create_enctlv(path->path[i], = encrypt_tlv_encrypted_data(path->path[i],
&blinding_iter, &blinding_iter,
&ids[i], &ids[i],
&ids[i+1], NULL, tlv,
/* FIXME: Pad? */
0,
NULL, NULL, NULL, NULL,
&blinding_iter, &blinding_iter,
&path->path[i]->blinded_node_id); &path->path[i]->blinded_node_id);
} }
/* FIXME: Add padding! */ /* FIXME: Add padding! */
path->path[nhops-1] = tal(path->path, struct onionmsg_hop); path->path[nhops-1] = tal(path->path, struct onionmsg_hop);
tlv = tlv_encrypted_data_tlv_new(tmpctx);
tlv->path_id = (u8 *)tal_dup(tlv, struct secret,
&cmd->ld->onion_reply_secret);
path->path[nhops-1]->encrypted_recipient_data path->path[nhops-1]->encrypted_recipient_data
= create_final_enctlv(path->path[nhops-1], = encrypt_tlv_encrypted_data(path->path[nhops-1],
&blinding_iter, &blinding_iter,
&ids[nhops-1], &ids[nhops-1],
/* FIXME: Pad? */ tlv,
0,
&cmd->ld->onion_reply_secret,
NULL, NULL,
&path->path[nhops-1]->blinded_node_id); &path->path[nhops-1]->blinded_node_id);

View File

@@ -619,6 +619,7 @@ send_modern_message(struct command *cmd,
size_t nhops = tal_count(sent->path); size_t nhops = tal_count(sent->path);
struct tlv_onionmsg_tlv **payloads; struct tlv_onionmsg_tlv **payloads;
struct out_req *req; struct out_req *req;
struct tlv_encrypted_data_tlv *tlv;
/* Now create enctlvs for *forward* path. */ /* Now create enctlvs for *forward* path. */
randombytes_buf(&blinding_iter, sizeof(blinding_iter)); randombytes_buf(&blinding_iter, sizeof(blinding_iter));
@@ -634,14 +635,16 @@ send_modern_message(struct command *cmd,
for (size_t i = 1; i < nhops - 1; i++) { for (size_t i = 1; i < nhops - 1; i++) {
payloads[i] = tlv_onionmsg_tlv_new(payloads); payloads[i] = tlv_onionmsg_tlv_new(payloads);
payloads[i]->encrypted_recipient_data = create_enctlv(payloads[i],
tlv = tlv_encrypted_data_tlv_new(tmpctx);
tlv->next_node_id = &sent->path[i+1];
/* FIXME: Pad? */
payloads[i]->encrypted_recipient_data
= encrypt_tlv_encrypted_data(payloads[i],
&blinding_iter, &blinding_iter,
&sent->path[i], &sent->path[i],
&sent->path[i+1], tlv,
NULL,
/* FIXME: Pad? */
0,
NULL, NULL, NULL, NULL,
&blinding_iter, &blinding_iter,
&node_alias[i]); &node_alias[i]);
} }
@@ -649,9 +652,12 @@ send_modern_message(struct command *cmd,
payloads[nhops-1] = sending->payload; payloads[nhops-1] = sending->payload;
/* We don't include enctlv in final, but it gives us final alias */ /* We don't include enctlv in final, but it gives us final alias */
if (!create_final_enctlv(tmpctx, &blinding_iter, &sent->path[nhops-1], tlv = tlv_encrypted_data_tlv_new(tmpctx);
/* FIXME: Pad? */ 0, if (!encrypt_tlv_encrypted_data(tmpctx,
NULL, NULL, &blinding_iter,
&sent->path[nhops-1],
tlv,
NULL,
&node_alias[nhops-1])) { &node_alias[nhops-1])) {
/* Should not happen! */ /* Should not happen! */
return command_fail(cmd, LIGHTNINGD, return command_fail(cmd, LIGHTNINGD,
@@ -668,12 +674,12 @@ send_modern_message(struct command *cmd,
json_add_pubkey(req->js, "blinding", &fwd_blinding); json_add_pubkey(req->js, "blinding", &fwd_blinding);
json_array_start(req->js, "hops"); json_array_start(req->js, "hops");
for (size_t i = 1; i < nhops; i++) { for (size_t i = 1; i < nhops; i++) {
u8 *tlv; u8 *tlvbin;
json_object_start(req->js, NULL); json_object_start(req->js, NULL);
json_add_pubkey(req->js, "id", &node_alias[i]); json_add_pubkey(req->js, "id", &node_alias[i]);
tlv = tal_arr(tmpctx, u8, 0); tlvbin = tal_arr(tmpctx, u8, 0);
towire_tlv_onionmsg_tlv(&tlv, payloads[i]); towire_tlv_onionmsg_tlv(&tlvbin, payloads[i]);
json_add_hex_talarr(req->js, "tlv", tlv); json_add_hex_talarr(req->js, "tlv", tlvbin);
json_object_end(req->js); json_object_end(req->js);
} }
json_array_end(req->js); json_array_end(req->js);