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?