[Ripple] Understanding passphrase, secret-key, and address (account).
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
- perform SHA-512 hashing on the passphrase.
- 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)
- set a counter, i =
0
(32-bit number), - append the seed with counter i,
- perform SHA-512 hashing on the result of step-2,
- Family Generator's private_key = first-half of result from step-3.
- 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
.
- set a counter, i =
0
(32-bit number) - append Generator's Public_key with an index_number (32-bit), followed by counter i,
- perform SHA-512 hashing on the result of step-2,
- additional_key = first-half of the result from step-3.
- if additional_key is zero or bigger than elliptic-curve's order, increase counter-i by 1 and repeat from step-2.
- 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
- perform SHA-256 hashing on the public key.
- perform RIPEMD-160 hashing on the result of step-1.
- 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
http://ripplepaperwallet.com/