Skip to content

Commit c4deb1e

Browse files
committed
add devtool/bip137-checkmessage utility
To validate BIP137 signatures produced by core-lightning in tests. Changelog-None. Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
1 parent 50df1cd commit c4deb1e

File tree

3 files changed

+79
-1
lines changed

3 files changed

+79
-1
lines changed

devtools/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@ topology
2020
fp16
2121
rune
2222
gossmap-compress
23+
bip137-checkmessage

devtools/Makefile

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
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
1+
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-checkmessage
22
ifeq ($(HAVE_SQLITE3),1)
33
DEVTOOLS += devtools/checkchannels
44
endif
@@ -99,6 +99,8 @@ devtools/mkquery: $(DEVTOOLS_COMMON_OBJS) $(BITCOIN_OBJS) wire/fromwire.o wire/t
9999

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

102+
devtools/bip137-checkmessage: $(DEVTOOLS_COMMON_OBJS) $(BITCOIN_OBJS) wire/fromwire.o wire/towire.o devtools/bip137-checkmessage.o
103+
102104
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
103105

104106
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

devtools/bip137-checkmessage.c

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#include "config.h"
2+
#include <bitcoin/pubkey.h>
3+
#include <bitcoin/shadouble.h>
4+
#include <bitcoin/varint.h>
5+
#include <ccan/err/err.h>
6+
#include <common/bech32.h>
7+
#include <common/utils.h>
8+
#include <secp256k1_recovery.h>
9+
#include <stdio.h>
10+
#include <wally_core.h>
11+
12+
/* FIXME: should we check signatures against addresses instead of keys? */
13+
static void usage(void)
14+
{
15+
fprintf(stderr, "Usage: bip137-checkmessage message hex-sig [key]\n"
16+
"If key does not match, signature is not valid!\n");
17+
exit(1);
18+
}
19+
20+
int main(int argc, char *argv[])
21+
{
22+
u8 *sig;
23+
u8 varint[VARINT_MAX_LEN];
24+
size_t varintlen, msg_len;
25+
secp256k1_ecdsa_recoverable_signature rsig;
26+
struct sha256_ctx sctx = SHA256_INIT;
27+
struct sha256_double shad;
28+
struct pubkey reckey;
29+
const char *keystr;
30+
31+
setup_locale();
32+
err_set_progname(argv[0]);
33+
wally_init(0);
34+
secp256k1_ctx = wally_get_secp_context();
35+
36+
if (argc != 3 && argc != 4)
37+
usage();
38+
39+
sig = tal_hexdata(NULL, argv[2], strlen(argv[2]));
40+
if (!sig)
41+
errx(1, "Not a valid hex string");
42+
43+
if (sig[0] < 39 || sig[0] >= 43)
44+
errx(1,
45+
"Signature header does not correspond to a P2WPKH type");
46+
47+
if (!secp256k1_ecdsa_recoverable_signature_parse_compact(
48+
secp256k1_ctx, &rsig, sig + 1, sig[0] - 39))
49+
errx(1, "Signature not parsable");
50+
51+
sha256_update(&sctx,
52+
"\x18"
53+
"Bitcoin Signed Message:\n",
54+
strlen("\x18"
55+
"Bitcoin Signed Message:\n"));
56+
msg_len = strlen(argv[1]);
57+
varintlen = varint_put(varint, msg_len);
58+
sha256_update(&sctx, varint, varintlen);
59+
sha256_update(&sctx, argv[1], msg_len);
60+
sha256_double_done(&sctx, &shad);
61+
62+
if (!secp256k1_ecdsa_recover(secp256k1_ctx, &reckey.pubkey, &rsig,
63+
shad.sha.u.u8))
64+
errx(1, "Signature not recoverable");
65+
66+
keystr = fmt_pubkey(NULL, &reckey);
67+
if (argv[3]) {
68+
if (!streq(keystr, argv[3]))
69+
errx(1, "Signature is invalid");
70+
printf("Signature is valid!\n");
71+
} else
72+
printf("Signature claims to be from key %s\n", keystr);
73+
return 0;
74+
}
75+

0 commit comments

Comments
 (0)