1

My goal: I don't want to require a private key to hierarchically derive new addresses.

Sure, I can create a batch of addresses, given a private key, at first. But once I have surpassed that batch I'll require the private key again to generate more addresses.

I want to derive addresses knowing only a public key. I know this is possible with BIP39, but understand there can be security concerns involved with this, ie. if an attacker stumbles upon an xpub and xprv they can derive as many addresses as they want and be able to sign transactions using them.

Attempting to derive from a HD public key with BIP44 results in a exception stating a hardened path requires a HD private key. However, I have found a workaround, but I fear it is cheating and might sacrifice the benefits of path hardening in BIP44.

Here's an example:

// It starts off with a `userCode` that represents a BIP39 Mnemonic code.
const codeUser = new Mnemonic('select scout crash enforce riot rival spring whale hollow radar rule sentence')

// Convert to HD private key...
const hdUserPrivateKey = codeUser.toHDPrivateKey()

console.log(hdUserPrivateKey.hdPublicKey.toString())
// Gives: `xpub661MyMwAqRbcEngoXGfFNahZ5FzSDGqY8pWKTqo6vtXxK15otDNLXJmbeHV7DUjvPc7CAFhYp6hzBiTanr8rgoHPHf6NSgZAyejK5bk8MiW`
// But we won't use it...

// Instead, I can then derive a BIP44 without the `change`, `address_index` segments from `hdUserPrivateKey`...
console.log(hdUserPrivateKey.deriveChild(`m/44'/0'/0'`).hdPublicKey.toString())
// Gives: `xpub6CsrEMgU2f8uEGfFMvsPjKB9ekHuZiesLqSHLwCJuNFkP2uJGm7WjTo2gy95S4KEBc4etdodNQXAvn5Vsf4kupJQ1DKR4DMfcHwKdhQ3k6h`
// This is the xpub I can use to derive addresses without requiring the initial private key.

// So knowing this, I can build a HD public key given that xpub...
const hdPublicKey = Mnemonic.bitcore.HDPublicKey('xpub6CsrEMgU2f8uEGfFMvsPjKB9ekHuZiesLqSHLwCJuNFkP2uJGm7WjTo2gy95S4KEBc4etdodNQXAvn5Vsf4kupJQ1DKR4DMfcHwKdhQ3k6h')

const derivative = 0

// We can derive from it this path, but what is this path defined as? Are we back in BIP39 territory now?
const publicKey = hdPublicKey.deriveChild(`m/0/${derivative}`).publicKey

const address = new Mnemonic.bitcore.Address(publicKey)

console.log(address.toString()) // 12XyHwtmoq5w4VQ5mzcu6BQzdLqCLxUv5e

...and of course, I can increment the derivative as many times as I wish to create new addresses from the public key.

Whenever I wish to sign a transaction...

const codeUser = new Mnemonic('select scout crash enforce riot rival spring whale hollow radar rule sentence')
const hdUserPrivateKey = codeUser.toHDPrivateKey()
const derivative = 0

// BIP 44 derivation path for private key...
const privateKey = hdUserPrivateKey.deriveChild(`m/44'/0'/0'/0/${derivative}`).privateKey

Is this approach valid or am I dodging BIP44 standards?

1 Answer 1

0

This is, in fact, the intended approach and use of BIP 44.

The purpose is to derive to the account level with hardened derivation. Then export that xpub to be imported into other software which derives the receiving and change addresses. When signing a transaction, the wallet with the private keys can derive the entire path to get the individual child private keys needed to sign.

3
  • Ah sweet, thanks for the clear clarification. My main aim is to make exported seeds work with various well known wallets. Would that mean the initial seed is classified at BIP39 on import? But then derived to BIP44 to get a new xpub. Then further derivatives are worked out from there, which is fine? I guess I'm kind of looking for a definition of the steps I made.
    – Luka
    Jan 22, 2021 at 20:46
  • You start with a BIP 39 mnemonic. When this is imported into a wallet, the wallet produces a BIP 32 seed and BIP 32 xprvs and xpubs. You use the BIP 44 derivation path to derive specific xpubs from the BIP 32 xprv. Those xpubs are then imported as BIP 32 xpubs in another wallet.
    – Andrew Chow
    Jan 22, 2021 at 22:13
  • This has answered my question.
    – Luka
    Jan 22, 2021 at 22:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.