Skip to content

Commit

Permalink
support derive key example
Browse files Browse the repository at this point in the history
  • Loading branch information
bucko13 committed Nov 29, 2019
1 parent fc29b18 commit f96e517
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 21 deletions.
53 changes: 53 additions & 0 deletions derive-key-example.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
const assert = require('assert')
const { secp256k1: bsecp256k1, BN, SHA256 } = require('bcrypto')

const lightning = require('./src/index.js')

const LND_SOCKET = 'localhost:10009' // should be socket where your node is running
const LND_MACAROON = 'admin.macaroon' // should be absolute path to your macaroon file
const LND_CERT = 'tls.cert' // abs path to cert file

lightning.setCredentials(LND_SOCKET, LND_MACAROON, LND_CERT)

let client = lightning.lightning()
let wallet = lightning.wallet()

function hash(data) {
return SHA256.digest(data)
}

function pubKeyToPoint(pubKey) {
const s = BN.fromBuffer(pubKey).isOdd()
const x = BN.fromBuffer(pubKey.slice(1, 33))
return bsecp256k1.curve.pointFromX(x, s)
}

;(async function() {
try {
const { identity_pubkey } = await client.getInfoAsync({})

let pubKeyN = Buffer.from(identity_pubkey, 'hex')
let pubKeyNPoint = pubKeyToPoint(pubKeyN)

// get ephemeral keys for generating shared secret
let ephemeralPriv = bsecp256k1.privateKeyGenerate()
let ephemeralPub = bsecp256k1.publicKeyCreate(ephemeralPriv, true)
let ephemeralPubBuff = bsecp256k1.publicKeyConvert(ephemeralPub, true)

// multiply node's public key by our ephemeral private key to generate shared pub key
let sharedPubKey = pubKeyNPoint.mul(BN.fromBuffer(ephemeralPriv))
sharedPubKey = sharedPubKey.encode(true)

// generate shared key by using our chosen KDF (Key Derivation Function)
const sharedKey = hash(sharedPubKey)

// get shared key from node with ephemeral pubkey
const { shared_key: derivedKey } = await wallet.deriveSharedKeyAsync({ ephemeral_pubkey: ephemeralPubBuff })

// assert they are equal
assert(sharedKey.toString('hex') === derivedKey.toString('hex'))
console.log('Success! Shared key:', sharedKey.toString('hex'))
} catch (e) {
console.error(e)
}
})()
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
},
"dependencies": {
"@grpc/proto-loader": "^0.5.2",
"bcrypto": "^4.2.9",
"bluebird": "^3.5.5",
"grpc": "^1.23.3",
"is-base64": "1.0.0"
Expand Down
40 changes: 19 additions & 21 deletions src/walletkit.proto
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,7 @@ message KeyReq {
int32 key_family = 2;
}

message KeyForAddressRequest {
/** Provide a bech32 encoded in-wallet address
*/
string addr_in = 1;
}

message AddrRequest{
message AddrRequest {
// No fields, as we always give out a p2wkh address.
}
message AddrResponse {
Expand Down Expand Up @@ -226,52 +220,54 @@ message BumpFeeRequest {
message BumpFeeResponse {
}

message SharedKeyRequest {
bytes ephemeral_pubkey = 1;
}

message SharedKeyResponse {
bytes shared_key = 1;
}

service WalletKit {
/**
DeriveNextKey attempts to derive the *next* key within the key family
(account in BIP43) specified. This method should return the next external
child within this branch.
*/
rpc DeriveNextKey(KeyReq) returns (signrpc.KeyDescriptor);
rpc DeriveNextKey (KeyReq) returns (signrpc.KeyDescriptor);

/**
DeriveKey attempts to derive an arbitrary key specified by the passed
KeyLocator.
*/
rpc DeriveKey(signrpc.KeyLocator) returns (signrpc.KeyDescriptor);
rpc DeriveKey (signrpc.KeyLocator) returns (signrpc.KeyDescriptor);

/**
NextAddr returns the next unused address within the wallet.
*/
rpc NextAddr(AddrRequest) returns (AddrResponse);

/**
KeyForAddress returns a KeyDescriptor containing the pubkey
corresponding to a given address, assuming it is owned by the wallet.
*/
rpc KeyForAddress(KeyForAddressRequest) returns (signrpc.KeyDescriptor);
rpc NextAddr (AddrRequest) returns (AddrResponse);

/**
PublishTransaction attempts to publish the passed transaction to the
network. Once this returns without an error, the wallet will continually
attempt to re-broadcast the transaction on start up, until it enters the
chain.
*/
rpc PublishTransaction(Transaction) returns (PublishResponse);
rpc PublishTransaction (Transaction) returns (PublishResponse);

/**
SendOutputs is similar to the existing sendmany call in Bitcoind, and
allows the caller to create a transaction that sends to several outputs at
once. This is ideal when wanting to batch create a set of transactions.
*/
rpc SendOutputs(SendOutputsRequest) returns (SendOutputsResponse);
rpc SendOutputs (SendOutputsRequest) returns (SendOutputsResponse);

/**
EstimateFee attempts to query the internal fee estimator of the wallet to
determine the fee (in sat/kw) to attach to a transaction in order to
achieve the confirmation target.
*/
rpc EstimateFee(EstimateFeeRequest) returns (EstimateFeeResponse);
rpc EstimateFee (EstimateFeeRequest) returns (EstimateFeeResponse);

/*
PendingSweeps returns lists of on-chain outputs that lnd is currently
Expand All @@ -283,7 +279,7 @@ service WalletKit {
remain supported. This is an advanced API that depends on the internals of
the UtxoSweeper, so things may change.
*/
rpc PendingSweeps(PendingSweepsRequest) returns (PendingSweepsResponse);
rpc PendingSweeps (PendingSweepsRequest) returns (PendingSweepsResponse);

/*
BumpFee bumps the fee of an arbitrary input within a transaction. This RPC
Expand Down Expand Up @@ -312,5 +308,7 @@ service WalletKit {
fee preference being provided. For now, the responsibility of ensuring that
the new fee preference is sufficient is delegated to the user.
*/
rpc BumpFee(BumpFeeRequest) returns (BumpFeeResponse);
rpc BumpFee (BumpFeeRequest) returns (BumpFeeResponse);

rpc DeriveSharedKey (SharedKeyRequest) returns (SharedKeyResponse);
}
25 changes: 25 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,16 @@ balanced-match@^1.0.0:
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=

bcrypto@^4.2.9:
version "4.2.9"
resolved "https://registry.yarnpkg.com/bcrypto/-/bcrypto-4.2.9.tgz#d57794196c1c230d20bb12319387f733452a6a53"
integrity sha512-upd5xGkB3REZwOOM2wGgUrc29HFQcm+mbXYLN8fKI2GcnWiCXmDU7f0wzr/ye2o1t0smhX3ddSzAqXIYEXehIw==
dependencies:
bsert "~0.0.10"
bufio "~1.0.6"
loady "~0.0.1"
nan "^2.13.2"

bluebird@^3.5.5:
version "3.5.5"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.5.tgz#a8d0afd73251effbbd5fe384a77d73003c17a71f"
Expand All @@ -287,6 +297,16 @@ braces@^3.0.1:
dependencies:
fill-range "^7.0.1"

bsert@~0.0.10:
version "0.0.10"
resolved "https://registry.yarnpkg.com/bsert/-/bsert-0.0.10.tgz#231ac82873a1418c6ade301ab5cd9ae385895597"
integrity sha512-NHNwlac+WPy4t2LoNh8pXk8uaIGH3NSaIUbTTRXGpE2WEbq0te/tDykYHkFK57YKLPjv/aGHmbqvnGeVWDz57Q==

bufio@~1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/bufio/-/bufio-1.0.6.tgz#e0eb6d70b2efcc997b6f8872173540967f90fa4d"
integrity sha512-mjYZFRHmI9bk3Oeexu0rWjHFY+w6hGLabdmwSFzq+EFr4MHHsNOYduDVdYl71NG5pTPL7GGzUCMk9cYuV34/Qw==

bytebuffer@~5:
version "5.0.1"
resolved "https://registry.yarnpkg.com/bytebuffer/-/bytebuffer-5.0.1.tgz#582eea4b1a873b6d020a48d58df85f0bba6cfddd"
Expand Down Expand Up @@ -1264,6 +1284,11 @@ listr@^0.14.3:
p-map "^2.0.0"
rxjs "^6.3.3"

loady@~0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/loady/-/loady-0.0.1.tgz#24a99c14cfed9cd0bffed365b1836035303f7e5d"
integrity sha512-PW5Z13Jd0v6ZcA1P6ZVUc3EV8BJwQuAiwUvvT6VQGHoaZ1d/tu7r1QZctuKfQqwy9SFBWeAGfcIdLxhp7ZW3Rw==

locate-path@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0"
Expand Down

0 comments on commit f96e517

Please sign in to comment.