Key Generation Pipeline

← Back to Cryptography I: Blockchain Security and Cryptographic Foundations

Introduction

Now that we understand where randomness comes from, let's explore how rippled transforms that randomness into cryptographic keys. This chapter traces the complete key generation pipeline—from random bytes to secret keys, from secret keys to public keys, and from public keys to account addresses.

We'll examine both random key generation (for new accounts) and deterministic key generation (for wallet recovery), and understand why rippled supports two different cryptographic algorithms.

The Two Paths to Key Generation

Rippled supports two approaches to key generation:

Path 1: Random Generation
    crypto_prng() → SecretKey → PublicKey → AccountID
    (Used for: New accounts, one-time keys)

Path 2: Deterministic Generation
    Seed → SecretKey → PublicKey → AccountID
    (Used for: Wallet recovery, multiple accounts from one seed)

Random Key Generation

The Simple Case: randomSecretKey()

// From src/libxrpl/protocol/SecretKey.cpp
SecretKey randomSecretKey()
{
    std::uint8_t buf[32];
    beast::rngfill(buf, sizeof(buf), crypto_prng());
    SecretKey sk(Slice{buf, sizeof(buf)});
    secure_erase(buf, sizeof(buf));
    return sk;
}

Step-by-step breakdown:

  1. Allocate buffer: Create 32-byte buffer on stack

  2. Fill with randomness: Use crypto_prng() to fill with random bytes

  3. Construct SecretKey: Wrap bytes in SecretKey object

  4. Secure cleanup: Erase temporary buffer from memory

  5. Return: SecretKey object (move semantics, no copy)

Why 32 Bytes?

Security level:

  • 128-bit security requires 2^128 operations to break

  • 256 bits provides 2^256 operations (overkill, but standard)

  • Quantum computers reduce security by half (2^256 → 2^128)

  • So 256 bits ensures long-term security even against quantum attacks

Generating a Complete Key Pair

Deterministic Key Generation from Seeds

What is a Seed?

A seed is a compact representation (typically 16 bytes) from which many keys can be derived:

Why seeds matter:

  • Backup: Remember one seed → recover all keys

  • Portability: Move keys between wallets

  • Hierarchy: Generate multiple accounts from one seed

Generating Keys from Seeds: The Interface

Ed25519: Simple Derivation

Why this works:

  • SHA-512-Half is a one-way function

  • Same seed always produces same secret key

  • Different seeds produce uncorrelated secret keys

  • No special validation needed (all 32-byte values are valid ed25519 keys)

Secp256k1: Complex Derivation

Why more complex?

Not all 32-byte values are valid secp256k1 secret keys. The value must be:

  • Greater than 0

  • Less than the curve order (a large prime number)

The Generator Class

Deriving the Root Key

Why this loop?

The probability that a random 256-bit value is >= CURVE_ORDER is approximately 1 in 2^128. This is so unlikely that we almost never need a second try, but the code handles it correctly.

Incrementing ordinal: If the first hash isn't valid, we increment the ordinal and try again. This ensures:

  • Deterministic behavior (same seed always produces same result)

  • Eventually finds a valid key (extremely high probability on first try)

  • No bias in the resulting key distribution

Public Key Derivation

For Secp256k1

Compressed vs Uncompressed:

Why compress?

  • Saves 32 bytes per public key

  • Given X, only two possible Y values exist

  • Prefix bit tells us which one

For Ed25519

Simpler than secp256k1:

  • No compression needed (Ed25519 public keys are naturally 32 bytes)

  • No serialization complexity

  • Just prepend type marker (0xED)

Account ID Generation

Once we have a public key, we derive the account ID:

RIPESHA: Double Hashing

The pipeline:

Why double hash?

  1. Defense in depth: If one hash is broken, the other provides protection

  2. Compactness: 20 bytes is shorter than 32 bytes

  3. Quantum resistance: Even if quantum computers break elliptic curve crypto, they can't reverse the hash to get the public key

Address Encoding

The final step is encoding the account ID as a human-readable address:

Result:

We'll explore Base58Check encoding in detail in Chapter 7.

Complete Key Generation Examples

Example 1: Random Ed25519 Key

Example 2: Deterministic Secp256k1 Key

Example 3: Multiple Accounts from One Seed

Key Type Detection

Public Key Type Detection

Automatic Algorithm Selection

The secp256k1 Context

Security Considerations

Secret Key Storage

Key Validation

Seed Protection

Performance Characteristics

Key Generation Speed

Caching Considerations

Summary

Key generation in rippled involves:

  1. Randomness: Cryptographically secure random bytes from crypto_prng()

  2. Secret keys: 32 bytes of random or deterministically-derived data

  3. Public keys: Derived via one-way function

  4. Account IDs: Double hash (SHA-256 + RIPEMD-160) of public keys

  5. Addresses: Base58Check encoding of account IDs

Two algorithms:

  • secp256k1 – complex, validated, widely used

  • ed25519 – simpler, faster, preferred

Two approaches:

  • Random: Maximum security, requires backup of each key

  • Deterministic: One seed recovers many keys, convenient for wallets

In the next chapter, we'll see how these keys are used to create and verify digital signatures—the mathematical proof of authorization.

Last updated