A simple library to recover Lightning Network node ids from signed messages. No need to run a Lightning Network node. Everything is done in js. Also supports signing.
- lnd
- core-lightning
- eclair
- LDK (react-native)
Basically, all implementations that follow the specinatweet and output zbase or hex are supported.
npm i ln-verifymessagejs
Check if a signature and message has been signed by a specific node.
import { verifyMessage } from "ln-verifymessagejs";
const messageThatHasBeenSigned = "helloWorld"
const zbaseSignature = "ry13r8phfdyt3yukuft4m8s5tq4kgbfmpnn9a54akrar7waxjooi1h1nsp8uzsf5t6fcctupzhhte1y388d19jwobz5bwh5rybs5wrb7"
const expectedNodeId = "02fbbee488a01cc8a9b429b6c4567e0ce7a43a2778d60729d5c4c67dcb9a34a898"
const isValid = verifyMessage(zbaseSignature, messageThatHasBeenSigned, expectedNodeId);
signature: string
Signature to verify.message: string
Plain text message that has been signed.nodePubkey: string
Node id of the node that signed the message.options
Optional arguments.options.prefix: string
Message prefix. Default isLightning Signed Message:
.
Recover a node id from a signature and message.
import { deriveNodeId } from "ln-verifymessagejs";
const messageThatHasBeenSigned = "ln-verifymessagejs";
const zbaseSignature = "rynmoqhhadjsttaracxgo9nhkoioi6peib8k18dekrih4hxpp36zcbgc6ntyrggc11uhjcb9prcx5py6qo16bk89i458r4n51ghggnxc";
const derivedNodeId = deriveNodeId(zbaseSignature, messageThatHasBeenSigned);
console.log("Message has been signed by", derivedNodeId);
signature: string
Signature to verify.message: string
Plain text message that has been signed.prefix?: string
Message prefix. Default isLightning Signed Message:
.
Be aware: deriveNodeId
does it check if the node exists.
Sign a message with a private key.
import { signMessage, utils } from "ln-verifymessagejs";
const {privateKey, publicKey} = utils.generateKeyPair(); // Generate a keypair or use your own private key.
const messageToSign = "helloWorld"
const signature = await signMessage(messageToSign, privateKey.hex);
message: string
Plain text message to sign.privateKey: Uint8Array | string
Private key either as bytes array or hex string.options
Optional arguments.options.signatureFormat: "hex" | "zbase"
Output encoding. Default iszbase
.options.prefix: string
Message prefix. Default isLightning Signed Message:
.
Derive a shared secret between a private key and a public key. Two parties deriving a secret with their respective private key and the partners public key generate the same shared secret.
import { generateSharedSecret } from "ln-verifymessagejs";
const myKeys = utils.generateKeyPair(); // Generate a keypair or use your own key.
const partnerNodeId = '0200000000a3eff613189ca6c4070c89206ad658e286751eca1f29262948247a5f';
const secret = generateSharedSecret(myKeys.privateKey.hex, partnerNodeId)
privateKey: Uint8Array | string
Private key either as bytes array or hex string.nodePubkey: string
Node id of the partner node.derivationName?: string
Optional derivation name to create a unique secret. Double sha256(baseSecret + derivationName).
Node operators can sign messages with Thunderhub or Ride the Lightning. If a user has access to a terminal messages can be signed directly with the cli.
lnd signmessage
lncli signmessage --msg MyMessageToSign
# {
# "signature": "rynmoqhhadjsttaracxgo9nhkoioi6peib8k18dekrih4hxpp36zcbgc6ntyrggc11uhjcb9prcx5py6qo16bk89i458r4n51ghggnxc"
# }
core-ightning signmessage
lightning-cli signmessage MyMessageToSign
# {
# "signature": "ddd47bc1398327e98775b27cc575fce1df2464c382549eacebc7233c1cbc4b430f8ee4d654719a1bc281f51b030ba9fa8bf95032c26abfe6e56bb282a9065332",
# "recid": "01",
# "zbase": "rdq7e66b8gb1x4c8qs383tmi9uo76jdraqbfj8ic7xd1gxyhztfwgdhqhumfehc4dxbed7e5ycf4u6wm9fedfoukz9uqk471okwocw31"
# }
# Use the zbase field
eclair signmessage
eclair-cli signmessage --msg=$(echo -n 'MyMessageToSign' | base64)
# {
# "nodeId": "02ca7361934233f6d4defd4d792fb2ce2cd0b50c7605e6c5cd16006bcd5be2bf70",
# "message": "aGVsbG8gd29ybGQK",
# "signature": "1f730dce842c31b692dc041c2d0f00423d2a2a67b0c63c1a905d500f09652a5b1a036763a1603333fa589ae92d1f7963428ff170e976d0966a113f4b9f9d0efc7f"
# }
# Use the signature field. It's hex
react-native-ldk signmessage
const res = await ldk.nodeSign({
message: 'MyMessageToSign',
messagePrefix: 'Lightning Signed Message:' //Optional with default
});
if (res.isErr()) {
console.error(res.error);
return;
}
console.log(res.value);