diff --git a/doc/beginners-guide/backup.md b/doc/beginners-guide/backup.md index 9811b9d26..09a24c5a8 100644 --- a/doc/beginners-guide/backup.md +++ b/doc/beginners-guide/backup.md @@ -63,11 +63,12 @@ chmod 0400 hsm_secret ``` -#### Codex32 Format +#### Readable Format -Run `tools/lightning-hsmtool getcodexsecret ` to get the `hsm_secret` in codex32 format. +Run `tools/lightning-hsmtool getsecret ` to get the `hsm_secret` mnemonic (12 words). For older +nodes, you will get a codex32 string instead, and must supply a four-letter id to attach to it, like so: -Example `tools/lightning-hsmtool getcodexsecret ~/.lightning/bitcoin/hsm_secret adt0`. +Example `tools/lightning-hsmtool getsecret ~/.lightning/bitcoin/hsm_secret adt0`. `hsm/secret/path` in the above command is `$LIGHTNINGDIR/hsm_secret`, and `id` is any 4 character string used to identify this secret. It **cannot** contain `i`, `o`, or `b`, but **can** contain all digits except `1`. diff --git a/doc/developers-guide/deprecated-features.md b/doc/developers-guide/deprecated-features.md index 5da91a552..f8cd848a6 100644 --- a/doc/developers-guide/deprecated-features.md +++ b/doc/developers-guide/deprecated-features.md @@ -26,7 +26,7 @@ privacy: | encrypted_hsm | Config | v25.12 | v26.12 | `hsm-passphrase` is a name which also makes sense for modern hsm_secrets which use BIP 39 | | newaddr.addresstype.defaultbech32 | Parameter | v25.12 | v26.12 | Use `p2tr` in the response (present since v23.08 if `addresstype` is `p2tr`, and always present since v24.12). | | channel_state_changed.null_message | Notification Field | v25.12 | v26.12 | In channel_state_changed notification, `message` will be missing instead of `null` | - +| hsmtool.getcodexsecret | Command | v25.12.1 | v26.12 | Doesn't work on nodes using mnemonic secrets (v25.12 or later). Use `getsecret` instead. | Inevitably there are features which need to change: either to be generalized, or removed when they can no longer be supported. Types of deprecation: diff --git a/doc/lightning-hsmtool.8.md b/doc/lightning-hsmtool.8.md index e198d6cfb..a9f6610ff 100644 --- a/doc/lightning-hsmtool.8.md +++ b/doc/lightning-hsmtool.8.md @@ -88,8 +88,11 @@ the last parameter. By default, mainnet-encoded keys are generated. This produces the same results as lightning-commando-rune(7) on a fresh node. You will still need to create a rune once the node starts, if you want commando to work (as it is only activated once it has generated one). +**getsecret** *hsm\_secret\_path* [*id*] + Extract the secret from the `hsm_secret` file and print it out, for use with `--recover`. This is usually a 12-word mnemonic, but for pre-v25.12 nodes, a 4-character `id` is needed to generate a BIP-93 formatted HSM secret (e.g. `ad00`): it cannot contain `i`, `o`, or `b`, but can contain digits except `1`. + **getcodexsecret** *hsm\_secret\_path* *id* - Print out the BIP-93 formatted HSM secret, for use with `--recover`. The `id` is any 4 character string you can use to identify this secret (e.g. `ad00`): it cannot contain `i`, `o`, or `b`, but can contain digits except `1`. + Deprecated alias for getsecret: only works on older (pre-v25.12) nodes. **getemergencyrecover** *emergency.recover\_path* Print out the bech32 encoded emergency.recover file. diff --git a/tests/test_wallet.py b/tests/test_wallet.py index a9a86f0d0..40282125c 100644 --- a/tests/test_wallet.py +++ b/tests/test_wallet.py @@ -1649,7 +1649,7 @@ def test_hsmtool_all_commands_work_with_mnemonic_formats(node_factory): # Test various commands work with mnemonic format test_commands = [ (["getnodeid", hsm_path], "03653e90c1ce4660fd8505dd6d643356e93cfe202af109d382787639dd5890e87d"), - (["getcodexsecret", hsm_path, "test"], "cl10testst6cqh0wu7p5ssjyf4z4ez42ks9jlt3zneju9uuypr2hddak6tlqsghuxusm6m6azq"), + (["getsecret", hsm_path], "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"), (["makerune", hsm_path], "6VkrWMI2hm2a2UTkg-EyUrrBJN0RcuPB80I1pCVkTD89MA=="), (["dumponchaindescriptors", hsm_path], "wpkh(xpub661MyMwAqRbcG9kjo3mdWQuSDbtdJzsd3K2mvifyeUMF3GhLcBAfELqjuxCvxUkYqQVe6rJ9SzmpipoUedb5MD79MJaLL8RME2A3J3Fw6Zd/0/0/*)#2jtshmk0\nsh(wpkh(xpub661MyMwAqRbcG9kjo3mdWQuSDbtdJzsd3K2mvifyeUMF3GhLcBAfELqjuxCvxUkYqQVe6rJ9SzmpipoUedb5MD79MJaLL8RME2A3J3Fw6Zd/0/0/*))#u6am4was\ntr(xpub661MyMwAqRbcG9kjo3mdWQuSDbtdJzsd3K2mvifyeUMF3GhLcBAfELqjuxCvxUkYqQVe6rJ9SzmpipoUedb5MD79MJaLL8RME2A3J3Fw6Zd/0/0/*)#v9hf4756"), ] diff --git a/tools/lightning-hsmtool.c b/tools/lightning-hsmtool.c index a3f487a10..ca5bf542c 100644 --- a/tools/lightning-hsmtool.c +++ b/tools/lightning-hsmtool.c @@ -56,7 +56,7 @@ static void show_usage(const char *progname) printf(" - checkhsm \n"); printf(" - dumponchaindescriptors [--show-secrets] [network]\n"); printf(" - makerune \n"); - printf(" - getcodexsecret \n"); + printf(" - getsecret []\n"); printf(" - getemergencyrecover \n"); printf(" - getnodeid \n"); exit(0); @@ -269,20 +269,40 @@ static void get_channel_seed(struct secret *channel_seed, const struct node_id * info, strlen(info)); } -static void print_codexsecret(const char *hsm_secret_path, const char *id) +static void print_secret(const char *hsm_secret_path, const char *id, bool must_be_oldstyle) { struct secret hsm_secret; char *bip93; const char *err; struct hsm_secret *hsms = load_hsm_secret(tmpctx, hsm_secret_path); - /* Extract first 32 bytes for legacy compatibility */ - memcpy(hsm_secret.data, hsms->secret_data, 32); - err = codex32_secret_encode(tmpctx, "cl", id, 0, hsm_secret.data, 32, &bip93); - if (err) - errx(ERROR_USAGE, "%s", err); + switch (hsms->type) { + case HSM_SECRET_ENCRYPTED: + errx(ERROR_USAGE, "Encrypted hsm_secret"); + case HSM_SECRET_MNEMONIC_NO_PASS: + if (must_be_oldstyle) + errx(ERROR_USAGE, "Cannot use getcodexsecret with modern nodes: use getsecret"); + printf("%s\n", hsms->mnemonic); + return; + case HSM_SECRET_MNEMONIC_WITH_PASS: + errx(ERROR_USAGE, "hsm_secret with passphrase"); + case HSM_SECRET_PLAIN: + if (id == NULL) + errx(ERROR_USAGE, "Must set 'id' for a codex32 secret"); + /* Extract first 32 bytes for legacy compatibility */ + memcpy(hsm_secret.data, hsms->secret_data, 32); - printf("%s\n", bip93); + err = codex32_secret_encode(tmpctx, "cl", id, 0, hsm_secret.data, 32, &bip93); + if (err) + errx(ERROR_USAGE, "%s", err); + + printf("%s\n", bip93); + return; + case HSM_SECRET_INVALID: + break; + } + /* Never happens. */ + abort(); } static void print_emergencyrecover(const char *emer_rec_path) @@ -745,10 +765,14 @@ int main(int argc, char *argv[]) if (argc < 3) show_usage(argv[0]); make_rune(argv[2]); + } else if(streq(method, "getsecret")) { + if (argc < 3) + show_usage(argv[0]); + print_secret(argv[2], argv[3], false); } else if(streq(method, "getcodexsecret")) { if (argc < 4) show_usage(argv[0]); - print_codexsecret(argv[2], argv[3]); + print_secret(argv[2], argv[3], true); } else if(streq(method, "getemergencyrecover")) { if (argc < 3) show_usage(argv[0]);