-
Notifications
You must be signed in to change notification settings - Fork 120
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
correct HDWallet derivation path for EOS keys #7
Comments
fyi: Some work on the signatures has been done. Xeroc had a un-merged patch for Trezor and Bitshares the HW wallet that produced passing signatures. I don't see the patch now. But I do see a new xeroc PR for steem: trezor/trezor-mcu#121 For BIP44, EOS is different. It does not have change addresses. Change addresses in BIP44 are fine but for contract permissions that are not a good fit. Due to the elliptic curve math derived keys on the same hierarchical level have a weaker security profile that make them unsafe. For example, one private key and a chain code can revile all private keys at that level and lower levels. So, this is better suited for flat and redundant change addresses but not suited for more meaningful contract permissions. Deriving keys are done in binary and use only sha256 hashing that does not involve any elliptic curve math. So, while EOS needs something different it is actually easier to implement and understand. This will be the starting point: mnemonicSeedBuffer = bip39.mnemonicToSeed(mnemonic, passphrase) // new stuff I propose (this needs peer review):
chainCode = Buffer.from('00'.repeat(32), hex) // testnet is '00'.repeat(32), replace with real chainCode
MASTER_SALT = chainCode
chainSeedBuffer = createHmac('sha256', MASTER_SALT).update(mnemonicSeedBuffer).digest()
// Here is what we have implemented now for the front-end and endorsed by @bytemaster back in 2017..
// This is more standard and implemented in https://github.com/eosio/eosjs-keygen
owner = createHash('sha256').update(chainSeedBuffer).update('owner').digest() // root of everything
active = createHash('sha256').update(owner).update('active').digest() // active always under owner
custom1 = createHash('sha256').update(active).update('custom1').digest() //custom permissions are always under active
custom2 = createHash('sha256').update(active).update('custom2').digest() // custom permissions can be flat
custom2a = = createHash('sha256').update(custom2).update('custom2a').digest() // or nested
// the numbering in the custom variable name is just for illustration If you go digging into eosjs-keygen, you'll find unit test and up-to-date markdown docks illustrating and enforcing the rules I showed above. If you wish to make it compatible, the string from of the master key has a two letter prefix "PW" followed by a WIF key; the prefix is just cosmetic and can be removed and will play no role in hashing or deriving keys. So, for a given mnemonic and passphrase you could create the PW prefixed master key used to derive the same chainSeedBuffer data and the same derived keys (the mnemonic comes first then a compatible master password could be create). This use case is limited though because the master password is typically not cold storage but the mnemonic is. https://github.com/EOSIO/eosjs-keygen # See generateMasterKeys - https://github.com/EOSIO/eosjs-keygen/blob/v1.3.1/src/keygen.js#L34-L59
master = PrivateKey.fromSeed('test') // <- returns eosjs-ecc key_private.js
ownerPrivate = master.getChildKey('owner')
activePrivate = ownerPrivate.getChildKey('active')
customPrivate = activePrivate.getChildKey('custom') // custom contract permissions In getChildKey, I did leave a warning until I see it used in the eosio wallet: function getChildKey(name) {
// console.error('WARNING: getChildKey untested against eosd'); // no eosd impl yet
const index = createHash('sha256').update(toBuffer()).update(name).digest()
return PrivateKey(index)
} |
@jcalfee I really appreciate your detailed explanation. This is of great help to me :) |
I got one more question: In which level of public key should be used for registering in EOS distribution smart contract? For example, which permission group is used at generate EOS keys in eos.io? Also, how can we derive the real chainCode used as MASTER_SALT for mainnet? Is there any standardized way to derive it? |
Generate EOS Key at eos.io is non-deterministic (completely random). @dskvr can you please update us on how a EOS claim will happen (does this still need an account name for example)? You can probably setup a deterministic claim key by using a MASTER_SALT that includes the chain ID concatenated with some words 'EOS Claim Key' and something else to make the claim key unique for the user for each ETH account they are claiming (so the ETH address): MASTER_SALT = chainId + 'EOS Claim Key' + ethAddress The chainCode / MASTER_SALT will probably be a hash of the genesis block (all the initial balances, etc). It will not be available until the chain is live. |
For "Generate EOS Key" aka (EOS Claim Key), normalization is as follows:
|
Thanks to your help, I could successfully derived my eos pub/priv key from my mnemonic 👍. |
Slip48 is recommended https://github.com/satoshilabs/slips/blob/master/slip-0048.md |
@crazybits Sip48 does not cover role hierarchies .. Where active is a child of owner. Although role hierarchies can be completely ignored in key derivation if you want too. What do you think about the role hierarchies in EOS? It is a way to introduce a non-hardened path (without the Sip48 tick |
Please don't get carried away with this one. I should mention though that the ECC math used for public / private chain codes did work for me when I used large numbers like arbitrary role names in EOS .. It is the spec that locks it down to numbers not the math .. It is actually just hashing the role ID to get the public or private key. Using numbers allows for better discovery without an index and tends to drive people to go register and use well known roles though. It is in my mind that strings can be in a modified BIP-0044/SLIP-0044 if it makes for a better use-case. |
As far as I know Ledger uses BIP-0044/SLIP-0044 ("m/44'/194'/0'/0/0"). |
hello sir, can you give me some reference on creating EOS active and owner keys by the help of mnemonic 12 words seed? please help me im stuck in this from past 4 days but no luck please help me |
I would like to know the correct derivation path in order to derive EOS keys from mnemonic phrases. Now I am referring to SatoshiLab's list of coin types for BIP44. Please let me know if it is wrong.
The text was updated successfully, but these errors were encountered: