Core Coin HD-Wallet scheme
The following standard defines the HD-wallet derivation scheme.
Since the classical BIP32 scheme is not compatible with Ed448, this standard defines a bit different implementation of the HD-derivation, based on a revised Core Coin cryptography mechanism.
|| concatenation + usual sum of two numbers +++ sum of two points on Ed448 H(x, salt) - 57 bytes of hash function HMAC-SHA512 with 2048 cycles of pbkdf2: PBKDF2(HMAC-SHA512, x, salt, 57, 2048)) chain, privKey, publicKey byte
The extended key is a byte array. It is obtained by
chaincode || privateKey or
chaincode || publicKey. Since only Scheme1 supports HD-wallet derivation, all private keys have the most significant bit of the last
byte == 1. Details could be obtained from "Core Coin cryptography scheme" CIP.
The master key is the root of the HD-derivation tree and one can get it from the mnemonics using a slightly modified BIP39 scheme. You should follow this scheme until you get the seed = BIP39 Seed, and then get master key by:
chain = H(seed, "mnemonicforthechain") key = H(seed, "mnemonicforthekey") masterKey = chain || key
Finally, for security reasons you should:
set the most significant bit of the last byte to 1 (masterKey |= 0x80) set the most significant bit of the next-to-last byte to 1 (masterKey |= 0x80) set the second significant bit of the next-to-last byte to 0 (masterKey &= 0xbf)
The master key is exactly the
m from the
m/44'/... derivation path.
Child pair generation: chain code
Note that you could always generate pubKey from privKey. We will denote this operation as private2public.
Generating a child chaincode is different for usual and hardened keys. To generate a usual key:
pubKey = private2public(privKey) childChain = H(0x03 || pubKey || i , chain), i < 2^31
In case you needed to generate a hardened key:
childChain = H(0x01 || privKey || i , chain), i >= 2^31
Child pair generation: private key 2 private key
Generating a child private key is also different for usual and hardened keys. In case of a usual key:
pubKey = private2public(privKey) template = H(0x02 || pubKey || i , chain), i < 2^31
In case of a hardened key:
template = H(0x00 || privKey || i , chain), i >= 2^31
Now we nullify the high 4 bytes and last 2 bit of the template. This is a security requirement. Let the result be
clampedTemplate = clamp(template). Then we calculate the child privKey as:
childPrivKey = privKey + clampedTemplate
Note, that there wiill not be an overflow due to high bytes of the template set to 0. The EdDSA security standards require the 9th bit of privateKey to be == 1, to avoid rho-attacks. So we clamped the template, because we want to add it to ptivateKey, and we want the 9th bit of the result to remain secure. Since we nullified 32 bits, so 23 bits after the 9th one are zeroes, and we could do at least operations of adding to the privateKey. This limits the hierarchy level of the tree to, say, .
Child pair generation: private key 2 public key
Public keys are generated by
privatetKey2privateKey generation, and then deriving public from privateKey as usual.
Child pair generation: public key 2 public
It is impossible to generate a child public key from a public hardened key. Actually, this is the main property of hardened keys. They are constructed to make such derivation impossible.
Usual child public keys could be derived from a usual parent public key.
At first we calculate clampedTemplate as above:
template = H(0x02 || publicKey || i , chain), i < 2^31 template -> clampedTemplate
Then we calculate a point on Ed448, corresponding to the clampedTemplate and add it to the publicKey (using point addition for Ed448):
point = private2public(clampedTemplate) childPublicKey = publicKey +++ point
This public key corresponds to private key, generated by the
This scheme was made to provide an alternative between the classical Ed448 signature mechanism and the possibility to generate HD-wallet keys in BIP32-like way.
Copyright and related rights waived via CC0.