Zondax / ledger-polkadot

Polkadot app for Ledger Nano S and X
Apache License 2.0
67 stars 32 forks source link

Address derivation details of Ledger app #43

Closed farukterzioglu closed 3 years ago

farukterzioglu commented 3 years ago

I have my own hd wallet implementation for Polkadot that developed with C#. I used Bip32-Ed25519 for addres derivation like in Ledger (I guess)

My implementation has the same results with test vectors here; https://github.com/satoshilabs/slips/blob/master/slip-0010.md#test-vector-1-for-ed25519

I can also confirm that addresses I generated from privates keys that generated by my code, also matches with official Polkadot wallet Subkey.

But my addresses doesn't match with Ledger.

The values I got from Ledger:

// 15fn3g9Ehu9FYTBUSzWPihcVfHnfm2AfFNtMtPNMHGkoWTEg m/44'/354'/0'/0'/0' // 1446qjMShfFgAtGzsLd5ykqC5cHXXDumcbNbPQTd9ZHsoePY m/44'/354'/1'/0'/0' // 13KpDbPsYHBsT8YDCP3LaDbZkKaTUMXQq4tM8y7hrYD2Hq6m m/44'/354'/2'/0'/0' // 14qrzk2kjH4gfs4Q2PCEKy6pWS3JeqHkEcvP3TFASm4mVtAW m/44'/354'/0'/0'/1'

with mnemonic identify fatal close west parent myself awake impact shoot wide wrong derive ship doctor mushroom weather absent vacant armed chuckle swarm hip music wing

From that mnemonic, I am generating the seed; fd18bdbc7382ea5356efef894d30dd3676a7ce37072e7947dd7e9076f9dd15b829b51d4d5fe9de7364f8dd6ad2c05320d942c69f3aebbad9228395e472d27a35 (also matches with bip39 )

Difference starts here. address-path pairs I got; Path: m/44'/354'/0'/0'/0', address: 13HTSwVwT5zCvTSho2RFGkmm5B2PE7aY4WnFpvUikYLTE2La Path: m/44'/354'/0'/0'/1', address: 12bhKwEky1hjSnsyQhvfXawCirC7UMpQXvkYRcJVP2T9TYwA Path: m/44'/354'/1'/0'/0', address: 18SnxCintfVLKcR8DDqamFizfPtUXKJh5tEEkrFDywU48Jf Path: m/44'/434'/2'/0'/0', address: 158Mt8CRsJPNz3XGNpHEBvPAqq5tFkzFK5KCN5hHzV8gtWPS

I am not sure what I am doing different that causes this issue.

Can anyone lead me to the right direction, maybe give more details about Zondax's Polkadot wallet implementation.

my code is here: https://github.com/farukterzioglu/HDWallet

jleni commented 3 years ago

That's SLIP0010 and it is known to be problematic for ed25519 when paths are not fully hardened. SLIP-0010 was actually designed for secp256k1 not ed25519.

Ledger's "NORMAL" derivation approach for ed25519 is to use ed25519+bip32 (cardano like) not SLIP0010

jleni commented 3 years ago

if you are interested in how Ledger derives keys in ed25519+bip32, they published a simplified python example here: https://github.com/LedgerHQ/orakolo/blob/master/src/python/orakolo/HDEd25519.py

You can also find interesting to look at the paper from Dmitry Khovratovich and Jason Law.

jleni commented 3 years ago

this can also be useful as a reference

https://github.com/LedgerHQ/nanos-secure-sdk/blob/e3293938e5988e1ffa05d1f2ba23db431275f21c/include/os.h#L1169-L1182

jleni commented 3 years ago

I hope this provides a more complete picture.

farukterzioglu commented 3 years ago

Thanks a lot @jleni it helped.