Bitcoin Keypair Generation

bitcoinbegins.com

How the original Bitcoin client created keys — live generator and full step-by-step walkthrough.
This is NOT where you should generate keypairs for real life use. Please be careful.

Background: Keys in the Early Bitcoin Client

Every time the original Bitcoin client (v0.1, released January 2009) needed a new address — whether for a coinbase reward or to receive a payment — it generated a fresh keypair automatically, using the following process:

The early client pre-generated a pool of 100 keypairs at startup, topping it up as keys were used. Each coinbase output in those first blocks used a fresh key drawn from this pool — which is why every early block has a distinct public key in its coinbase output.


Live Keypair Generator

Click the button to generate a genuine Bitcoin keypair in your browser, using real secp256k1 elliptic curve cryptography — the exact curve and algorithm used by Satoshi's original client. Every value shown is mathematically valid and correctly derived.

Important: These are cryptographically real Bitcoin keypairs. Do not use them to receive or store actual funds — they are generated in a browser page and should be treated as educational examples only. Never share a private key.

⚡ Generated Keypair

Step 1 Private Key (32 bytes, hex)
Click Generate below…
Step 2 Public Key — Uncompressed (65 bytes) · used in early blocks
2b Public Key — Compressed (33 bytes) · later improvement, not used in Block 0/1
Step 3 SHA-256 of uncompressed public key
Step 4 RIPEMD-160 of that SHA-256 — the Hash160 / pubkey hash (20 bytes)
Step 5 Version byte 0x00 prepended (mainnet)
Step 6 Checksum — first 4 bytes of double-SHA256 of Step 5
Step 7 Bitcoin Address — Base58Check of (Step 5 + checksum)
WIF Private Key — for importing into wallets (starts with 5 for uncompressed)

Step-by-Step Walkthrough

The following uses a fixed, well-known example keypair (from the Bitcoin developer documentation) so every intermediate value can be explained precisely. The same process applies to every keypair generated above.

FIXED EXAMPLE — for annotation purposes

Step 1 Generate a random private key

The private key is a random integer between 1 and n — the order of the secp256k1 curve. It must be exactly 256 bits (32 bytes). In the original Bitcoin client, this was generated by OpenSSL's RAND_bytes(), a cryptographically secure random number generator. In modern browsers, crypto.getRandomValues() serves the same purpose.

The only constraints: it must not be zero, and must be less than n (a number just slightly below 2²⁵⁶). Any valid 256-bit random number satisfies this in practice.

Example private key:

0c28fca386c7a227600b2fe50b7cae11ec86d3bf1fbe471be89827e19d72aa1d

This is a standard example private key used in Bitcoin developer documentation. The corresponding address is known and publicly documented.

Step 2 Derive the public key via elliptic curve multiplication

The public key is computed as K = k × G, where k is the private key and G is the secp256k1 generator point — a fixed, well-known point on the curve that every Bitcoin implementation uses.

This "multiplication" is not ordinary arithmetic. It is a sequence of point additions and point doublings on the elliptic curve y² = x³ + 7 (over a finite field of ~2²⁵⁶ elements). The result is a new point on the curve with coordinates (x, y). The key property is that this is a one-way function: given the result and G, you cannot work backwards to find k. This is the mathematical foundation of Bitcoin's security.

In the early Bitcoin client, the result was encoded in uncompressed format: a 04 prefix byte followed by the 32-byte x and 32-byte y coordinates (65 bytes total).

Resulting public key (uncompressed, 65 bytes):

04d0de0aaeaefad02b8bdc8a01a1b8b11c696bd3d66a2c5f10780d95b7df42645cd85228a6fb29940e858e7e55842ae2bd115d1ed7cc0e82d934e929c97648cb0a

Compressed format (introduced later, not used in the very earliest blocks): Because the secp256k1 curve is symmetric around the x-axis, the y coordinate can always be reconstructed from x. So only x needs to be stored, with prefix 02 if y is even, or 03 if y is odd — saving 32 bytes per key.

03d0de0aaeaefad02b8bdc8a01a1b8b11c696bd3d66a2c5f10780d95b7df42645c

The prefix is 03 here because the y coordinate (d852…cb0a) is odd.

Step 3 SHA-256 hash of the public key

The full 65-byte uncompressed public key is hashed using SHA-256. This is a one-way cryptographic function that always produces exactly 32 bytes of output, regardless of input size. It is not possible to reconstruct the public key from its hash.

Input: the 65-byte uncompressed public key above

SHA-256 result (32 bytes):

58618fffe27f39d1f68d8d4eb5d496ab6925d1c0e981a522720495a9720552ef

Step 4 RIPEMD-160 of the SHA-256 result

The 32-byte SHA-256 output is hashed again using RIPEMD-160, producing a 20-byte (160-bit) result. This two-step combination — SHA-256 followed by RIPEMD-160 — is called Hash160 in Bitcoin terminology, and is also referred to as the pubkey hash.

Using two independent algorithms means that breaking either one alone is not enough to reverse the process. It also produces a shorter, more practical address.

RIPEMD-160 result — the Hash160 (20 bytes):

a65d1a239d4ec666643d350c7bb8fc44d2881128

This 20-byte value is the core of the Bitcoin address. Everything else that follows is just formatting and error-checking around it.

Step 5 Prepend the network version byte

A single byte is prepended to identify which Bitcoin network this address belongs to:

The original client always used 0x00. This gives a 21-byte payload.

After prepending version byte:

00a65d1a239d4ec666643d350c7bb8fc44d2881128

Step 6 Compute the checksum

A 4-byte checksum is appended to catch transcription errors. It is computed by running the 21-byte payload through SHA-256 twice (double-SHA256), then taking the first 4 bytes of the result.

First SHA-256:

dd1cd208877a6a835fa0cee5095de605a7bc6f15efaa4bf977f733c35b050934

Second SHA-256:

268e839baa663479bad676b100524229ca219ffacd44681f472e210792b2622c

First 4 bytes — the checksum:

268e839b

If you type an address incorrectly, the checksum will not match and the wallet software will reject it before any funds are sent to an invalid address. This is why Bitcoin addresses have built-in typo detection.

Step 7 Assemble and Base58Check encode

The final address is formed by concatenating version byte + hash160 + checksum (25 bytes total), then encoding in Base58Check.

Full 25-byte payload:

00a65d1a239d4ec666643d350c7bb8fc44d2881128268e839b

Base58 is similar to Base64 but with characters removed that are easily confused when written by hand: no 0 (zero), O (capital-o), I (capital-i), or l (lowercase-L). The full Bitcoin Base58 alphabet is:

123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz

The 25-byte payload is treated as one large integer and converted to this base-58 number system. Any leading zero bytes in the payload each become a leading 1 character — which is why all legacy Bitcoin addresses start with 1 (the version byte 0x00 always encodes to 1 in Base58).

Final Bitcoin address:

1GAehh7TsJAHuUAeKZcXf5CnwuGuGgyX2S

This is the address corresponding to our example private key, using the uncompressed public key format used by the early Bitcoin client. It can be verified at any block explorer.


Bonus: WIF Format (Wallet Import Format)

Internally, wallet.dat stored private keys as raw bytes. But when a key needed to be exported, backed up as text, or shared between wallets, Bitcoin uses WIF (Wallet Import Format) — the same Base58Check process applied to the private key rather than the address.

How WIF is constructed

The process mirrors address derivation:

  1. Take the 32-byte raw private key
  2. Prepend version byte 0x80 (mainnet private key)
  3. Optionally append 0x01 if the corresponding public key is compressed (not done in early client)
  4. Compute double-SHA256, take first 4 bytes as checksum
  5. Base58Check encode the result

WIF breakdown for our example:

80 0c28fca386c7a227600b2fe50b7cae11ec86d3bf1fbe471be89827e19d72aa1d 507a5b8d
version 0x80  private key (32 bytes)  checksum (4 bytes)

Encoded WIF key:

5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ

WIF keys for uncompressed public keys always start with 5. Keys for compressed public keys start with K or L. Since the early Bitcoin client used only uncompressed keys, all early WIF exports begin with 5.


How the Early Client Stored These Keys

Every generated keypair was written into wallet.dat — a Berkeley DB database file in the Bitcoin data directory. The file held the raw private key bytes, the corresponding public key, and metadata such as creation time and optional labels.

File wallet.datBerkeley DB 4.x format. A widely-used embedded database library from the early 2000s, used by many applications of the era.
Encryption None — Bitcoin v0.1 through v0.3Wallet encryption was added in Bitcoin 0.4.0, September 2011 — over two and a half years after launch. Before this, anyone with access to wallet.dat had immediate, complete access to all private keys and therefore all funds.
Key pool 100 pre-generated keypairsGenerated at startup and maintained as a pool. New keys were generated to replace used ones. This meant a backup taken today might not contain keys generated tomorrow — leading to loss of funds if a stale backup was later restored.
Key generation OpenSSL EC_KEY_generate_key()The original client delegated key generation entirely to OpenSSL, which uses the operating system's cryptographically secure random number generator internally.
Windows location %APPDATA%\Bitcoin\wallet.dat
Linux / Mac location ~/.bitcoin/wallet.dat
The stale backup problem
If you backed up wallet.dat today and continued using the wallet, new keypairs would be drawn from the pool and eventually exhausted — after which the client would generate entirely new keys that were not in your backup. Any funds received to those new addresses would be permanently unrecoverable if you ever restored from the old backup. Satoshi's advice was to back up after every few transactions. This caused real losses for many early users.

Summary

The keypair generation process — unchanged in its fundamentals from those first blocks to today — involves just a handful of steps. Private key → elliptic curve multiplication → public key → double hash → address. Each step is a one-way operation, so the chain cannot be reversed: an address doesn't reveal the public key it came from, and the public key doesn't reveal the private key.

Every coinbase transaction in those first Bitcoin blocks — each with its own fresh key drawn from Satoshi's 100-key pool — was generated exactly this way, written to an unencrypted file on disk, and treated as the sole record of ownership of those 50 BTC.