bitcoinjs / bitcoinjs-lib

A javascript Bitcoin library for node.js and browsers.
MIT License
5.6k stars 2.08k forks source link

How to generate child public keys from bip32 public key #997

Closed ghost closed 6 years ago

ghost commented 6 years ago

We're creating an online webshop and want to be able to generate a unique address per order. However we do not wamt the webserver to have the private keys.

Is there a way we can use this library to accomplish this?

I have tested using getPublicKeyBuffer and then creating am HDNode. However it seems like we're able to spend those funds (vs. Merely generating more receive addresses).

Thank you in advance,

junderw commented 6 years ago
// one time code to generate the master key
const bip39 = require('bip39')
const bitcoin = require('bitcoinjs-lib')

let phrase = bip39.generateMnemonic() // this will generate a random phrase
// 'width humor wheat sad obscure outer ancient grab edit labor record express'

let seedBuffer = bip39.mnemonicToSeed(phrase)
// <Buffer 85 19 18 81 cf 0e cc f7 9c 5d 61 ......

let masterNode = bitcoin.HDNode.fromSeedBuffer(seedBuffer)
// Deriving the first account based on BIP44
let account0 = masterNode.derivePath("m/44'/0'/0'")

let xpubString = account0.neutered().toBase58()
// 'xpub6CBhr9A6hYbCH4S35uAoDVYcs31vMTwh9kaQ177ftZ6tVhWbFAov1C1ekKwu6KJ4Ydv......

let key0 = account0.derivePath("0/0").keyPair
let key0FromXpub = account0.neutered().derivePath("0/0").keyPair

let address0 = key0.getAddress()
let address0FromXpub = key0FromXpub.getAddress()

console.log(address0)
// 15a3JRVLot7dVgBqa1GcXwC7wx3yf4dw1P
console.log(address0FromXpub)
// 15a3JRVLot7dVgBqa1GcXwC7wx3yf4dw1P
console.log(address0 === address0FromXpub)
// true
console.log(key0.toWIF())
// KyLVo6gfg5QnPnk4j4bF15RTVey2aJBBbwwfPbPMBjY3rqiRz9Qa
console.log(key0FromXpub.toWIF())
// Error: Missing private key
//     at ECPair.toWIF (/home/linux/node_modules/bitcoinjs-lib/src/ecpair.js:122:22)

Now we have xpub, we can upload to server

// on the server
const bitcoin = require('bitcoinjs-lib')

let address0FromXpub = bitcoin.HDNode.fromBase58('xpub6CBhr9A6hYbCH4S35uAoDVYcs31' +
'vMTwh9kaQ177ftZ6tVhWbFAov1C1ekKwu6KJ4Ydvdmp9cuDArAN9TUFpVjfJwZ9nqKMWcrmbzCcTSqU8')

let key0 = address0FromXpub.derivePath("0/0").keyPair

let address0 = address0FromXpub.derivePath("0/0").keyPair.getAddress()
let address1 = address0FromXpub.derivePath("0/1").keyPair.getAddress()
let address2 = address0FromXpub.derivePath("0/2").keyPair.getAddress()
let address3 = address0FromXpub.derivePath("0/3").keyPair.getAddress()
// '15a3JRVLot7dVgBqa1GcXwC7wx3yf4dw1P'
// '1LUxjkAp1JzxPA3y8LV9PGFxqgPv9Rri1h'
// '13LqgJGEzERsLLhx2WbjM5Z1dJBLgZbpD7'
// '1CoE8VJVSbCzmzRDnpJ4iuSmPSg7ry3hMT'

console.log(key0.toWIF())
// Error: Missing private key
//     at ECPair.toWIF (/home/linux/node_modules/bitcoinjs-lib/src/ecpair.js:122:22)
ghost commented 6 years ago

@junderw This is fantastic, thank you so much for this.

Now the only thing is that...apparently there is little support for BIP44 wallets right now.

Which means a merchant will not see the money flowing into their wallet via their favorite wallet (Breadwallet, Bitcoin.com wallet, Copay, Electron, etc).

Or perhaps I'm missing something? The funds do not show up automatically in the "top level account" automatically with Electron or Coinomi or others).

It's as if I have to manually import the public and/or private key WIF to see it show up.

ghost commented 6 years ago

Closing issue however since the question was answered thoroughly. Thanks again!

dabura667 commented 6 years ago

Almost every wallet uses BIP39 phrases with BIP44 derivation.

Copay does, bitcoin.com does.

The only ones that don’t are breadwallet........ and I can’t think of others.

Breadwallet first account is m/0’