VerifyMessage
VerifyMessage verifies a signature over a message and recovers the signer's public key. The signature is only deemed valid if the recovered public key corresponds to a node key in the public Lightning network. The signature must be zbase32 encoded and signed by an active node in the resident node's channel database. In addition to returning the validity of the signature, VerifyMessage also returns the recovered pubkey from the signature.
Source: lightning.proto
gRPC
rpc VerifyMessage (VerifyMessageRequest) returns (VerifyMessageResponse);
REST
HTTP Method | Path |
---|---|
POST | /v1/verifymessage |
Code Samples
- gRPC
- REST
- Shell
- Javascript
- Python
const fs = require('fs');
const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');
const GRPC_HOST = 'localhost:10009'
const MACAROON_PATH = 'LND_DIR/data/chain/bitcoin/regtest/admin.macaroon'
const TLS_PATH = 'LND_DIR/tls.cert'
const loaderOptions = {
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true,
};
const packageDefinition = protoLoader.loadSync('lightning.proto', loaderOptions);
const lnrpc = grpc.loadPackageDefinition(packageDefinition).lnrpc;
process.env.GRPC_SSL_CIPHER_SUITES = 'HIGH+ECDSA';
const tlsCert = fs.readFileSync(TLS_PATH);
const sslCreds = grpc.credentials.createSsl(tlsCert);
const macaroon = fs.readFileSync(MACAROON_PATH).toString('hex');
const macaroonCreds = grpc.credentials.createFromMetadataGenerator(function(args, callback) {
let metadata = new grpc.Metadata();
metadata.add('macaroon', macaroon);
callback(null, metadata);
});
let creds = grpc.credentials.combineChannelCredentials(sslCreds, macaroonCreds);
let client = new lnrpc.Lightning(GRPC_HOST, creds);
let request = {
msg: <bytes>,
signature: <string>,
};
client.verifyMessage(request, function(err, response) {
console.log(response);
});
// Console output:
// {
// "valid": <bool>,
// "pubkey": <string>,
// }
import codecs, grpc, os
# Generate the following 2 modules by compiling the lightning.proto with the grpcio-tools.
# See https://github.com/lightningnetwork/lnd/blob/master/docs/grpc/python.md for instructions.
import lightning_pb2 as lnrpc, lightning_pb2_grpc as lightningstub
GRPC_HOST = 'localhost:10009'
MACAROON_PATH = 'LND_DIR/data/chain/bitcoin/regtest/admin.macaroon'
TLS_PATH = 'LND_DIR/tls.cert'
# create macaroon credentials
macaroon = codecs.encode(open(MACAROON_PATH, 'rb').read(), 'hex')
def metadata_callback(context, callback):
callback([('macaroon', macaroon)], None)
auth_creds = grpc.metadata_call_credentials(metadata_callback)
# create SSL credentials
os.environ['GRPC_SSL_CIPHER_SUITES'] = 'HIGH+ECDSA'
cert = open(TLS_PATH, 'rb').read()
ssl_creds = grpc.ssl_channel_credentials(cert)
# combine macaroon and SSL credentials
combined_creds = grpc.composite_channel_credentials(ssl_creds, auth_creds)
# make the request
channel = grpc.secure_channel(GRPC_HOST, combined_creds)
stub = lightningstub.LightningStub(channel)
request = lnrpc.VerifyMessageRequest(
msg=<bytes>,
signature=<string>,
)
response = stub.VerifyMessage(request)
print(response)
# {
# "valid": <bool>,
# "pubkey": <string>,
# }
- Javascript
- Python
const fs = require('fs');
const request = require('request');
const REST_HOST = 'localhost:8080'
const MACAROON_PATH = 'LND_DIR/data/chain/bitcoin/regtest/admin.macaroon'
let requestBody = {
msg: <string>, // <bytes> (base64 encoded)
signature: <string>, // <string>
};
let options = {
url: `https://${REST_HOST}/v1/verifymessage`,
// Work-around for self-signed certificates.
rejectUnauthorized: false,
json: true,
headers: {
'Grpc-Metadata-macaroon': fs.readFileSync(MACAROON_PATH).toString('hex'),
},
form: JSON.stringify(requestBody),
}
request.post(options, function(error, response, body) {
console.log(body);
});
// Console output:
// {
// "valid": <boolean>, // <bool>
// "pubkey": <string>, // <string>
// }
import base64, codecs, json, requests
REST_HOST = 'localhost:8080'
MACAROON_PATH = 'LND_DIR/data/chain/bitcoin/regtest/admin.macaroon'
TLS_PATH = 'LND_DIR/tls.cert'
url = f'https://{REST_HOST}/v1/verifymessage'
macaroon = codecs.encode(open(MACAROON_PATH, 'rb').read(), 'hex')
headers = {'Grpc-Metadata-macaroon': macaroon}
data = {
'msg': base64.b64encode(<bytes>),
'signature': <string>,
}
r = requests.post(url, headers=headers, data=json.dumps(data), verify=TLS_PATH)
print(r.json())
# {
# "valid": <bool>,
# "pubkey": <string>,
# }
$ lncli verifymessage --help
NAME:
lncli verifymessage - Verify a message signed with the signature.
USAGE:
lncli verifymessage [command options] msg signature
CATEGORY:
Wallet
DESCRIPTION:
Verify that the message was signed with a properly-formed signature
The signature must be zbase32 encoded and signed with the private key of
an active node in the resident node's channel database.
Positional arguments and flags can be used interchangeably but not at the same time!
OPTIONS:
--msg value the message to verify
--sig value the zbase32 encoded signature of the message
Messages
lnrpc.VerifyMessageRequest
Source: lightning.proto
Field | gRPC Type | REST Type | REST Placement |
---|---|---|---|
msg | bytes | string | body |
signature | string | string | body |
lnrpc.VerifyMessageResponse
Source: lightning.proto
Field | gRPC Type | REST Type |
---|---|---|
valid | bool | boolean |
pubkey | string | string |