Core Coin HD-Wallet scheme

Dmitry (@todesstile)June 16, 2022
About 2 min

Abstract

The following standard defines the HD-wallet derivation scheme.

Motivation

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.

Specification

Definitions

|| 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 [57]byte

Extended keys

The extended key is a [114]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.

Master key

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[113] |= 0x80)
set the most significant bit of the next-to-last byte to 1 (masterKey[112] |= 0x80)
set the second significant bit of the next-to-last byte to 0 (masterKey[112] &= 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 2222^{22} operations of adding to the privateKey. This limits the hierarchy level of the tree to, say, 2202^{20}.

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 private2private method.

Rationale

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 CC0open in new window.