Skip to content

Conversation

@Lagrang3
Copy link
Collaborator

@Lagrang3 Lagrang3 commented Feb 3, 2026

I've noticed that in order to generate a new hsm_secret file one needs either to write your own program, as described in the documentation (https://blockstream.github.io/greenlight/getting-started/register/) or use core lightning's hsmtool.
It would be nice to have that functionality already packed with glcli.

With the command "glcli signer generate-secret" the user can generate a hsm_secret file from a mnemonic sentence and passphrase using BIP39.

With the command "glcli signer generate-secret" the user can generate a
hsm_secret file from a mnemonic sentence and passphrase using BIP39.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
@Lagrang3 Lagrang3 force-pushed the glcli_generate_hsm_secret branch from b800b42 to b352304 Compare February 3, 2026 16:42
}
}

async fn generate_secret<P: AsRef<Path>>(
Copy link

@sangbida sangbida Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @Lagrang3! This will generate an older version of the hsm_secret and while we do support it, you won't get the benefit of recoverable addresses that you will with the modern version of the hsm secret. So for reference, we support 4 types of hsm_secrets:

  • Legacy 32 byte secrets - This is your usual 32 bytes, so in your case your mnemonic produces a seed and you store the first 32 bytes of it in the file. Your password case is also a variant of this, this is quite different to how it is in CLN, In CLN if the secret is 32 bytes it means that there is no passphrase. We rely on the 32 bytes == no passphrase in our recovery tools such as exposesecret. In your case, we're adding a passphrase option that leads to a completely different 32 byte secret.

  • Legacy 73 byte encrypted secrets - This is how passphrase support used to work, the passphrase would be used to encrypt the 32 byte secret to produce an encrypted 73 byte secret.

  • Modern mnemonics (no passphrase) - In this case we'll have 32 bytes of zero padding followed by the mnemonic itself. So it would look something like:

Full content (hex): 00000000000000000000000000000000000000000000000000000000000000006162616e646f6e206162616e646f6e206162616e646f6e206162616e646f6e206162616e646f6e206162616e646f6e206162616e646f6e206162616e646f6e206162616e646f6e206162616e646f6e206162616e646f6e2061626f7574
Full content (repr): b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about
  • Modern mnemonic with passphrase: In this case, instead of the 32 byte zero padding we pad with 32 bytes of the sha256 hash of the full BIP39 seed generated from the mnemonic and passphrase. We do this to validate that the password that we have been given is correct without exposing the passphrase. So an example of this would be:
Full content (hex): 61ce9e277eb9894701400a422e43ba27c7d9d10b72bad52c16a411d2dbaf82f172697475616c2069646c65206861742073756e6e7920756e69766572736520706c75636b206b657920616c7068612077696e672063616b6520686176652077656464696e67
Full content (repr): b"a\xce\x9e'~\xb9\x89G\x01@\nB.C\xba'\xc7\xd9\xd1\x0br\xba\xd5,\x16\xa4\x11\xd2\xdb\xaf\x82\xf1ritual idle hat sunny universe pluck key alpha wing cake have wedding"

You can see how it's done in generate_hsm() and derive_seed_hash()

My recommendation would be to follow the modern standard for hsm_secrets so taproot wallet addresses are recoverable!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice explanation! Thank you.
I do prefer the modern mnemonic with passphrase.

I've implemented the legacy 32 byte secret because I had troubles with registering a node with the modern hsm_secret. It Might have been an issue with the signer not being recently enough. Let me investigate.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here it is

sec.copy_from_slice(&secret[0..32]);

The current signer only reads the first 32 bytes from the hsm_secret file.
Ok. It seems a bit more of work is needed to make the Signer work with the modern hsm_secret format.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aah yep, that won't work for the modern hsms unfortunately :( Let me know if you would like to pair on this 😄

@Lagrang3 Lagrang3 marked this pull request as draft February 4, 2026 07:54
@Lagrang3
Copy link
Collaborator Author

Lagrang3 commented Feb 4, 2026

Modern mnemonic with passphrase: In this case, instead of the 32 byte zero padding we pad with 32 bytes of the sha256 hash of the full BIP39 seed generated from the mnemonic and passphrase. We do this to validate that the password that we have been given is correct without exposing the passphrase.

Does this mean that the node cannot restart with the hsm_secret file alone and the passphrase has to be provided?

UPD: Yes. I don't like the friction that the passphrase adds to he user's workflow. I would go for the modern mnemonic format without the passphrase.

@sangbida
Copy link

sangbida commented Feb 4, 2026

Modern mnemonic with passphrase: In this case, instead of the 32 byte zero padding we pad with 32 bytes of the sha256 hash of the full BIP39 seed generated from the mnemonic and passphrase. We do this to validate that the password that we have been given is correct without exposing the passphrase.

Does this mean that the node cannot restart with the hsm_secret file alone and the passphrase has to be provided?

UPD: Yes. I don't like the friction that the passphrase adds to he user's workflow. I would go for the modern mnemonic format without the passphrase.

Yep, this is consistent with the behaviour that was there previously I believe. We can't pass in the password in on command line because then we would have to store the passphrase practically raw in lightningd and then pass it on to hsmd, we want to interface with the passphrase as little as possible in our code paths, which unfortunately means that a user is prompted for a password (if they have set one up) on restart.

In greenlight land, can users currently set up a password for their node? If not, are there any other differences in the user flow/ code paths when it comes to the hsm_secret? (Just curious to know)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants