mirror of
https://github.com/lightningnetwork/lnd.git
synced 2024-11-19 01:43:16 +01:00
lncli: add sign/verify message with an address
adds the functionality in the lncli walletkit to sign and verify a message with a single address. Signing works only with lnd default wallet account. Verifying signature on messages with external addresses is also supported.
This commit is contained in:
parent
39b77edca1
commit
5edf64f4c5
@ -52,6 +52,8 @@ var (
|
||||
Usage: "Interact with wallet addresses.",
|
||||
Subcommands: []cli.Command{
|
||||
listAddressesCommand,
|
||||
signMessageWithAddrCommand,
|
||||
verifyMessageWithAddrCommand,
|
||||
},
|
||||
}
|
||||
)
|
||||
@ -1193,6 +1195,200 @@ func listAddresses(ctx *cli.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
var signMessageWithAddrCommand = cli.Command{
|
||||
Name: "signmessage",
|
||||
Usage: "Sign a message with the private key of the provided " +
|
||||
"address.",
|
||||
ArgsUsage: "address msg",
|
||||
Description: `
|
||||
Sign a message with the private key of the specified address, and
|
||||
return the signature. Signing is solely done in the ECDSA compact
|
||||
signature format. This is also done when signing with a P2TR address
|
||||
meaning that the private key of the P2TR address (internal key) is used
|
||||
to sign the provided message with the ECDSA format. Only addresses are
|
||||
accepted which are owned by the internal lnd wallet.
|
||||
`,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "address",
|
||||
Usage: "specify the address which private key " +
|
||||
"will be used to sign the message",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "msg",
|
||||
Usage: "the message to sign for",
|
||||
},
|
||||
},
|
||||
Action: actionDecorator(signMessageWithAddr),
|
||||
}
|
||||
|
||||
func signMessageWithAddr(ctx *cli.Context) error {
|
||||
ctxc := getContext()
|
||||
|
||||
// Display the command's help message if we do not have the expected
|
||||
// number of arguments/flags.
|
||||
if ctx.NArg() > 2 || ctx.NumFlags() > 2 {
|
||||
return cli.ShowCommandHelp(ctx, "signmessagewithaddr")
|
||||
}
|
||||
|
||||
walletClient, cleanUp := getWalletClient(ctx)
|
||||
defer cleanUp()
|
||||
|
||||
var (
|
||||
args = ctx.Args()
|
||||
addr string
|
||||
msg []byte
|
||||
)
|
||||
|
||||
switch {
|
||||
case ctx.IsSet("address"):
|
||||
addr = ctx.String("address")
|
||||
|
||||
case ctx.Args().Present():
|
||||
addr = args.First()
|
||||
args = args.Tail()
|
||||
|
||||
default:
|
||||
return fmt.Errorf("address argument missing")
|
||||
}
|
||||
|
||||
switch {
|
||||
case ctx.IsSet("msg"):
|
||||
msg = []byte(ctx.String("msg"))
|
||||
|
||||
case ctx.Args().Present():
|
||||
msg = []byte(args.First())
|
||||
args = args.Tail()
|
||||
|
||||
default:
|
||||
return fmt.Errorf("msg argument missing")
|
||||
}
|
||||
|
||||
resp, err := walletClient.SignMessageWithAddr(
|
||||
ctxc,
|
||||
&walletrpc.SignMessageWithAddrRequest{
|
||||
Msg: msg,
|
||||
Addr: addr,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
printRespJSON(resp)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var verifyMessageWithAddrCommand = cli.Command{
|
||||
Name: "verifymessage",
|
||||
Usage: "Verify a message signed with the private key of the " +
|
||||
"provided address.",
|
||||
ArgsUsage: "address sig msg",
|
||||
Description: `
|
||||
Verify a message signed with the signature of the public key
|
||||
of the provided address. The signature must be in compact ECDSA format
|
||||
The verification is independent whether the address belongs to the
|
||||
wallet or not. This is achieved by only accepting ECDSA compacted
|
||||
signatures. When verifying a signature with a taproot address, the
|
||||
signature still has to be in the ECDSA compact format and no tapscript
|
||||
has to be included in the P2TR address.
|
||||
Supports address types P2PKH, P2WKH, NP2WKH, P2TR.
|
||||
|
||||
Besides whether the signature is valid or not, the recoverd public key
|
||||
of the compact ECDSA signature is returned.
|
||||
`,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "address",
|
||||
Usage: "specify the address which corresponding" +
|
||||
"public key will be used",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "sig",
|
||||
Usage: "the base64 encoded compact signature " +
|
||||
"of the message",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "msg",
|
||||
Usage: "the message to sign",
|
||||
},
|
||||
},
|
||||
Action: actionDecorator(verifyMessageWithAddr),
|
||||
}
|
||||
|
||||
func verifyMessageWithAddr(ctx *cli.Context) error {
|
||||
ctxc := getContext()
|
||||
|
||||
// Display the command's help message if we do not have the expected
|
||||
// number of arguments/flags.
|
||||
if ctx.NArg() > 3 || ctx.NumFlags() > 3 {
|
||||
return cli.ShowCommandHelp(ctx, "signmessagewithaddr")
|
||||
}
|
||||
|
||||
walletClient, cleanUp := getWalletClient(ctx)
|
||||
defer cleanUp()
|
||||
|
||||
var (
|
||||
args = ctx.Args()
|
||||
addr string
|
||||
sig string
|
||||
msg []byte
|
||||
)
|
||||
|
||||
switch {
|
||||
case ctx.IsSet("address"):
|
||||
addr = ctx.String("address")
|
||||
|
||||
case args.Present():
|
||||
addr = args.First()
|
||||
args = args.Tail()
|
||||
|
||||
default:
|
||||
return fmt.Errorf("address argument missing")
|
||||
}
|
||||
|
||||
switch {
|
||||
case ctx.IsSet("sig"):
|
||||
sig = ctx.String("sig")
|
||||
|
||||
case ctx.Args().Present():
|
||||
sig = args.First()
|
||||
args = args.Tail()
|
||||
|
||||
default:
|
||||
return fmt.Errorf("sig argument missing")
|
||||
}
|
||||
|
||||
switch {
|
||||
case ctx.IsSet("msg"):
|
||||
msg = []byte(ctx.String("msg"))
|
||||
|
||||
case ctx.Args().Present():
|
||||
msg = []byte(args.First())
|
||||
args = args.Tail()
|
||||
|
||||
default:
|
||||
return fmt.Errorf("msg argument missing")
|
||||
}
|
||||
|
||||
resp, err := walletClient.VerifyMessageWithAddr(
|
||||
ctxc,
|
||||
&walletrpc.VerifyMessageWithAddrRequest{
|
||||
Msg: msg,
|
||||
Signature: sig,
|
||||
Addr: addr,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
printRespJSON(resp)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var importAccountCommand = cli.Command{
|
||||
Name: "import",
|
||||
Usage: "Import an on-chain account into the wallet through its " +
|
||||
|
Loading…
Reference in New Issue
Block a user