Skip to content

Commit

Permalink
Merge pull request #121 from sputn1ck/signmessage
Browse files Browse the repository at this point in the history
signmessage: add signmessage cmd
  • Loading branch information
guggero authored Feb 6, 2024
2 parents cf4cabb + 3fbf8d0 commit c75f9ff
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 0 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,7 @@ Available Commands:
rescuefunding Rescue funds locked in a funding multisig output that never resulted in a proper channel; this is the command the initiator of the channel needs to run
rescuetweakedkey Attempt to rescue funds locked in an address with a key that was affected by a specific bug in lnd
showrootkey Extract and show the BIP32 HD root key from the 24 word lnd aezeed
signmessage Sign a message with the nodes identity pubkey.
signrescuefunding Rescue funds locked in a funding multisig output that never resulted in a proper channel; this is the command the remote node (the non-initiator) of the channel needs to run
summary Compile a summary about the current state of channels
sweeptimelock Sweep the force-closed state after the time lock has expired
Expand Down Expand Up @@ -488,6 +489,7 @@ Legend:
| [rescueclosed](doc/chantools_rescueclosed.md) | :pencil: (:pushpin:) Rescue funds in a legacy (pre `STATIC_REMOTE_KEY`) channel output |
| [rescuefunding](doc/chantools_rescuefunding.md) | :pencil: (:pushpin:) Rescue funds from a funding transaction. Deprecated, use [zombierecovery](doc/chantools_zombierecovery.md) instead |
| [showrootkey](doc/chantools_showrootkey.md) | :pencil: Display the master root key (`xprv`) from your seed (DO NOT SHARE WITH ANYONE) |
| [signmessage](doc/chantools_signmessage.md) | :pencil: Sign a message with the nodes identity pubkey. |
| [signrescuefunding](doc/chantools_signrescuefunding.md) | :pencil: (:pushpin:) Sign to funds from a funding transaction. Deprecated, use [zombierecovery](doc/chantools_zombierecovery.md) instead |
| [summary](doc/chantools_summary.md) | Create a summary of channel funds from a `channel.db` file |
| [sweepremoteclosed](doc/chantools_sweepremoteclosed.md) | :pencil: Find channel funds from remotely force closed channels and sweep them |
Expand Down
1 change: 1 addition & 0 deletions cmd/chantools/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ func main() {
newRescueFundingCommand(),
newRescueTweakedKeyCommand(),
newShowRootKeyCommand(),
newSignMessageCommand(),
newSignRescueFundingCommand(),
newSummaryCommand(),
newSweepTimeLockCommand(),
Expand Down
90 changes: 90 additions & 0 deletions cmd/chantools/signmessage.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package main

import (
"fmt"

chantools_lnd "github.com/lightninglabs/chantools/lnd"
"github.com/lightningnetwork/lnd/keychain"
"github.com/spf13/cobra"
"github.com/tv42/zbase32"
)

var (
signedMsgPrefix = []byte("Lightning Signed Message:")
)

type signMessageCommand struct {
Msg string

rootKey *rootKey
cmd *cobra.Command
}

func newSignMessageCommand() *cobra.Command {
cc := &signMessageCommand{}
cc.cmd = &cobra.Command{
Use: "signmessage",
Short: "Sign a message with the node's private key.",
Long: `Sign msg with the resident node's private key.
Returns the signature as a zbase32 string.`,
Example: `chantools signmessage --msg=foobar`,
RunE: cc.Execute,
}
cc.cmd.Flags().StringVar(
&cc.Msg, "msg", "", "the message to sign",
)

cc.rootKey = newRootKey(cc.cmd, "decrypting the backup")

return cc.cmd
}

func (c *signMessageCommand) Execute(_ *cobra.Command, _ []string) error {
if c.Msg == "" {
return fmt.Errorf("please enter a valid msg")
}

extendedKey, err := c.rootKey.read()
if err != nil {
return fmt.Errorf("error reading root key: %w", err)
}

signer := &chantools_lnd.Signer{
ExtendedKey: extendedKey,
ChainParams: chainParams,
}

// Create the key locator for the node key.
keyLocator := keychain.KeyLocator{
Family: keychain.KeyFamilyNodeKey,
Index: 0,
}

// Fetch the private key for node key.
privKey, err := signer.FetchPrivKey(&keychain.KeyDescriptor{
KeyLocator: keyLocator,
})
if err != nil {
return err
}

// Create a new signer.
privKeyMsgSigner := keychain.NewPrivKeyMessageSigner(
privKey, keyLocator,
)

// Prepend the special lnd prefix.
// See: https://github.com/lightningnetwork/lnd/blob/63e698ec4990e678089533561fd95cfd684b67db/rpcserver.go#L1576 .
msg := []byte(c.Msg)
msg = append(signedMsgPrefix, msg...)
sigBytes, err := privKeyMsgSigner.SignMessageCompact(msg, true)
if err != nil {
return err
}

// Encode the signature.
sig := zbase32.EncodeToString(sigBytes)
fmt.Println(sig)

return nil
}
26 changes: 26 additions & 0 deletions doc/chantools_signmessage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
## chantools signmessage

Signs a message with the nodes key, results in the same signature as
`lncli signmessage`

### Synopsis

```
chantools signmessage [flags]
```

### Examples

```
chantools signmessage --msg=foobar
```

### Options

```
--bip39 read a classic BIP39 seed and passphrase from the terminal instead of asking for lnd seed format or providing the --rootkey flag
-h, --help help for signmessage
--msg string the message to sign
--rootkey string BIP32 HD root key of the wallet to use for decrypting the backup; leave empty to prompt for lnd 24 word aezeed
--single_hash single hash the msg instead of double hash (lnd default is false)
```
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ require (
github.com/stretchr/objx v0.5.0 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 // indirect
github.com/tv42/zbase32 v0.0.0-20220222190657-f76a9fc892fa // indirect
github.com/ulikunitz/xz v0.5.11 // indirect
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,8 @@ github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 h1:uruHq4dN7GR16kFc5fp3d1RIYzJW5onx8Ybykw2YQFA=
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tv42/zbase32 v0.0.0-20220222190657-f76a9fc892fa h1:2EwhXkNkeMjX9iFYGWLPQLPhw9O58BhnYgtYKeqybcY=
github.com/tv42/zbase32 v0.0.0-20220222190657-f76a9fc892fa/go.mod h1:is48sjgBanWcA5CQrPBu9Y5yABY/T2awj/zI65bq704=
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
Expand Down

0 comments on commit c75f9ff

Please sign in to comment.