MultiversX Tracker is Live!

Generate Public Keys from Extended Public Key in python

Bitcoin Stack Exchange

Bitcoin News / Bitcoin Stack Exchange 197 Views

The conversion from extended public key to child public key is specified in BIP32:

The function CKDpub((Kpar, cpar), i) → (Ki, ci) computes a child extended public key from the parent extended public key. It is only defined for non-hardened child keys.

  • Check whether i ≥ 231 (whether the child is a hardened key).
    • If so (hardened child): return failure
    • If not (normal child): let I = HMAC-SHA512(Key = cpar, Data = serP(Kpar) || ser32(i)).
  • Split I into two 32-byte sequences, IL and IR.
  • The returned child key Ki is point(parse256(IL)) + Kpar.
  • The returned chain code ci is IR.
  • In case parse256(IL) ≥ n or Ki is the point at infinity, the resulting key is invalid, and one should proceed with the next value for i.

The other used functions are defined so:

  • point(p): returns the coordinate pair resulting from EC point multiplication (repeated application of the EC group operation) of the secp256k1 base point with the integer p.
  • ser32(i): serialize a 32-bit unsigned integer i as a 4-byte sequence, most significant byte first.
  • ser256(p): serializes the integer p as a 32-byte sequence, most significant byte first.
  • serP(P): serializes the coordinate pair P = (x,y) as a byte sequence using SEC1's compressed form: (0x02 or 0x03) || ser256(x), where the header byte depends on the parity of the omitted y coordinate.
  • parse256(p): interprets a 32-byte sequence as a 256-bit number, most significant byte first.

The first problem I see in your code is that your public key is 34 bytes long. According to the specification it should be 33 bytes long and start with either 0x02 or 0x03.

Next, chain_code.encode("utf-8") doesn't convert a hexadecimal string to bytes. Use something like bytes.fromhex(chain_code) instead.

Finally, lefthand_hash_output is created wrong, should be h[:32].

For sample source code you should check out the implementation in python-bip32. It uses coincurve for secp256k1 curve operations.

def _derive_public_child(pubkey, chaincode, index): """A.k.a CKDpub, in bip-0032. :param pubkey: The parent's (compressed) public key, as bytes :param chaincode: The parent's chaincode, as bytes :param index: The index of the node to derive, as int :return: (child_pubkey, child_chaincode) """ assert isinstance(pubkey, bytes) and isinstance(chaincode, bytes) assert not index & HARDENED_INDEX # payload is the I from the BIP. Index is 32 bits unsigned int, BE. payload = hmac.new( chaincode, pubkey + index.to_bytes(4, "big"), hashlib.sha512 ).digest() try: tmp_pub = coincurve.PublicKey.from_secret(payload[:32]) except ValueError: raise BIP32DerivationError( "Invalid private key at index {}, try the " "next one!".format(index) ) parent_pub = coincurve.PublicKey(pubkey) try: child_pub = coincurve.PublicKey.combine_keys([tmp_pub, parent_pub]) except ValueError: raise BIP32DerivationError( "Invalid public key at index {}, try the " "next one!".format(index) ) return child_pub.format(), payload[32:]

Get BONUS $200 for FREE!

You can get bonuses upto $100 FREE BONUS when you:
💰 Install these recommended apps:
💲 SocialGood - 100% Crypto Back on Everyday Shopping
💲 xPortal - The DeFi For The Next Billion
💲 CryptoTab Browser - Lightweight, fast, and ready to mine!
💰 Register on these recommended exchanges:
🟡 Binance🟡 Bitfinex🟡 Bitmart🟡 Bittrex🟡 Bitget
🟡 CoinEx🟡 Crypto.com🟡 Gate.io🟡 Huobi🟡 Kucoin.



Comments