Bitcoin Keys 101 - From seed phrase to address

This article explains the generation of private keys in Bitcoin until obtaining a public address and the different type of addresses available.

[TOC]

General workflow

The basic worklow is the following

1.Generate the seed phrase

Note: this is not a required step, you can directly generate the private key, but this is a standard practice in Bitcoin Wallets, defined in BIP-39.

More information in my article: Bitcoin Keys 102: How Wallets Generate Seed Phrases and Private Keys

2.Create a private key

3.Compute the public key

4.Derive the Bitcoin address from the public key

Bitcoin-address-bitcoin-address-basic-workflow.drawio

Create a Bitcoin address

Create a Legacy Bitcoin Address

Private key generation

  • A private key is generated randomly. It is a 256-bit number that serves as the secret key for spending Bitcoin from the address it generates.
  • In Bitcoin, this is often done using a secure pseudorandom number generator to ensure privacy and security.

Bitcoin-address-bitcoin address.drawio

Public key generation

Using Elliptic Curve Cryptography (ECC), specifically the secp256k1 curve in Bitcoin, the private key is used to generate a corresponding public key.

ecp256k1’s elliptic curve \(\begin{aligned} y2 = x3 + 7 \end{aligned}\) Secp256k1

  • This public key is a 512-bit number (or 64 bytes in hexadecimal format).

Hash

  • Perform SHA-256 Hashing on the Public Key:

The public key is hashed using the SHA-256 hashing algorithm, producing a 256-bit hash.

  • Apply RIPEMD-160 Hashing:

The result from the SHA-256 hash is then hashed using the RIPEMD-160 hashing algorithm, which produces a 160-bit (20 bytes) output. This is called the Public Key Hash (PKH).

Add a Version Byte

A version byte is added to the beginning of the Public Key Hash. For standard Bitcoin addresses, this version byte is 0x00 (or 00 in hexadecimal). The purpose of the version byte is to help distinguish address types.

Type Version prefix (hex) Base58 result prefix
Address for pay to public key hash (P2PKH) 0x00 1
Address for pay to script hash (P2SH) 0x05 3
Testnet Address for P2PKH 0x6F m or n
Testnet Address for P2SH 0xC4 2
Private Key WIF 0x80 5, K, or L
BIP32 Extended Public Key 0x0488B21E xpub

Calculate the Checksum

  • The versioned Public Key Hash is then double-hashed using SHA-256.

  • The first 4 bytes of this second hash become the checksum, which is appended to the end of the versioned Public Key Hash.

Encode in Base58

The resulting byte sequence (versioned Public Key Hash + checksum) is encoded using Base58Check encoding, resulting in a human-readable Bitcoin address. \(Base58Check(Versioned Public Key hash||checksum)\) This process generates a string, such as 1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa, which is the Bitcoin address.

Main reference: bitcoin.it - Technical background of version 1 Bitcoin addresses

P2SH details

From bip-0013

This bitcoin address type is constructed in the same manner as legal bitcoin addresses with Base58Check encoding:

    base58-encode: [one-byte version][20-byte hash][4-byte checksum]
  • Version byte is 5 for a main-network address, 196 for a testnet address.

  • The 20-byte hash is the hash of the script that will be used to redeem the coins.
  • And the 4-byte checksum is the first four bytes of the double SHA256 hash of the version and hash.

Variation

Native SegWit (Bech32)

Bech32 is a segwit address format specified by BIP 0173 (Bech32) and BIP 0350 (Bech32m). This address format is also known as “bc1 addresses”. This type of address is considered as more efficient (so lower fees) than a traditionnal legacy addresss because it uses less block space.

The main difference is that the encodage algorithm used is Bech32 instead of Base58Check for a legacy address.

Format: Starts with bc1q...

How it’s created:

  • Same initial steps as Legacy (generate pubkey, hash it with SHA-256 and RIPEMD-160)
  • These operation gives an array of 8-bit unsigned integers (base 2^8=256)

Then:

  • Encode it using Bech32 which converts the hash value to an array of 5-bit unsigned integers
  • Add the witness version byte (0) in front of the previous step
  • Compute the checksum by using the data from previous step and the network identifier (bc for MainNet and tb for TestNet) and append it to the previous step
  • …and some additional steps explained here

Reference: en.bitcoin.it/wiki/Bech32

Summary Table

Address Type BIP Format Prefix Script Type Encoding
Legacy - 1 P2PKH Base58Check
P2SH bip-0013 3 P2SH Base58Check
SegWit BIP_0173 bc1q... P2WPKH / P2WSH Bech32
Taproot BIP_0350 bc1p... P2TR Bech32m

Reference

You might also enjoy