# Addresses Accounts in the XRP Ledger are identified by an address in the XRP Ledger's [base58](/docs/references/protocol/data-types/base58-encodings) format. The address is derived from the account's master [public key](https://en.wikipedia.org/wiki/Public-key_cryptography), which is in turn derived from a secret key. An address is represented as a string in JSON and has the following characteristics: * Between 25 and 35 characters in length * Starts with the character `r` * Uses alphanumeric characters, excluding the number "`0`" capital letter "`O`", capital letter "`I`", and lowercase letter "`l`" * Case-sensitive * Includes a 4-byte checksum so that the probability of generating a valid address from random characters is approximately 1 in 232 Note There is also an **X**-address format that "packs" a [destination tag](/docs/concepts/transactions/source-and-destination-tags) into the address. These addresses start with an `X` (for Mainnet) or a `T` (for [test networks](/docs/concepts/networks-and-servers/parallel-networks)). Exchanges and wallets can use X-addresses to represent all the data a customer needs to know in one value. For more information, see the [X-address format site](https://xrpaddress.info/) and [codec](https://github.com/xrp-community/xrpl-tagged-address-codec). The XRP Ledger protocol only supports "classic" addresses natively, but many [client libraries](/docs/references/client-libraries) support X-addresses too. Any valid address can [become an account in the XRP Ledger](/docs/concepts/accounts#creating-accounts) by being funded. You can also use an address that has not been funded to represent a [regular key](/docs/concepts/accounts/cryptographic-keys) or a member of a [signer list](/docs/concepts/accounts/multi-signing). Only a funded account can be the sender of a transaction. Creating a valid address is a strictly mathematical task starting with a key pair. You can generate a key pair and calculate its address entirely offline without communicating to the XRP Ledger or any other party. The conversion from a public key to an address involves a one-way hash function, so it is possible to confirm that a public key matches an address but it is impossible to derive the public key from the address alone. (This is part of the reason why signed transactions include the public key *and* the address of the sender.) ## Special Addresses Some addresses have special meaning, or historical uses, in the XRP Ledger. In many cases, these are "black hole" addresses, meaning the address is not derived from a known secret key. Since it is effectively impossible to guess a secret key from only an address, any XRP possessed by black hole addresses is lost forever. | Address | Name | Meaning | Black Hole? | | --- | --- | --- | --- | | `rrrrrrrrrrrrrrrrrrrrrhoLvTp` | ACCOUNT_ZERO | An address that is the XRP Ledger's [base58](/docs/references/protocol/data-types/base58-encodings) encoding of the value `0`. In peer-to-peer communications, `rippled` uses this address as the issuer for XRP. | Yes | | `rrrrrrrrrrrrrrrrrrrrBZbvji` | ACCOUNT_ONE | An address that is the XRP Ledger's [base58](/docs/references/protocol/data-types/base58-encodings) encoding of the value `1`. In the ledger, [RippleState entries](/docs/references/protocol/ledger-data/ledger-entry-types/ripplestate) use this address as a placeholder for the issuer of a trust line balance. | Yes | | `rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh` | The genesis account | When `rippled` starts a new genesis ledger from scratch (for example, in stand-alone mode), this account holds all the XRP. This address is generated from the seed value `masterpassphrase` which is [hard-coded](https://github.com/XRPLF/rippled/blob/70d5c624e8cf732a362335642b2f5125ce4b43c1/src/xrpld/app/ledger/Ledger.cpp#L184). | No | | `rrrrrrrrrrrrrrrrrNAMEtxvNvQ` | Ripple Name reservation black-hole | In the past, Ripple asked users to send XRP to this account to reserve Ripple Names. | Yes | | `rrrrrrrrrrrrrrrrrrrn5RM1rHd` | NaN Address | Old JavaScript client libraries generated this address when encoding the value [NaN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NaN) using the XRP Ledger's [base58](/docs/references/protocol/data-types/base58-encodings) string encoding format. | Yes | ## Address Encoding These technical details are only relevant for people building low-level library software for XRP Ledger compatibility! [[Source]](https://github.com/XRPLF/rippled/blob/70d5c624e8cf732a362335642b2f5125ce4b43c1/src/libxrpl/protocol/AccountID.cpp#L133-L175) XRP Ledger addresses are encoded using [base58](/docs/references/protocol/data-types/base58-encodings) with the *dictionary* `rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz`. Since the XRP Ledger encodes several types of keys with base58, it prefixes the encoded data with a one-byte "type prefix" (also called a "version prefix") to distinguish them. The type prefix causes addresses to usually start with different letters in base58 format. The following diagram shows the relationship between keys and addresses: [](/assets/address-encoding.33a06633d99b1ebd63484567699c1de91f162670abca5bbb1fa89a0eb4488e8c.ac57e6ef.svg) 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/XRPLF/xrpl-dev-portal/blob/master/_code-samples/address_encoding/js/encode_address.js). For the process of deriving a public key from a passphrase or seed value, see [Key Derivation](/docs/concepts/accounts/cryptographic-keys#key-derivation). 1. Import required algorithms: SHA-256, RIPEMD160, and base58. Set the dictionary for base58. ``` 'use strict'; const assert = require('assert'); const crypto = require('crypto'); const R_B58_DICT = 'rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz'; const base58 = require('base-x')(R_B58_DICT); assert(crypto.getHashes().includes('sha256')); assert(crypto.getHashes().includes('ripemd160')); ``` 2. Start with a 33-byte ECDSA secp256k1 public key, or a 32-byte Ed25519 public key. For Ed25519 keys, prefix the key with the byte `0xED`. ``` const pubkey_hex = 'ED9434799226374926EDA3B54B1B461B4ABF7237962EAE18528FEA67595397FA32'; const pubkey = Buffer.from(pubkey_hex, 'hex'); assert(pubkey.length == 33); ``` 3. Calculate the [RIPEMD160](https://en.wikipedia.org/wiki/RIPEMD) hash of the SHA-256 hash of the public key. This value is the "Account ID". ``` const pubkey_inner_hash = crypto.createHash('sha256').update(pubkey); const pubkey_outer_hash = crypto.createHash('ripemd160'); pubkey_outer_hash.update(pubkey_inner_hash.digest()); const account_id = pubkey_outer_hash.digest(); ``` 4. Calculate the SHA-256 hash of the SHA-256 hash of the Account ID; take the first 4 bytes. This value is the "checksum". ``` const address_type_prefix = Buffer.from([0x00]); const payload = Buffer.concat([address_type_prefix, account_id]); const chksum_hash1 = crypto.createHash('sha256').update(payload).digest(); const chksum_hash2 = crypto.createHash('sha256').update(chksum_hash1).digest(); const checksum = chksum_hash2.slice(0,4); ``` 5. Concatenate the payload and the checksum. Calculate the base58 value of the concatenated buffer. The result is the address. ``` const dataToEncode = Buffer.concat([payload, checksum]); const address = base58.encode(dataToEncode); console.log(address); // rDTXLQ7ZKZVKz33zJbHjgVShjsBnqMBhmN ```