How are XRPL addresses generated?
Last updated:
XRPL address generation is a multi-step cryptographic process that transforms a public key into a human-readable, checksummed identifier. Understanding this process is essential for developers building wallets, tools, or integrations with the XRP Ledger.
The Address Generation Pipeline
The complete process involves several cryptographic operations:
1. Generate private key (256-bit random number) 2. Derive public key from private key (algorithm-specific) 3. Hash the public key (SHA-256, then RIPEMD-160) 4. Add account type prefix 5. Compute checksum 6. Encode in Base58
Step-by-Step Process
Step 1: Private Key Generation
```javascript // Generate cryptographically secure random 256-bit number const crypto = require('crypto'); const privateKeyBytes = crypto.randomBytes(32); const privateKeyHex = privateKeyBytes.toString('hex'); ```
Step 2: Public Key Derivation
This step differs by algorithm:
```javascript // Ed25519 const ed25519 = require('ed25519'); const publicKeyEd = ed25519.publicKey(privateKeyBytes); // Result: 32-byte public key, prefixed with 'ED' when hex-encoded
// secp256k1 const secp256k1 = require('secp256k1'); const publicKeySecp = secp256k1.publicKeyCreate(privateKeyBytes, true); // compressed // Result: 33-byte compressed public key (02/03 prefix + 32 bytes) ```
Step 3: Hash the Public Key
This is where XRPL's specific hashing scheme comes in:
```javascript const crypto = require('crypto');
function accountPublicKeyToAddress(publicKey) { // Step 3a: SHA-256 hash const sha256 = crypto.createHash('sha256') .update(publicKey) .digest(); // Step 3b: RIPEMD-160 hash const ripemd160 = crypto.createHash('ripemd160') .update(sha256) .digest(); return ripemd160; // 20-byte hash } ```
Step 4: Add Type Prefix
```javascript // Account addresses use type ID 0 const ACCOUNT_ID = 0; const payload = Buffer.concat([ Buffer.from([ACCOUNT_ID]), ripemd160Hash ]); // 21 bytes total ```
Step 5: Compute Checksum
XRPL uses a double SHA-256 checksum:
```javascript function computeChecksum(payload) { const hash1 = crypto.createHash('sha256').update(payload).digest(); const hash2 = crypto.createHash('sha256').update(hash1).digest(); return hash2.slice(0, 4); // First 4 bytes }
const checksum = computeChecksum(payload); const addressBytes = Buffer.concat([payload, checksum]); // 25 bytes ```
Step 6: Base58 Encoding
XRPL uses Bitcoin's Base58Check alphabet (no 0, O, I, l to avoid confusion):
```javascript const BASE58_ALPHABET = 'rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz';
function encodeBase58(buffer) { let num = BigInt('0x' + buffer.toString('hex')); let encoded = ''; while (num > 0n) { const remainder = num % 58n; num = num / 58n; encoded = BASE58_ALPHABET[Number(remainder)] + encoded; } // Add leading 'r' characters for leading zero bytes for (let i = 0; i < buffer.length && buffer[i] === 0; i++) { encoded = 'r' + encoded; } return encoded; }
const address = encodeBase58(addressBytes); // Result: rN7n7otQDd6FczFgLdlqtyMVrn3HMfgnZh (for example) ```
Complete Implementation
```javascript const xrpl = require('xrpl'); const crypto = require('crypto');
function generateAddress(algorithm = 'ed25519') { // Step 1: Generate private key const privateKey = crypto.randomBytes(32); // Step 2: Derive public key (using xrpl library for simplicity) const wallet = xrpl.Wallet.fromSeed( xrpl.encodeSeed(privateKey, algorithm), { algorithm } ); // Steps 3-6 are handled internally by the library return { privateKey: wallet.privateKey, publicKey: wallet.publicKey, address: wallet.address }; }
const account = generateAddress('ed25519'); console.log('Address:', account.address); console.log('Public Key:', account.publicKey); ```
Why This Design?
The address generation scheme incorporates multiple design principles:
1. Double Hashing
Using both SHA-256 and RIPEMD-160 provides: - Additional security layer - Smaller address size (160 bits vs 256 bits) - Potential quantum resistance (attacking requires inverting two hash functions)
2. Checksum
The 4-byte checksum catches: - Transcription errors - Transmission errors - Invalid addresses (only 1 in 4 billion random strings is valid)
3. Base58 Encoding
Advantages over hex or Base64: - Human-readable (no similar-looking characters) - Compact (shorter than hex) - Double-click selectable (no special characters) - Case-sensitive (more entropy per character)
4. 'r' Prefix
All XRPL addresses start with 'r', making them: - Instantly recognizable as XRPL addresses - Distinct from Bitcoin addresses (start with 1, 3, or bc1) - Easy to validate programmatically
Address Properties
- Length: Typically 25-35 characters - Character set: Base58 (rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz) - Always starts with: 'r' - Case-sensitive: Yes - Collision resistance: 2^160 possible addresses
Comparison to Bitcoin
XRPL's address generation closely mirrors Bitcoin's P2PKH addresses:
``` Bitcoin: [Type][RIPEMD160(SHA256(pubkey))][Checksum] -> Base58 XRPL: [Type][RIPEMD160(SHA256(pubkey))][Checksum] -> Base58 ```
The main difference: Bitcoin addresses start with '1' (type 0x00), while XRPL uses 'r' for accounts.
Address Validation
```javascript const xrpl = require('xrpl');
function isValidAddress(address) { try { // Decode and verify checksum const decoded = xrpl.decodeAddress(address); return decoded.length === 20; // 160 bits } catch (e) { return false; } }
console.log(isValidAddress('rN7n7otQDd6FczFgLdlqtyMVrn3HMfgnZh')); // true console.log(isValidAddress('invalidAddress')); // false ```
Security Considerations
1. Private Key Protection: The private key must be kept secret; anyone with it controls the account 2. Deterministic Derivation: Same private key always produces same address 3. One-Way Function: Cannot derive private key from address (computationally infeasible) 4. Collision Resistance: Finding two keys with the same address requires ~2^80 operations
Common Pitfalls
1. Wrong Checksum: Manually modified addresses will fail validation 2. Case Sensitivity: 'rn7n7...' ≠ 'rN7n7...' 3. X-Address Confusion: X-addresses and classic addresses are different formats for the same account 4. Algorithm Mismatch: Cannot derive Ed25519 address from secp256k1 key
Understanding XRPL's address generation process is crucial for secure wallet implementation, address validation, and debugging integration issues. The multi-layered cryptographic approach ensures addresses are secure, error-resistant, and compatible with established blockchain standards.