clightning-dumpkeys.c (6611B)
1 2 #include "short_types.h" 3 #include "hkdf.h" 4 #include "compiler.h" 5 #include "secp256k1.h" 6 #include "bip32.h" 7 #include "hash.h" 8 #include "base58.h" 9 #include "descriptor.h" 10 11 #include <stdio.h> 12 #include <unistd.h> 13 #include <sys/types.h> 14 #include <fcntl.h> 15 #include <errno.h> 16 #include <assert.h> 17 18 #define BIP32_ENTROPY_LEN_256 32 19 20 #define fatal(fmt, ...) do { fprintf(stderr, fmt "\n", __VA_ARGS__); exit(1); } while (0) 21 #define fatal1(...) do { fprintf(stderr, __VA_ARGS__); exit(1); } while (0) 22 23 /* General 256-bit secret, which must be private. Used in various places. */ 24 struct secret { 25 u8 data[32]; 26 }; 27 28 static struct { 29 struct secret hsm_secret; 30 struct ext_key master; 31 struct ext_key parent_ext; 32 struct ext_key child_ext; 33 } secretstuff; 34 35 36 struct bip32_key_version { 37 u32 bip32_pubkey_version; 38 u32 bip32_privkey_version; 39 }; 40 41 42 43 /* Version codes for BIP32 extended keys in libwally-core. 44 * It's not suitable to add this struct into client struct, 45 * so set it static.*/ 46 static struct bip32_key_version bip32_key_version; 47 48 bool read_all(int fd, void *data, size_t size) 49 { 50 while (size) { 51 ssize_t done; 52 53 done = read(fd, data, size); 54 if (done < 0 && errno == EINTR) 55 continue; 56 if (done <= 0) 57 return false; 58 data = (char *)data + done; 59 size -= done; 60 } 61 62 return true; 63 } 64 65 66 67 static void populate_secretstuff(void) 68 { 69 u8 bip32_seed[BIP32_ENTROPY_LEN_256]; 70 u32 salt = 0; 71 /* struct ext_key master_extkey, child_extkey; */ 72 const u32 flags = SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN; 73 secp256k1_context *ctx = secp256k1_context_create(flags); 74 75 bip32_key_version = (struct bip32_key_version) { 76 .bip32_pubkey_version = BIP32_VER_MAIN_PUBLIC, 77 .bip32_privkey_version = BIP32_VER_MAIN_PRIVATE 78 }; 79 80 assert(bip32_key_version.bip32_pubkey_version == BIP32_VER_MAIN_PUBLIC 81 || bip32_key_version.bip32_pubkey_version == BIP32_VER_TEST_PUBLIC); 82 83 assert(bip32_key_version.bip32_privkey_version == BIP32_VER_MAIN_PRIVATE 84 || bip32_key_version.bip32_privkey_version == BIP32_VER_TEST_PRIVATE); 85 86 /* Fill in the BIP32 tree for bitcoin addresses. */ 87 /* In libwally-core, the version BIP32_VER_TEST_PRIVATE is for testnet/regtest, 88 * and BIP32_VER_MAIN_PRIVATE is for mainnet. For litecoin, we also set it like 89 * bitcoin else.*/ 90 do { 91 hkdf_sha256(bip32_seed, sizeof(bip32_seed), 92 &salt, sizeof(salt), 93 &secretstuff.hsm_secret, 94 sizeof(secretstuff.hsm_secret), 95 "bip32 seed", strlen("bip32 seed")); 96 salt++; 97 } while (bip32_key_from_seed(ctx, bip32_seed, sizeof(bip32_seed), 98 bip32_key_version.bip32_privkey_version, 99 0, &secretstuff.master) != WALLY_OK); 100 101 /* BIP 32: 102 * 103 * The default wallet layout 104 * 105 * An HDW is organized as several 'accounts'. Accounts are numbered, 106 * the default account ("") being number 0. Clients are not required 107 * to support more than one account - if not, they only use the 108 * default account. 109 * 110 * Each account is composed of two keypair chains: an internal and an 111 * external one. The external keychain is used to generate new public 112 * addresses, while the internal keychain is used for all other 113 * operations (change addresses, generation addresses, ..., anything 114 * that doesn't need to be communicated). Clients that do not support 115 * separate keychains for these should use the external one for 116 * everything. 117 * 118 * - m/iH/0/k corresponds to the k'th keypair of the external chain of 119 * account number i of the HDW derived from master m. 120 */ 121 /* Hence child 0, then child 0 again to get extkey to derive from. */ 122 if (bip32_key_from_parent(ctx, &secretstuff.master, 0, 123 BIP32_FLAG_KEY_PRIVATE, 124 &secretstuff.child_ext) != WALLY_OK) 125 /*~ status_failed() is a helper which exits and sends lightningd 126 * a message about what happened. For hsmd, that's fatal to 127 * lightningd. */ 128 fatal1("Can't derive child bip32 key"); 129 130 if (bip32_key_from_parent(ctx, &secretstuff.child_ext, 0, 131 BIP32_FLAG_KEY_PRIVATE, 132 &secretstuff.parent_ext) != WALLY_OK) 133 fatal1("Can't derive private bip32 key"); 134 } 135 136 static void load_hsm(const char *secretfile) 137 { 138 int fd = open(secretfile ? secretfile : "hsm_secret", O_RDONLY); 139 if (fd < 0) 140 fatal("opening: %s", strerror(errno)); 141 if (!read_all(fd, &secretstuff.hsm_secret, sizeof(secretstuff.hsm_secret))) 142 fatal("reading: %s", strerror(errno)); 143 close(fd); 144 145 populate_secretstuff(); 146 } 147 148 static int wally_free_string(char *str) 149 { 150 if (!str) 151 return WALLY_EINVAL; 152 wally_clear(str, strlen(str)); 153 free(str); 154 return WALLY_OK; 155 } 156 157 static inline size_t hex_str_size(size_t bytes) 158 { 159 return 2 * bytes + 1; 160 } 161 162 163 static char hexchar(unsigned int val) 164 { 165 if (val < 10) 166 return '0' + val; 167 if (val < 16) 168 return 'a' + val - 10; 169 abort(); 170 } 171 172 UNUSED static bool hex_encode(const void *buf, size_t bufsize, char *dest, 173 size_t destsize) 174 { 175 size_t i; 176 177 if (destsize < hex_str_size(bufsize)) 178 return false; 179 180 for (i = 0; i < bufsize; i++) { 181 unsigned int c = ((const unsigned char *)buf)[i]; 182 *(dest++) = hexchar(c >> 4); 183 *(dest++) = hexchar(c & 0xF); 184 } 185 *dest = '\0'; 186 187 return true; 188 } 189 190 static void print_key(struct ext_key *key, const char *name, int key_type, 191 const char *key_type_name) { 192 static u8 buf[128]; 193 static char cbuf[512]; 194 static char cbuf2[512]; 195 char *out; 196 197 int ret = bip32_key_serialize(key, key_type, buf, BIP32_SERIALIZED_LEN); 198 199 assert(ret == WALLY_OK); 200 201 wally_base58_from_bytes(buf, BIP32_SERIALIZED_LEN, 202 BASE58_FLAG_CHECKSUM, &out); 203 204 printf("%s\t%s %s\n", out, name, key_type_name); 205 206 if (!streq(name, "root")) { 207 snprintf(cbuf, sizeof(cbuf), "combo(%s/*)", out); 208 descriptor_checksum(cbuf, strlen(cbuf), cbuf2, sizeof(cbuf2)); 209 210 printf("%s#%s\t%s %s descriptor\n", cbuf, cbuf2, name, key_type_name); 211 } 212 wally_free_string(out); 213 214 } 215 216 static void dump_bip32(struct ext_key *key, const char *name) { 217 print_key(key, name, BIP32_FLAG_KEY_PRIVATE, "private"); 218 print_key(key, name, BIP32_FLAG_KEY_PUBLIC, "public"); 219 } 220 221 static int dump_xpriv(const char *secretfile) { 222 223 bip32_key_version = (struct bip32_key_version) 224 { .bip32_pubkey_version = BIP32_VER_MAIN_PUBLIC 225 , .bip32_privkey_version = BIP32_VER_MAIN_PRIVATE 226 }; 227 228 229 load_hsm(secretfile); 230 231 dump_bip32(&secretstuff.master, "root"); 232 printf("\n"); 233 dump_bip32(&secretstuff.parent_ext, "extended"); 234 /* printf("\n"); */ 235 /* dump_bip32(&secretstuff.child_ext, "extended internal"); */ 236 237 238 return 0; 239 } 240 241 void usage() 242 { 243 fprintf(stderr, "usage: clightning-dumpkeys <hsmd_secretfile>\n"); 244 exit(42); 245 } 246 247 int main(int argc, char *argv[]) 248 { 249 if (argc != 2) 250 usage(); 251 252 const char *secretfile = argv[1]; 253 254 dump_xpriv(secretfile); 255 256 return 0; 257 }