From BIP32:
We signify an prolonged non-public key as (okay, c), with okay the traditional
non-public key, and c the chain code. An prolonged public secret is
represented as (Ok, c), with Ok = level(okay) and c the chain code.
level(p): returns the coordinate pair ensuing from EC level
multiplication (repeated utility of the EC group operation) of the
secp256k1 base level with the integer p.ser256(p): serializes the integer p as a 32-byte sequence,
most important byte first.serP(P): serializes the coordinate pair P = (x,y) as a byte
sequence utilizing SEC1’s compressed kind: (0x02 or 0x03) ||
ser256(x), the place the header byte depends upon the parity of
the omitted y coordinate.
Prolonged private and non-private keys are serialized as follows:
- 4 byte: model bytes (mainnet: 0x0488B21E public, 0x0488ADE4 non-public; testnet: 0x043587CF public, 0x04358394 non-public)
- 1 byte: depth: 0x00 for grasp nodes, 0x01 for level-1 derived keys, ….
- 4 bytes: the fingerprint of the mother or father’s key (0x00000000 if grasp key)
- 4 bytes: baby quantity. That is ser32(i) for i in xi = xpar/i, with xi the important thing being serialized. (0x00000000 if grasp key)
- 32 bytes: the chain code
- 33 bytes: the general public key or non-public key information (serP(Ok) for public keys, 0x00 || ser256(okay) for personal keys)
This 78 byte construction could be encoded like different Bitcoin information in
Base58, by first including 32 checksum bits (derived from the double
SHA-256 checksum), after which changing to the Base58 illustration.
This leads to a Base58-encoded string of as much as 112 characters.
Thus the prolonged public key (xpub) could be derived from the prolonged non-public key (xprv) as follows:
- Convert the xprv from Base58 to bytes and extract the non-public key from the final 33 bytes (ignoring the checksum).
- Calculate the general public key from the non-public key as per level(p).
- Serialize the consequence:
- 4 bytes: 0x0488B21E (mainnet) or 0x043587CF (testnet)
- 41 bytes: depth, mother or father fingerprint, baby quantity and chain code are the identical as within the xprv
- 33 bytes: public key serialized utilizing serP(Ok)
- Add the 4-byte checksum and convert to Base58.