diff --git a/content/_img-sources/key-address-rels.uxf b/content/_img-sources/key-address-rels.uxf index 9dc94dce10..9c2823ed9f 100644 --- a/content/_img-sources/key-address-rels.uxf +++ b/content/_img-sources/key-address-rels.uxf @@ -5,8 +5,8 @@ UMLObject 60 - 60 - 150 + 50 + 110 70 Passphrase @@ -19,33 +19,34 @@ lt=. UMLObject - 350 - 60 - 180 + 320 + 50 + 130 70 - Secret Key + Seed -- - +(16 bytes) Relation - 200 - 80 - 170 - 40 + 160 + 70 + 180 + 50 lt=<. -SHA-512Half - 150.0;20.0;10.0;20.0 +SHA512, keep +first 16 bytes + 160.0;20.0;10.0;20.0 UMLObject - 650 - 60 + 60 + 180 220 70 @@ -58,21 +59,21 @@ SHA-512Half Relation - 520 + 160 80 - 150 - 50 + 600 + 120 lt=<- Public Key Derivation - 130.0;20.0;10.0;20.0 + 10.0;100.0;10.0;70.0;580.0;70.0;580.0;10.0;550.0;10.0 UMLObject 360 - 190 + 270 180 80 @@ -84,25 +85,28 @@ Derivation Relation - 300 - 120 - 440 - 130 + 270 + 180 + 220 + 160 lt=<- - SHA-256 of RIPEMD160 + + + +RIPEMD160 of SHA-256 - 60.0;90.0;10.0;90.0;10.0;40.0;420.0;40.0;420.0;10.0 + 90.0;110.0;40.0;110.0;40.0;40.0;10.0;40.0 UMLObject 690 - 190 + 270 180 80 @@ -116,7 +120,7 @@ Checksum (4 bytes) UMLObject 60 - 190 + 270 190 80 @@ -130,7 +134,7 @@ Checksum (4 bytes) Relation 240 - 230 + 310 140 30 @@ -141,7 +145,7 @@ Checksum (4 bytes) UMLObject 400 - 320 + 400 100 70 @@ -154,7 +158,7 @@ Checksum (4 bytes) Relation 490 - 230 + 310 120 140 @@ -165,7 +169,7 @@ Checksum (4 bytes) Relation 530 - 210 + 290 80 30 @@ -176,7 +180,7 @@ Checksum (4 bytes) UMLState 590 - 210 + 290 100 40 @@ -188,7 +192,7 @@ type=sender Relation 420 - 260 + 340 130 80 @@ -196,4 +200,30 @@ type=sender SHA-256 twice 10.0;60.0;10.0;10.0 + + UMLObject + + 600 + 50 + 110 + 70 + + Private Key +-- +(32 bytes) + + + + Relation + + 440 + 70 + 180 + 50 + + lt=<- +Private Key +Derivation + 160.0;20.0;10.0;20.0 + diff --git a/content/concepts/payment-system-basics/accounts/accounts.md b/content/concepts/payment-system-basics/accounts/accounts.md index 8a0dec754e..e2a31ebfe4 100644 --- a/content/concepts/payment-system-basics/accounts/accounts.md +++ b/content/concepts/payment-system-basics/accounts/accounts.md @@ -93,9 +93,9 @@ XRP Ledger addresses are encoded using [base58](https://en.wikipedia.org/wiki/Ba The following diagram shows the relationship between keys and addresses: -![Passphrase → Secret Key → Public Key + Type Prefix → Account ID + Checksum → Address](img/key-address-rels.png) +![Passphrase → Seed → Private Key → Public Key + Type Prefix → Account ID + Checksum → Address](img/key-address-rels.png) -The formula for calculating an XRP Ledger address is as follows. For the complete example code, see [`encode_address.js`](https://github.com/ripple/ripple-dev-portal/blob/master/content/_code-samples/address_encoding/encode_address.js). +The formula for calculating an XRP Ledger address from a public key is as follows. For the complete example code, see [`encode_address.js`](https://github.com/ripple/ripple-dev-portal/blob/master/content/_code-samples/address_encoding/encode_address.js). For the process of deriving a public key from a passphrase or seed value, see [Key Derivation](cryptographic-keys.html#key-derivation). 1. Import required algorithms: SHA-256, RIPEMD160, and base58. Set the dictionary for base58. diff --git a/content/concepts/payment-system-basics/accounts/cryptographic-keys.md b/content/concepts/payment-system-basics/accounts/cryptographic-keys.md index a511e2c38d..3855b77255 100644 --- a/content/concepts/payment-system-basics/accounts/cryptographic-keys.md +++ b/content/concepts/payment-system-basics/accounts/cryptographic-keys.md @@ -116,6 +116,58 @@ The supported types of key pairs can be used interchangeably throughout the XRP In the future, it is likely that the XRP Ledger will need new cryptographic signing algorithms to keep up with developments in cryptography. For example, if quantum computers using [Shor's algorithm](https://en.wikipedia.org/wiki/Shor's_algorithm) (or something similar) will soon be practical enough to break elliptic curve cryptography, XRP Ledger developers can add a cryptographic signing algorithm that isn't easily broken. As of mid 2019, there's no clear first choice "quantum-resistant" signing algorithm and quantum computers are not yet practical enough to be a threat, so there are no immediate plans to add any specific algorithms. +## Key Derivation + +The process of deriving a key pair depends on the signing algorithm. In all cases, keys are generated from a _seed_ value that is 16 bytes (128 bits) in length. The seed value can be completely random (recommended) or it can be derived from a specific passphrase by taking the [SHA-512 hash][Hash] and keeping the first 16 bytes (similar to [SHA-512Half][], but keeping only 128 bits instead of 256 bits of the output). + +### Ed25519 Key Derivation +[[Source]](https://github.com/ripple/rippled/blob/fc7ecd672a3b9748bfea52ce65996e324553c05f/src/ripple/protocol/impl/SecretKey.cpp#L203 "Source") + +All 32-byte numbers are valid Ed25519 private keys, so Ed25519 private key derivation is a single step: + +- Calculate the [SHA-512Half][] of the seed value. The result is the 32-byte private key. + +To calculate an Ed25519 public key, use the standard public key derivation for [Ed25519](https://ed25519.cr.yp.to/software.html) to derive the public key. (As always with cryptographic algorithms, use a standard, well-known, publicly-audited implementation whenever possible. For example, [OpenSSL](https://www.openssl.org/) has implementations of core Ed25519 and secp256k1 functions.) + +### secp256k1 Key Derivation + +Key derivation for secp256k1 XRP Ledger keys involves more steps than Ed25519 key derivation for a couple reasons: + +- Not all 32-byte numbers are valid secp256k1 private keys. +- The XRP Ledger's reference implementation has an unused, incomplete framework for deriving a family of key pairs from a single seed value. + +The steps to derive a valid secp256k1 private key from a seed value are as follows: + +1. Calculate a "root key pair" from the seed value, as follows: + + 1. Concatenate the following in order, for a total of 20 bytes: + - The seed value (16 bytes) + - A "root sequence" value (4 bytes), as a big-endian unsigned integer. Use 0 as a starting value for the root sequence. + + 2. Calculate the [SHA-512Half][] of the concatenated (seed+root sequence) value. + + 3. If the result is not a valid secp265k1 private key, increment the root sequence by 1 and start over. [[Source]](https://github.com/ripple/rippled/blob/fc7ecd672a3b9748bfea52ce65996e324553c05f/src/ripple/crypto/impl/GenerateDeterministicKey.cpp#L103 "Source") + + A valid secp256k1 key must not be zero, and it must be numerically less than the _secp256k1 modulus_ (also called the "group order"). The secp256k1 modulus is the constant value `0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141`. + + 4. With a valid secp256k1 private key, use the standard ECDSA public key derivation with the secp256k1 curve to derive the root public key. (As always with cryptographic algorithms, use a standard, well-known, publicly-audited implementation whenever possible. For example, [OpenSSL](https://www.openssl.org/) has implementations of core Ed25519 and secp256k1 functions.) + +2. Derive an intermediate key pair from the root public key you calculated in step 1, as follows: + + 1. Concatenate the following in order, for a total of 40 bytes: + - The root public key (32 bytes) + - `0x00000000000000000000000000000000` (4 bytes of zeroes). (This value was intended to be used to derive different members of the same family, but in practice only the value 0 is used.) + - A "key sequence" value (4 bytes), as a big-endian unsigned integer. Use 0 as a starting value for the key sequence. + + 2. Calculate the [SHA-512Half][] of the concatenated value. + + 3. If the result is not a valid secp265k1 private key, increment the key sequence by 1 and restart deriving the account's intermediate key pair. + + 4. With a valid secp256k1 private key, use the standard ECDSA public key derivation with the secp256k1 curve to derive the intermediate public key. (As always with cryptographic algorithms, use a standard, well-known, publicly-audited implementation whenever possible. For example, [OpenSSL](https://www.openssl.org/) has implementations of core Ed25519 and secp256k1 functions.) + +3. Calculate the sum of the root public key and the intermediate public key. The result is the master public key. ***TODO: which private key do you use?*** + + ## See Also - **Concepts:** diff --git a/content/references/rippled-api/admin-rippled-methods/status-and-debugging-methods/peers.md b/content/references/rippled-api/admin-rippled-methods/status-and-debugging-methods/peers.md index 06cca0c621..575b0ac5b5 100644 --- a/content/references/rippled-api/admin-rippled-methods/status-and-debugging-methods/peers.md +++ b/content/references/rippled-api/admin-rippled-methods/status-and-debugging-methods/peers.md @@ -377,7 +377,7 @@ The response follows the [standard format][], with a successful result containin | `cluster` | Object | Summary of other `rippled` servers in the same cluster, if [configured as a cluster](clustering.html). [New in: rippled 0.30.1][] | | `peers` | Array | Array of peer objects. | -Each field of the `cluster` object is the public key of that `rippled` server's identifying keypair. (This is the same value that that server returns as `pubkey_node` in the [server_info method][].) The contents of that field are an object with the following fields: +Each field of the `cluster` object is the public key of that `rippled` server's identifying key pair. (This is the same value that that server returns as `pubkey_node` in the [server_info method][].) The contents of that field are an object with the following fields: | `Field` | Type | Description | |:--------|:-------|:----------------------------------------------------------| diff --git a/content/references/rippled-api/ledger-data-formats/ledger-object-types/accountroot.md b/content/references/rippled-api/ledger-data-formats/ledger-object-types/accountroot.md index 3d9d765bc5..5c286613e8 100644 --- a/content/references/rippled-api/ledger-data-formats/ledger-object-types/accountroot.md +++ b/content/references/rippled-api/ledger-data-formats/ledger-object-types/accountroot.md @@ -42,7 +42,7 @@ The `AccountRoot` object has the following fields: | `Domain` | String | VariableLength | _(Optional)_ A domain associated with this account. In JSON, this is the hexadecimal for the ASCII representation of the domain. | | `EmailHash` | String | Hash128 | _(Optional)_ The md5 hash of an email address. Clients can use this to look up an avatar through services such as [Gravatar](https://en.gravatar.com/). | | `MessageKey` | String | VariableLength | _(Optional)_ A public key that may be used to send encrypted messages to this account. In JSON, uses hexadecimal. No more than 33 bytes. | -| `RegularKey` | String | AccountID | _(Optional)_ The address of a keypair that can be used to sign transactions for this account instead of the master key. Use a [SetRegularKey transaction][] to change this value. | +| `RegularKey` | String | AccountID | _(Optional)_ The address of a [key pair](cryptographic-keys.html) that can be used to sign transactions for this account instead of the master key. Use a [SetRegularKey transaction][] to change this value. | | `TickSize` | Number | UInt8 | _(Optional)_ How many significant digits to use for exchange rates of Offers involving currencies issued by this address. Valid values are `3` to `15`, inclusive. _(Requires the [TickSize amendment][].)_ | | `TransferRate` | Number | UInt32 | _(Optional)_ A [transfer fee](https://ripple.com/knowledge_center/transfer-fees/) to charge other users for sending currency issued by this account to each other. | | `WalletLocator` | String | Hash256 | _(Optional)_ **DEPRECATED**. Do not use. | diff --git a/img/key-address-rels.png b/img/key-address-rels.png index 2312d9cacf..53e4352e27 100644 Binary files a/img/key-address-rels.png and b/img/key-address-rels.png differ