[Ripple] Understanding passphrase, secret-key, and address (account).

in #ripple8 years ago (edited)

Introduction

The relationship between the 'secret_key' and address of a Ripple account, is quite different from other cryptos. In Ripple, when we say 'secret_key', it's not refering to the private-key used for signing account's transactions (as in most other cryptos), but the seed from which the signing keypair was derived.

Taking the root-account as an example, the following explain how the address and signing-keypair of a ripple account is generated from its secret (seed).


from Passphrase to Seed

  1. perform SHA-512 hashing on the passphrase.
  2. seed = first 128-bits of the result of step-1.

example:
The root account is generated from a passphrase: masterpassphrase.
from this a seed is generated: DEDCE9CE67B451D852FD4E846FCDE31C(hex), or snoPBrXtMeMyMHUVTgbuqAfg1SUTb in Base-58-Check encoding.

In most condition a wallet-client would generate a (random) seed directly rather than deriving from a passphrase.


from Seed to Family Generator (Root Account)

  1. set a counter, i = 0 (32-bit number),
  2. append the seed with counter i,
  3. perform SHA-512 hashing on the result of step-2,
  4. Family Generator's private_key = first-half of result from step-3.
  5. if the computed private_key is zero or bigger than elliptic-curve's order, increase counter i by 1 then repeat from step-2.

e.g.
from seed DEDCE9CE67B451D852FD4E846FCDE31C,
Family Generator's private_key = first-half-of-sha512 (DEDCE9CE67B451D852FD4E846FCDE31C + 00000000) = 395898665728F57DE5D90F1DE102278A967D6941A45A6C9A98CB123394489E55

The corresponding public_key = 03D49C56E1B185F1BE899AE66A02EFC17F78EA6FC53AF85E0FE54C6E8B7F8C71A8


from Family Generator to (child) Account with index_number

By default, index_number = 0.

  1. set a counter, i = 0 (32-bit number)
  2. append Generator's Public_key with an index_number (32-bit), followed by counter i,
  3. perform SHA-512 hashing on the result of step-2,
  4. additional_key = first-half of the result from step-3.
  5. if additional_key is zero or bigger than elliptic-curve's order, increase counter-i by 1 and repeat from step-2.
  6. Account's private_key = Generator's private_key + additional_key, (mod curve's order).

e.g.

Family Generator (public) = 03D49C56E1B185F1BE899AE66A02EFC17F78EA6FC53AF85E0FE54C6E8B7F8C71A8,
For the first child Account (index_number = 0),
Account's private_key = 1ACAAEDECE405B2A958212629E16F2EB46B153EEE94CDD350FDEFF52795525B7
Account's public_key = 0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020


from Account's Public_Key to Address

  1. perform SHA-256 hashing on the public key.
  2. perform RIPEMD-160 hashing on the result of step-1.
  3. perform Base-58-Check encoding on the result of step-2, with version_byte = 0.

e.g.
Account's public_key = 0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020,
Ripple address = rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh.

This computation of address from public-key is exactly the same as the protocol for deriving a normal bitcoin address. The only difference is the character-set used for base-58-encoding:
Alphabet-set used by Ripple is rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz,
(for comparison, Bitcoin's: 123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz).


Summary

The Account Family of Ripple is a feature quite similar to HD-wallet(BIP32) of Bitcoin. The workflow of masterpassphrase --> seed --> root account --> account was embeded into rippled's codes since infant stage of Ripple. But somehow the use of Account Families had never been introduced to end-users, nor being established by wallet-clients. The only use-case of Root-Account in Ripple-network now is for the consensus process between validators.

Nevertheless, most ripple-wallet clients today still using the seed (e.g. snoPBrXtMeMyMHUVTgbuqAfg1SUTb) as 'secret_key' for an account, probably for the sack of compatibility.

References:

https://wiki.ripple.com/Account_Family
https://github.com/ripple/rippled/blob/master/src/ripple/crypto/impl/GenerateDeterministicKey.cpp