Skip to content

Signmessage #8226

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion common/hsm_version.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
* v6 no secret from get_per_commitment_point: 0cad1790beb3473d64355f4cb4f64daa80c28c8a241998b7ef0223385d7ffff9
* v6 with sign_bolt12_2 (tweak using node id): 8fcb731279a10af3f95aeb8be1da6b2ced76a1984afa18c5f46a03515d70ea0e
* v6 with dev_warn_on_overgrind: a273b68e19336073e551c01a78bcd1e1f8cc510da7d0dde3afc45e249f9830cc
*/
* v6 with bip137_sign_message: 4bfe28b02e92aae276b8eca2228e32f32d5dee8d5381639e7364939fa2fa1370
*/
#define HSM_MIN_VERSION 5
#define HSM_MAX_VERSION 6
#endif /* LIGHTNING_COMMON_HSM_VERSION_H */
93 changes: 93 additions & 0 deletions contrib/msggen/msggen/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -32878,6 +32878,99 @@
}
]
},
"signmessagewithkey.json": {
"$schema": "../rpc-schema-draft.json",
"type": "object",
"rpc": "signmessagewithkey",
"title": "Command to create a signature using a key from the wallet",
"description": [
"The **signmessagewithkey** RPC command creates a digital signature of *message* using the key associated with the address provided in the input.",
"The signature scheme follows the BIP137 specification."
],
"added": "v25.05",
"request": {
"required": [
"message",
"address"
],
"additionalProperties": false,
"properties": {
"message": {
"type": "string",
"description": [
"Less than 65536 characters long message to be signed by the node."
]
},
"address": {
"type": "string",
"description": [
"A Bitcoin accepted type address for lookup in the list of addresses issued to date.",
"Only P2WPKH type addresses are supported"
]
}
}
},
"response": {
"required": [
"address",
"pubkey",
"signature",
"base64"
],
"additionalProperties": false,
"properties": {
"address": {
"type": "string",
"description": [
"The bitcoin address used for signing."
]
},
"pubkey": {
"type": "pubkey",
"description": [
"The public key associated with the bitcoin address provided."
]
},
"signature": {
"type": "hex",
"description": [
"The signature."
]
},
"base64": {
"type": "string",
"description": [
"The signature encoded in base64."
]
}
}
},
"author": [
"Lagrang3 <<[email protected]>> is mainly responsible."
],
"see_also": [],
"resources": [
"Main web site: <https://github.com/ElementsProject/lightning>"
],
"examples": [
{
"request": {
"id": "example:signmessagewithkey#1",
"method": "signmessagewithkey",
"params": {
"message": "a test message",
"address": "bcrt1qgrh5vtf63mtayzhxwp480aww3j3qfr5qpq65un"
}
},
"response": {
"address": "bcrt1qgrh5vtf63mtayzhxwp480aww3j3qfr5qpq65un",
"pubkey": "03bc4a456585ba21ba26af4a0e5399ec76410b2e0ca67db0f3bcb2f47b232fa4b0",
"signature": "28564edf260a72d991cbb38cf608e293124f8b8f478d13d4544fe27b9d76c65df1284ca395ccdfd3d5f151729ef18f56c028f5f860155d6aa4d0aaaa176a00db01",
"base64": "KFZO3yYKctmRy7OM9gjikxJPi49HjRPUVE/ie512xl3xKEyjlczf09XxUXKe8Y9WwCj1+GAVXWqk0KqqF2oA2wE="
}
}
]
},
"signpsbt.json": {
"$schema": "../rpc-schema-draft.json",
"type": "object",
Expand Down
1 change: 1 addition & 0 deletions devtools/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ topology
fp16
rune
gossmap-compress
bip137-verifysignature
4 changes: 3 additions & 1 deletion devtools/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
DEVTOOLS := devtools/bolt11-cli devtools/decodemsg devtools/onion devtools/dump-gossipstore devtools/gossipwith devtools/create-gossipstore devtools/mkcommit devtools/mkfunding devtools/mkclose devtools/mkgossip devtools/mkencoded devtools/mkquery devtools/lightning-checkmessage devtools/topology devtools/route devtools/bolt12-cli devtools/encodeaddr devtools/features devtools/fp16 devtools/rune devtools/gossmap-compress
DEVTOOLS := devtools/bolt11-cli devtools/decodemsg devtools/onion devtools/dump-gossipstore devtools/gossipwith devtools/create-gossipstore devtools/mkcommit devtools/mkfunding devtools/mkclose devtools/mkgossip devtools/mkencoded devtools/mkquery devtools/lightning-checkmessage devtools/topology devtools/route devtools/bolt12-cli devtools/encodeaddr devtools/features devtools/fp16 devtools/rune devtools/gossmap-compress devtools/bip137-verifysignature
ifeq ($(HAVE_SQLITE3),1)
DEVTOOLS += devtools/checkchannels
endif
Expand Down Expand Up @@ -99,6 +99,8 @@ devtools/mkquery: $(DEVTOOLS_COMMON_OBJS) $(BITCOIN_OBJS) wire/fromwire.o wire/t

devtools/lightning-checkmessage: $(DEVTOOLS_COMMON_OBJS) $(BITCOIN_OBJS) wire/fromwire.o wire/towire.o devtools/lightning-checkmessage.o

devtools/bip137-verifysignature: $(DEVTOOLS_COMMON_OBJS) $(BITCOIN_OBJS) wire/fromwire.o wire/towire.o devtools/bip137-verifysignature.o

devtools/route: $(DEVTOOLS_COMMON_OBJS) $(BITCOIN_OBJS) wire/fromwire.o wire/towire.o wire/tlvstream.o common/gossmap.o common/fp16.o common/random_select.o common/route.o common/dijkstra.o devtools/clean_topo.o devtools/route.o

devtools/topology: $(DEVTOOLS_COMMON_OBJS) $(BITCOIN_OBJS) wire/fromwire.o wire/towire.o wire/tlvstream.o common/gossmap.o common/fp16.o common/random_select.o common/dijkstra.o common/route.o devtools/clean_topo.o devtools/topology.o
114 changes: 114 additions & 0 deletions devtools/bip137-verifysignature.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#include "config.h"
#include <assert.h>
#include <bitcoin/base58.h>
#include <bitcoin/pubkey.h>
#include <bitcoin/shadouble.h>
#include <bitcoin/varint.h>
#include <ccan/err/err.h>
#include <common/addr.h>
#include <common/bech32.h>
#include <common/utils.h>
#include <secp256k1_recovery.h>
#include <stdio.h>
#include <wally_core.h>

static void usage(void)
{
fprintf(stderr,
"Usage: bip137-verifysignature message hex-sig [address] [network]\n"
"If key does not match, signature is not valid!\n");
exit(1);
}

static char *encode_pubkey_to_p2wpkh_addr(const tal_t *ctx,
const struct pubkey *pubkey,
const struct chainparams *chain)
{
char *out;
const char *hrp;
struct ripemd160 h160;
bool ok;
hrp = chain->onchain_hrp;

/* out buffer is 73 + strlen(human readable part),
* see common/bech32.h*/
out = tal_arr(ctx, char, 73 + strlen(hrp));
pubkey_to_hash160(pubkey, &h160);
ok = segwit_addr_encode(out, hrp, 0, h160.u.u8, sizeof(h160));
if(!ok)
tal_free(out);
return out;
}

int main(int argc, char *argv[])
{
u8 *sig;
u8 varint[VARINT_MAX_LEN];
size_t varintlen, msg_len;
secp256k1_ecdsa_recoverable_signature rsig;
struct sha256_ctx sctx = SHA256_INIT;
struct sha256_double shad;
struct pubkey reckey;
const char *addr;
const struct chainparams *chain = NULL;
const char *input_chain = NULL, *input_address = NULL;

setup_locale();
err_set_progname(argv[0]);
wally_init(0);
secp256k1_ctx = wally_get_secp_context();

if (argc != 3 && argc != 4 && argc != 5)
usage();
if (argc > 3)
input_address = argv[3];
if (argc > 4)
input_chain = argv[4];

sig = tal_hexdata(NULL, argv[2], strlen(argv[2]));
if (!sig)
errx(1, "Not a valid hex string");

if (sig[0] < 39 || sig[0] >= 43)
errx(1,
"Signature header does not correspond to a P2WPKH type");

if (!secp256k1_ecdsa_recoverable_signature_parse_compact(
secp256k1_ctx, &rsig, sig + 1, sig[0] - 39))
errx(1, "Signature not parsable");

sha256_update(&sctx,
"\x18"
"Bitcoin Signed Message:\n",
strlen("\x18"
"Bitcoin Signed Message:\n"));
msg_len = strlen(argv[1]);
varintlen = varint_put(varint, msg_len);
sha256_update(&sctx, varint, varintlen);
sha256_update(&sctx, argv[1], msg_len);
sha256_double_done(&sctx, &shad);

if (!secp256k1_ecdsa_recover(secp256k1_ctx, &reckey.pubkey, &rsig,
shad.sha.u.u8))
errx(1, "Signature not recoverable");

if (input_chain) {
chain = chainparams_for_network(input_chain);
if (!chain)
errx(1, "Invalid network");
} else {
/* By default, assume we are verifying a mainnet signature. */
chain = chainparams_for_network("bitcoin");
}
addr = encode_pubkey_to_p2wpkh_addr(NULL, &reckey, chain);
if (!addr)
errx(1, "Failed to derive address from recovered key");
if (input_address) {
if (!streq(addr, input_address))
errx(1, "Signature is invalid");
printf("Signature is valid!\n");
} else
printf("Signature claims to be from address %s\n", addr);
return 0;
}

93 changes: 93 additions & 0 deletions doc/schemas/signmessagewithkey.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
{
"$schema": "../rpc-schema-draft.json",
"type": "object",
"rpc": "signmessagewithkey",
"title": "Command to create a signature using a key from the wallet",
"description": [
"The **signmessagewithkey** RPC command creates a digital signature of *message* using the key associated with the address provided in the input.",
"The signature scheme follows the BIP137 specification."
],
"added": "v25.05",
"request": {
"required": [
"message",
"address"
],
"additionalProperties": false,
"properties": {
"message": {
"type": "string",
"description": [
"Less than 65536 characters long message to be signed by the node."
]
},
"address": {
"type": "string",
"description": [
"A Bitcoin accepted type address for lookup in the list of addresses issued to date.",
"Only P2WPKH type addresses are supported"
]
}
}
},
"response": {
"required": [
"address",
"pubkey",
"signature",
"base64"
],
"additionalProperties": false,
"properties": {
"address": {
"type": "string",
"description": [
"The bitcoin address used for signing."
]
},
"pubkey": {
"type": "pubkey",
"description": [
"The public key associated with the bitcoin address provided."
]
},
"signature": {
"type": "hex",
"description": [
"The signature."
]
},
"base64": {
"type": "string",
"description": [
"The signature encoded in base64."
]
}
}
},
"author": [
"Lagrang3 <<[email protected]>> is mainly responsible."
],
"see_also": [],
"resources": [
"Main web site: <https://github.com/ElementsProject/lightning>"
],
"examples": [
{
"request": {
"id": "example:signmessagewithkey#1",
"method": "signmessagewithkey",
"params": {
"message": "a test message",
"address": "bcrt1qgrh5vtf63mtayzhxwp480aww3j3qfr5qpq65un"
}
},
"response": {
"address": "bcrt1qgrh5vtf63mtayzhxwp480aww3j3qfr5qpq65un",
"pubkey": "03bc4a456585ba21ba26af4a0e5399ec76410b2e0ca67db0f3bcb2f47b232fa4b0",
"signature": "28564edf260a72d991cbb38cf608e293124f8b8f478d13d4544fe27b9d76c65df1284ca395ccdfd3d5f151729ef18f56c028f5f860155d6aa4d0aaaa176a00db01",
"base64": "KFZO3yYKctmRy7OM9gjikxJPi49HjRPUVE/ie512xl3xKEyjlczf09XxUXKe8Y9WwCj1+GAVXWqk0KqqF2oA2wE="
}
}
]
}
2 changes: 2 additions & 0 deletions hsmd/hsmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,7 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c)
case WIRE_HSMD_GET_CHANNEL_BASEPOINTS:
case WIRE_HSMD_SIGN_INVOICE:
case WIRE_HSMD_SIGN_MESSAGE:
case WIRE_HSMD_BIP137_SIGN_MESSAGE:
case WIRE_HSMD_SIGN_OPTION_WILL_FUND_OFFER:
case WIRE_HSMD_SIGN_BOLT12:
case WIRE_HSMD_SIGN_BOLT12_2:
Expand Down Expand Up @@ -748,6 +749,7 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c)
case WIRE_HSMD_GET_CHANNEL_BASEPOINTS_REPLY:
case WIRE_HSMD_DEV_MEMLEAK_REPLY:
case WIRE_HSMD_SIGN_MESSAGE_REPLY:
case WIRE_HSMD_BIP137_SIGN_MESSAGE_REPLY:
case WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY_REPLY:
case WIRE_HSMD_SIGN_BOLT12_REPLY:
case WIRE_HSMD_SIGN_BOLT12_2_REPLY:
Expand Down
9 changes: 9 additions & 0 deletions hsmd/hsmd_wire.csv
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,15 @@ msgdata,hsmd_sign_message,msg,u8,len
msgtype,hsmd_sign_message_reply,123
msgdata,hsmd_sign_message_reply,sig,secp256k1_ecdsa_recoverable_signature,

# sign a raw message with a derived key
msgtype,hsmd_bip137_sign_message,45
msgdata,hsmd_bip137_sign_message,len,u16,
msgdata,hsmd_bip137_sign_message,msg,u8,len
msgdata,hsmd_bip137_sign_message,keyidx,u32,

msgtype,hsmd_bip137_sign_message_reply,145
msgdata,hsmd_bip137_sign_message_reply,sig,secp256k1_ecdsa_recoverable_signature,

# lightningd needs to get a scriptPubkey for a utxo with closeinfo
msgtype,hsmd_get_output_scriptpubkey,24
msgdata,hsmd_get_output_scriptpubkey,channel_id,u64,
Expand Down
Loading
Loading