From 889216e0a960ab3b875d66b259ca13d92863b64f Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Sat, 12 Oct 2019 04:36:01 +1030 Subject: [PATCH] hsmd: add support for signing a lightning msg from nodeid. Signed-off-by: Rusty Russell --- hsmd/hsm_wire.csv | 8 ++++++++ hsmd/hsmd.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/hsmd/hsm_wire.csv b/hsmd/hsm_wire.csv index e43d99114..05604082f 100644 --- a/hsmd/hsm_wire.csv +++ b/hsmd/hsm_wire.csv @@ -198,3 +198,11 @@ msgdata,hsm_check_future_secret,commitment_secret,secret, msgtype,hsm_check_future_secret_reply,122 msgdata,hsm_check_future_secret_reply,correct,bool, + +# lightningd asks us to sign a string. +msgtype,hsm_sign_message,23 +msgdata,hsm_sign_message,len,u16, +msgdata,hsm_sign_message,msg,u8,len + +msgtype,hsm_sign_message_reply,123 +msgdata,hsm_sign_message_reply,sig,secp256k1_ecdsa_recoverable_signature, diff --git a/hsmd/hsmd.c b/hsmd/hsmd.c index a8f60a6f8..af33f8a44 100644 --- a/hsmd/hsmd.c +++ b/hsmd/hsmd.c @@ -1765,6 +1765,48 @@ static struct io_plan *handle_sign_node_announcement(struct io_conn *conn, return req_reply(conn, c, take(reply)); } +/*~ lightningd asks us to sign a message. I tweeted the spec + * in https://twitter.com/rusty_twit/status/1182102005914800128: + * + * @roasbeef & @bitconner point out that #lnd algo is: + * zbase32(SigRec(SHA256(SHA256("Lightning Signed Message:" + msg)))). + * zbase32 from https://philzimmermann.com/docs/human-oriented-base-32-encoding.txt + * and SigRec has first byte 31 + recovery id, followed by 64 byte sig. #specinatweet + */ +static struct io_plan *handle_sign_message(struct io_conn *conn, + struct client *c, + const u8 *msg_in) +{ + u8 *msg; + struct sha256_ctx sctx = SHA256_INIT; + struct sha256_double shad; + secp256k1_ecdsa_recoverable_signature rsig; + struct privkey node_pkey; + + if (!fromwire_hsm_sign_message(tmpctx, msg_in, &msg)) + return bad_req(conn, c, msg_in); + + /* Prefixing by a known string means we'll never be convinced + * to sign some gossip message, etc. */ + sha256_update(&sctx, "Lightning Signed Message:", + strlen("Lightning Signed Message:")); + sha256_update(&sctx, msg, tal_count(msg)); + sha256_double_done(&sctx, &shad); + + node_key(&node_pkey, NULL); + /*~ By no small coincidence, this libsecp routine uses the exact + * recovery signature format mandated by BOLT 11. */ + if (!secp256k1_ecdsa_sign_recoverable(secp256k1_ctx, &rsig, + shad.sha.u.u8, + node_pkey.secret.data, + NULL, NULL)) { + return bad_req_fmt(conn, c, msg_in, "Failed to sign message"); + } + + return req_reply(conn, c, + take(towire_hsm_sign_message_reply(NULL, &rsig))); +} + #if DEVELOPER static struct io_plan *handle_memleak(struct io_conn *conn, struct client *c, @@ -1844,6 +1886,7 @@ static bool check_client_capabilities(struct client *client, case WIRE_HSM_SIGN_COMMITMENT_TX: case WIRE_HSM_GET_CHANNEL_BASEPOINTS: case WIRE_HSM_DEV_MEMLEAK: + case WIRE_HSM_SIGN_MESSAGE: return (client->capabilities & HSM_CAP_MASTER) != 0; /*~ These are messages sent by the HSM so we should never receive them. */ @@ -1865,6 +1908,7 @@ static bool check_client_capabilities(struct client *client, case WIRE_HSM_CHECK_FUTURE_SECRET_REPLY: case WIRE_HSM_GET_CHANNEL_BASEPOINTS_REPLY: case WIRE_HSM_DEV_MEMLEAK_REPLY: + case WIRE_HSM_SIGN_MESSAGE_REPLY: break; } return false; @@ -1945,6 +1989,8 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) case WIRE_HSM_SIGN_MUTUAL_CLOSE_TX: return handle_sign_mutual_close_tx(conn, c, c->msg_in); + case WIRE_HSM_SIGN_MESSAGE: + return handle_sign_message(conn, c, c->msg_in); #if DEVELOPER case WIRE_HSM_DEV_MEMLEAK: return handle_memleak(conn, c, c->msg_in); @@ -1967,6 +2013,7 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) case WIRE_HSM_CHECK_FUTURE_SECRET_REPLY: case WIRE_HSM_GET_CHANNEL_BASEPOINTS_REPLY: case WIRE_HSM_DEV_MEMLEAK_REPLY: + case WIRE_HSM_SIGN_MESSAGE_REPLY: break; }