-
Notifications
You must be signed in to change notification settings - Fork 872
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
Feature to export bip32 root key as mnemonic or xprv? #1762
Comments
as is documented at: https://github.com/hkjn/lnhw/tree/master/doc/hsmd the hsm_secret is basically just a 32 Byte secrete. which of course could be transfered to a bip39 mnemonic wordlist. On the other side bip39 is already implemented in libwally (c.f.: https://github.com/ElementsProject/libwally-core/blob/master/src/bip39.c ) which is used within c-lighting. So I guess yes it would be easy to provide an API for it. Has this not been done because it was low priority or are there other reasons against this? @peertrade one reason why it is not less useful for a lightning node in comparison to a bitcoin to do that is that you would only be able to derive your onchain funds but for your payment channels you need to stare the state which in general is much lager than 32 bytes. so you wouldn't be able to recover those anyway. |
@renepickhardt thx for your comments. I get your point about needing the state for lightning channels, but really my concern is about on-chain funds that have been added to the internal wallet, so I still hope for a simple way to obtain xprv from the hsm_seed for use by other tools. I suppose that for offline backup right now, base64 encoding hsm_secret file is viable strategy, eg:
|
you can get the xprv with the following python script which was basically written by @stepansnigirev ( https://github.com/stepansnigirev )
|
Notice that we are planning to consolidate our derivation structure to the one that |
Independently of your comment I have tried to provide a patch which lists the I have several questions:
|
@renepickhardt thx for the python script. I tried to run it but it imports some files I'm missing. What deps do I need to install?
|
This topic is discussed in #746. FWIW I vote against an rpc call. |
@peertrade yeah you are missing a dependency which is also written by @stepansnigirev sorry didn't realize that. He said he would release his code soon. I don't want to publish all this stuff |
@peertrade , the script relies on hd.py from this repo: https://github.com/jimmysong/pybtcfork |
ok, I got the python script working (by running it inside pybtcfork dir) and it generated an xprv. But the pubkey of first address generated by bip32.org does not match that of lightning-cli dev-listaddrs, so I think there is an error in my process.
From my reading of hsmd doc, I think the path should just be m/0, but I also tried m/0/0/0 both hardened and unhardened with no match on pubkey. I am attaching the hsm_secret file tgz'd. ( no funds, only for testing, don't worry ). Can anyone show me where I'm going wrong? |
on https://iancoleman.io/bip39/
it should list the public keys and they should be the same. Here's a patch that gets lightning_hsmd to dump a privkey on command: From 85e27993237e27150bf503af22699ee4c34aff6a Mon Sep 17 00:00:00 2001
From: William Casarin <jb55@jb55.com>
Date: Wed, 1 Aug 2018 00:23:12 -0700
Subject: [PATCH] hsm: dump privkey command
---
hsmd/hsm.c | 37 ++++++++++++++++++++++++++++++++++---
1 file changed, 34 insertions(+), 3 deletions(-)
diff --git a/hsmd/hsm.c b/hsmd/hsm.c
index 6c62a3f5..dedad1fd 100644
--- a/hsmd/hsm.c
+++ b/hsmd/hsm.c
@@ -42,6 +42,8 @@
#include <wire/gen_peer_wire.h>
#include <wire/wire_io.h>
+#include <libbase58.h>
+
#define REQ_FD 3
/* Nobody will ever find it here! */
@@ -1060,9 +1062,9 @@ static void maybe_create_new_hsm(void)
status_unusual("HSM: created new hsm_secret file");
}
-static void load_hsm(void)
+static void load_hsm(const char *secretfile)
{
- int fd = open("hsm_secret", O_RDONLY);
+ int fd = open(secretfile ? secretfile : "hsm_secret", O_RDONLY);
if (fd < 0)
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"opening: %s", strerror(errno));
@@ -1081,7 +1083,7 @@ static void init_hsm(struct daemon_conn *master, const u8 *msg)
master_badmsg(WIRE_HSM_INIT, msg);
maybe_create_new_hsm();
- load_hsm();
+ load_hsm(NULL);
send_init_response(master);
}
@@ -1381,8 +1383,37 @@ static void master_gone(struct io_conn *unused UNUSED, struct daemon_conn *dc UN
exit(2);
}
+static bool my_sha256(void *digest, const void *data, size_t datasz)
+{
+ sha256(digest, data, datasz);
+ return true;
+}
+
+
+static int dump_xpriv(const char *secretfile) {
+ static u8 buf[BIP32_SERIALIZED_LEN];
+ static char enc[1024];
+ size_t outlen = sizeof(enc);
+ load_hsm(secretfile);
+
+ secretstuff.bip32.version = BIP32_VER_MAIN_PRIVATE;
+ int ret = bip32_key_serialize(&secretstuff.bip32, BIP32_FLAG_KEY_PRIVATE,
+ buf, BIP32_SERIALIZED_LEN);
+
+ assert(ret == WALLY_OK);
+
+ b58_sha256_impl = my_sha256;
+ b58check_enc(enc, &outlen, 4, buf+1, BIP32_SERIALIZED_LEN-1);
+ printf("%.*s\n", (int)outlen, enc);
+
+ return 0;
+}
+
int main(int argc, char *argv[])
{
+ if (argc == 3 && streq(argv[1], "--dump-xpriv"))
+ exit(dump_xpriv(argv[2]));
+
setup_locale();
struct client *client;
--
2.17.1 then you do |
@jb55 thx for that! With your patch I was able to generate the correct xprv and derive addresses from it that match values from @renepickhardt I think there may be a bug in your python script. I realized that my xxd command was wrong, it should be:
But after putting the hex value into the script, I still get an xprv that does not derive correct values. I then tried to read the hsm_secret file directly in the script like so:
and that produces the exact same (non-working) xprv as the xxd obtained value. |
Maybe I didn't understand, but in no way you can derive a bip39 mnemonic wordlist from a seed. Probably I misunderstood what you meant by the word "transferred" though: "To create a binary seed from the mnemonic, we use the PBKDF2 function with a mnemonic sentence (in UTF-8 NFKD) used as the password and the string "mnemonic" + passphrase (again in UTF-8 NFKD) used as the salt. The iteration count is set to 2048 and HMAC-SHA512 is used as the pseudo-random function. The length of the derived key is 512 bits (= 64 bytes)." |
…ecrete for the first time the mnemonic words will be printed to status_info
…ecrete for the first time the mnemonic words will be printed to status_info. fixed typo
@gabridome as far as I understand the situation these should be two separated problems. One problem is how do you get truly random binary data and the other problem is how to you encode the data together with some checksum as a list of words. I think transfering |
It is just not a correct BIP39 derivation procedure. @renepickhardt in BIP39, the initial entropy (ENT) is NOT the seed. ENT + checksum ---> list of words ---> BIP 32 seed (512 bits). The second operation is irreversible. If you derive the words from |
So summarizing then: It is fine to export an xprv for existing hsm_secret, but for mnemonic to work according to bip39, then hsm_secret must in fact be generated from a mnemonic, not vice-versa. Is there any chance to get @jb55's patch for exporting xprv merged now? Full bip39 support would be a bit more involved I suppose. |
@peertrade that patch was a hack, I don't expect it to be merged. I think a better solution would be a |
I'd prefer to have an external tool to generate and handle the |
@cdecker As I was implementing a I'm curious if an RPC But, here's where I'm not clear. Since the RPC uses UNIX domain sockets, the caller needs access to the host, correct? If that's the case, then nothing is stopping them from getting access to the |
Fair enough, Would a cleaned up patch like the one I gave above be acceptable? Basically adds a quick xpriv export as a cli option to hsmd. Is that too hacky? I'm not sure what the state of the new derivation scheme that @rustyrussell is working on and how it may affect that patch... |
FWIW, I've taken your old patch above and re-worked it to function with current master and tested it out on Testnet to see if I could actually succeed. It's my first time interacting with any actual C code myself (as well as |
@ctrlbreak- good to hear! feel free to put up the patch up on a branch somewhere so we can keep it going. |
thinking about this some more, I think the best option is to dump the xprivs as output descriptors. this way it could be easily imported into bitcoind with importmulti. |
Perhaps a compromise would be to generate using BIP32 in the first place, and place the words in a If Or just append the words to the |
I made a standalone repo for this: https://github.com/jb55/clightning-dumpkeys still need to add output descriptor support |
this can probably be closed now. you can use the above tool to dump the xprvs/xpubs and output descriptors. |
As the original request ask for mnemonic or xprv, and we have an xprv method now, I concur. |
I also added a warning to make it clear that this is not a backup method, as I've seen people asking about it:
|
hmm, I don't really see that we have an xprv method now. Yes, there is now a 3rd party tool (thanks for this @jb55!), but nothing built into c-lightning. It's not much different from last year when we had a functional patch. I think the @jb55's xprv export tool should at least go into a contrib directory. Of course, if/when a supported backup system becomes baked in, that could be a different story.
oh, is this work in progress? |
@peertrade yes the current plan is a replicated DB backup plugin, there was talk about potential static channel backups like LND does it (saved with data loss protection info), but I believe those aren't as ideal? cc @ZmnSCPxj |
For myself, the only safe channel backup is either DB replication, or (before we deploy any "static channel backup"-like system) we should first write and deploy code on a lot of nodes that tests peers for attempts at stealing from channels that have initiated the For DB replication, you are probably better off using a commodity replicating self-healing filesystem, such as ZFS (turn off dedup, since Lightning stores cryptographic data mainly which is very unlikely to be duplicated). However, if you need to run on single-board computer like RaspPi, well ZFS is not going to fit. Hooking at the DB level seems questionable to me: plugins hooked there can be triggered before
I can reopen this if @jb55 is willing to make a PR for this export tool. |
"ZmnSCPxj, ZmnSCPxj jxPCSmnZ" <notifications@github.com> writes:
For myself, the only safe channel backup is either DB replication
I'm working on this now
For DB replication, you are probably better off using a commodity
replicating self-healing filesystem, such as ZFS (turn off dedup,
since Lightning stores cryptographic data mainly which is very
unlikely to be duplicated). However, if you need to run on
single-board computer like RaspPi, well ZFS is not going to fit.
Hooking at the DB level seems questionable to me: plugins hooked there
can be triggered *before* `init` (because we already do some DB
updates just from starting up), plugins hooked there cannot safely
execute most (all, because things could change in the future) commands
because most of them touch the database, plugins get a DB sqlite3
query that they have to somehow understand, plugins need to coordinate
the timing of them sampling/copying the database file and writing the
query to their own write-ahead log... there is a lot of space for
edge-case bugs here, you are really better of with ZFS.
we discussed this today on IRC: https://jb55.com/s/802aa6f679b5a336.txt
I don't think ZFS is a reasonable thing to require of end users. I share
your concern about the brittleness of maintaining a write-ahead log and
replication plugin based on db hooks, but I don't see any other option.
In the chance we fall out of sync I believe we can just start over a
fresh snapshot, it's not ideal but should be robust?
An alternative is to have a specialized backup for a specific subset of
the database that could be backed up independently, or snapshotted on
each update. I'm not sure if this is possible but it's something I'm
looking into.
>I think the @jb55's xprv export tool should at least go into a contrib directory.
I can reopen this if @jb55 is willing to make a PR for this export tool.
I would have to rewrite it to use the internal libwally/ccan libs. I
extracted it for the purpose of being a standalone tool with minimal
dependencies, and based on cdecker's preference of an out of tree tool.
It's probably fine to have it out of tree for now unless we find a
compelling reason otherwise.
|
NIH shrug ZFS is safe and well-tested and a lot more people are going to be invested in keeping it safe and well-tested. Our own boutique backup will take at least a year of development and #recklessness before it would be anywhere near as safe. Those who cannot wait and need for some reason to handle mass amounts of Bitcoin on LN nodes now should really use ZFS (and should not use lnd SCB; given the major LN node implementations are open-source, it is trivial for an attacker to write code that exploits SCB and gets away with it before code that probes for theft attempts becomes too widespread for safe stealing of SCB users).
How do we know we are out of sync? If the plugin dies at some point and Maybe add a flag that says "there must be something that is hooked to Maybe also add a flag that says "the peer must support But really: sqlite3 is already pretty robust by itself and communicates well with most filesystems about when exactly it should get synced to disk and etc etc and I think the correct way is by filesystem replication. Sqlite3 already has a write-ahead log if you enable it, and even if you disable it you still get a rollback log that is just as safe in terms of database consistency. It just doesn't do replication by itself (because, you know, replicating filesystems already exist....). But I could be wrong. Feel free to continue with a Edit: If you really want to continue here, I would suggest rather the creation of a |
one word: discoverability. How is a user of c-lightning to find the tool? If it were linked to in the README or other relevant doc, I guess that would be sufficient... |
I wanted to derive keys for another purpose, this thread was helpful, I made a plugin from what I discovered for xpriv/xpub export, export responsibly. |
I'm trying to figure out fund backup/recovery strategies, in particular offline. Typically in HD wallets one receives a bip39 mnemonic and also has access to the root xprv key. One can write these down, store in safe location. Also, one can watch or restore funds by importing into 3rd party wallets/tools if need be.
In c-lightning, I haven't yet found a way to do that. I do see that:
So I'm hoping for something that enables me to turn hsm_secret into an xprv. It could take the form of:
The text was updated successfully, but these errors were encountered: