# How Ethereum Addresses Are Derived from a Private Key

Source: https://www.ethvanity.com/blog/how-ethereum-addresses-are-derived

Published: 2026-11-02

Updated: 2026-11-09

![From secret to address. Private key: A secret scalar on secp256k1; Public key: Derived by elliptic-curve multiplication; Address: Last 20 bytes of the public-key Keccak-256 hash.](https://www.ethvanity.com/images/blog/how-ethereum-addresses-are-derived-diagram-v2.webp)

From secret to address. Private key: A secret scalar on secp256k1; Public key: Derived by elliptic-curve multiplication; Address: Last 20 bytes of the public-key Keccak-256 hash.

[Full-size diagram (SVG)](https://www.ethvanity.com/images/blog/how-ethereum-addresses-are-derived-diagram-v2.svg)

[Diagram download (PNG)](https://www.ethvanity.com/images/blog/how-ethereum-addresses-are-derived-diagram-v2.png)

An Ethereum address comes from a 32-byte secp256k1 private key: multiply it by the curve's generator point to get a 64-byte public key, hash that with Keccak-256, and keep the last 20 bytes, written as 0x plus 40 hex characters. Each step is one-way, so the address reveals nothing usable about the key.

## Step 1: the private key

A private key is a 256-bit number, stored as 32 bytes or 64 hex characters. It must lie between 1 and n - 1, where n is the order of the secp256k1 curve: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141, about 1.158 x 10^77. Almost every random 256-bit value is valid, since the excluded range is a tiny fraction of the total.

Security rests entirely on how the key is chosen. It must come from a cryptographically secure random number generator with the full 256 bits of entropy. Wallets usually derive keys from a BIP-39 recovery phrase through BIP-32 hierarchical derivation, with m/44'/60'/0'/0/0 as the common path for the first Ethereum account, but the end result is the same kind of 32-byte key. Vanity generators skip the phrase and search raw keys directly, which is why weak seeding, as in the [Profanity vulnerability](https://www.ethvanity.com/blog/profanity-vanity-address-vulnerability), is so damaging.

The size of the space is what makes random keys safe. With about 1.158 x 10^77 valid keys and roughly 2^160, or 1.46 x 10^48, possible addresses, two independently generated keys colliding is not a practical concern. The risk lies entirely in non-random generation, such as keys derived from short passwords, timestamps or 32-bit seeds, which attackers scan systematically.


## Step 2: the secp256k1 public key

The public key is the elliptic-curve point K = k x G, where k is the private key and G is secp256k1's fixed generator point. The point has two 32-byte coordinates, X and Y. In uncompressed SEC1 form it is written as 65 bytes: a 0x04 marker followed by X and Y. Ethereum drops the marker and uses the 64 bytes X || Y.

Computing K from k takes milliseconds. Going back from K to k is the elliptic-curve discrete logarithm problem, for which the best known classical attacks on a 256-bit curve need on the order of 2^128 operations. That asymmetry is the foundation of the whole account system.

A compressed form of the public key also exists: 33 bytes made of a 0x02 or 0x03 prefix, which records whether Y is even or odd, followed by X. Ethereum addresses are always computed from the uncompressed 64-byte X || Y, so hashing a compressed key, or hashing the 65-byte form with the 0x04 marker still attached, produces a wrong address.


## Step 3 and 4: Keccak-256 and the last 20 bytes

Ethereum hashes the 64-byte public key with Keccak-256, producing 32 bytes, and keeps the rightmost 20 bytes (160 bits) as the address. Ethereum uses the original Keccak submission, whose padding differs from the final NIST SHA3-256 standard, so a generic SHA3-256 function gives the wrong result.

Using private key 1 as a worked example, the public key is G itself, its Keccak-256 hash is 0xc0a6c424ac7157ae408398df7e5f4552091a69125d5dfcb7b8c2659029395bdf, and the last 20 bytes give the address 0x7e5f4552091a69125d5dfcb7b8c2659029395bdf. The first 12 bytes, c0a6c424ac7157ae408398df, are simply discarded.


| Stage | Size | Example for private key 1 |
| --- | --- | --- |
| Private key | 32 bytes | 0x00...0001 |
| Public key (uncompressed, no 0x04) | 64 bytes | 79be667e...(X) followed by Y |
| Keccak-256 of public key | 32 bytes | c0a6c424...395bdf |
| Address (last 20 bytes) | 20 bytes | 0x7e5f4552...29395bdf |
| EIP-55 display | 42 characters | 0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf |


## Step 5: hex encoding and the EIP-55 checksum

The 20 bytes are written as 40 hexadecimal characters with a 0x prefix. Most software then applies EIP-55: it hashes the lowercase hex text with Keccak-256 and uppercases each letter whose matching hash nibble is 8 or higher. For private key 1 that gives 0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf. The algorithm and a worked example are in [hex characters and EIP-55](https://www.ethvanity.com/blog/ethereum-vanity-address-hex-checksum).

The checksum changes only how the address is displayed. The underlying value, and the account it identifies, is the same in lowercase, uppercase or checksummed form.


## Code example with ethers v6

The snippet reproduces every step with ethers v6 and checks the result against the library's Wallet class. It uses private key 1, a famous test value whose address is publicly known and constantly watched by bots. Never send funds to this address or use any published key, including Hardhat's documented default account 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266, for anything real.


```sh
// npm install ethers@6
import { SigningKey, keccak256, dataSlice, getAddress, Wallet } from "ethers";

// TEST KEY ONLY - publicly known, never use for real funds
const privateKey = "0x0000000000000000000000000000000000000000000000000000000000000001";

const publicKey = SigningKey.computePublicKey(privateKey, false); // 0x04 + X + Y (65 bytes)
const hash = keccak256("0x" + publicKey.slice(4));            // drop 0x04, hash 64 bytes
const address = getAddress(dataSlice(hash, 12));               // last 20 bytes + EIP-55

console.log(address);                       // 0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf
console.log(new Wallet(privateKey).address); // same result
```


## Where wallet keys come from: BIP-39, BIP-32 and BIP-44

Wallets such as MetaMask do not store a single random key. BIP-39 encodes 128 bits of entropy plus a 4-bit checksum as 12 words, or 256 bits plus an 8-bit checksum as 24 words, from a 2,048-word list. The phrase is stretched with PBKDF2-HMAC-SHA512 over 2,048 iterations into a 512-bit seed, and BIP-32 turns that seed into a tree of keys. BIP-44 fixes the path m/44'/60'/0'/0/i, where 60 is Ethereum's SLIP-44 coin type and i is the account index.

Each leaf of that tree is an ordinary 32-byte secp256k1 private key, so the address derivation from step 2 onward is identical. Vanity generators usually skip the phrase layer because searching phrases would add thousands of hash iterations to every attempt. The result is a standalone key that a recovery phrase cannot restore, which is why importing one into a wallet needs separate backup, as explained in [importing a vanity key into MetaMask](https://www.ethvanity.com/blog/import-vanity-private-key-metamask).


| Layer | Standard | Output |
| --- | --- | --- |
| Mnemonic | BIP-39 | 12 or 24 words (128 or 256 bits of entropy) |
| Seed | BIP-39 PBKDF2, 2,048 rounds | 512-bit seed |
| Key tree | BIP-32 | Master key and child keys |
| Path | BIP-44 with coin type 60 | m/44'/60'/0'/0/0 for the first account |


## Why the derivation cannot be reversed

Each step is one-way. Reversing the hash would require a Keccak-256 preimage, and even with the public key in hand, recovering the private key requires solving the discrete logarithm. The truncation to 160 bits also means about 2^96 different public keys map to each address on average, so the address does not even determine a unique public key.

This is also why vanity addresses are a search problem rather than a calculation: there is no way to compute a key for a chosen address, only to try keys until one fits. Each try has a 1 in 16^n chance of matching an n-character pattern, as the [difficulty guide](https://www.ethvanity.com/blog/ethereum-vanity-address-difficulty) shows. Contract addresses follow different formulas, covered in [EOA vs CREATE2 vanity](https://www.ethvanity.com/blog/ethereum-wallet-vs-create2-vanity).

Quantum computers are the one known long-term threat to this model. Shor's algorithm would in principle solve the elliptic-curve discrete logarithm, which is why accounts whose public keys are exposed on-chain are the ones discussed in Ethereum's post-quantum research. Hashing to an address protects only keys whose public key has never been revealed. An address that has never signed anything exposes just 20 bytes of a hash, not the curve point an attacker would need.


## Explore the related mechanism

- [Ethereum Vanity Address Format: Hex Characters and EIP-55 Checksum](https://www.ethvanity.com/blog/ethereum-vanity-address-hex-checksum) — Which characters an Ethereum vanity address can use, how the EIP-55 checksum works, and why case-sensitive patterns need more attempts.
- [EOA Vanity Address vs CREATE2 Vanity Contract Address](https://www.ethvanity.com/blog/ethereum-wallet-vs-create2-vanity) — How a vanity wallet (EOA keypair search) differs from a vanity contract address mined with a CREATE2 salt, with the EIP-1014 formulas.
- [Open the complete workflow guide](https://www.ethvanity.com/guide) to place these checks in order.
- [Open the address generator](https://www.ethvanity.com/) when you have chosen a compatible format and pattern.

## Frequently asked questions

### Can two private keys produce the same Ethereum address?

Mathematically yes, because 2^256 keys map to 2^160 addresses. Finding such a collision deliberately would take around 2^80 work by the birthday bound, and hitting a specific existing address would take around 2^160, so it does not happen in practice.

### Why does Ethereum use Keccak-256 instead of SHA3-256?

Ethereum adopted Keccak before NIST finalized SHA-3 with different padding. The two functions produce different outputs for the same input, so libraries expose keccak256 separately.

### Does the chain ID affect the address?

No. The derivation uses only the key, so the same address exists on every EVM chain, as explained in [same address on every EVM chain](https://www.ethvanity.com/blog/same-address-every-evm-chain).

### Can I derive a vanity address from a recovery phrase?

In principle you could search phrases, but each attempt costs 2,048 PBKDF2 rounds plus BIP-32 derivation, so it is far slower than searching raw keys. Vanity keys are therefore usually standalone private keys that need their own backup.

### Why is the public key visible after I send a transaction?

Ethereum signatures let anyone recover the signer's public key from the signature and the signed message. Nodes use this to check that the recovered key hashes to the sender's address.

## Sources

- [ethereum.org: Ethereum accounts](https://ethereum.org/en/developers/docs/accounts/)

- [Ethereum Yellow Paper](https://ethereum.github.io/yellowpaper/paper.pdf)

- [SEC 2: Recommended elliptic curve domain parameters (secp256k1)](https://www.secg.org/sec2-v2.pdf)

- [ethers v6 documentation: SigningKey](https://docs.ethers.org/v6/api/crypto/#SigningKey)

- [BIP-39: Mnemonic code for generating deterministic keys](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki)



Editorial method: https://www.ethvanity.com/about#publication-method
