TeachMeBitcoin

Example

From TeachMeBitcoin, the free encyclopedia Reading time: 3 min

3. OP_HASH160 — RIPEMD160(SHA256()) Explained

Overview

OP_HASH160 is arguably the most commonly used hash opcode in Bitcoin. It applies a double hash: first SHA-256 to the input, then RIPEMD-160 to the result, producing a 20-byte output. This is the standard way Bitcoin generates addresses from public keys.

Opcode value: 0xa9 (decimal 169)
Output size: 20 bytes (160 bits)
Formula: HASH160(x) = RIPEMD160(SHA256(x))

Why HASH160 Combines Two Hash Functions

The combination of SHA-256 followed by RIPEMD-160 was a deliberate design decision by Satoshi:

  1. Size reduction: A 256-bit hash is large for addresses. RIPEMD-160 reduces it to 160 bits, resulting in shorter addresses.

  2. Security layering: Even if one hash function is found to have weaknesses, the attacker must also break the other.

  3. Collision resistance: RIPEMD-160 provides 80-bit collision resistance; combined with SHA-256's strength, the composite is robust.

import hashlib

def hash160(data: bytes) -> bytes:
    sha256_hash = hashlib.sha256(data).digest()
    ripemd160 = hashlib.new('ripemd160')
    ripemd160.update(sha256_hash)
    return ripemd160.digest()

# Example
pubkey = bytes.fromhex("02...compressed_pubkey...")
pubkey_hash = hash160(pubkey)  # 20 bytes

P2PKH: The Classic Use Case

Pay-to-Public-Key-Hash (P2PKH) is the most common script type in Bitcoin's history. The locking script uses OP_HASH160 to commit to the hash of a public key:

# P2PKH locking script (scriptPubKey)
OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG

# P2PKH unlocking script (scriptSig)
<signature> <pubKey>

# Full execution trace
Stack start:                  [ <sig> | <pubKey> ]
After OP_DUP:                 [ <sig> | <pubKey> | <pubKey> ]
After OP_HASH160:             [ <sig> | <pubKey> | HASH160(<pubKey>) ]
After push <pubKeyHash>:      [ <sig> | <pubKey> | HASH160(<pubKey>) | <pubKeyHash> ]
After OP_EQUALVERIFY:         [ <sig> | <pubKey> ]  (fails if hashes differ)
After OP_CHECKSIG:            [ 0x01 ]

P2SH: Hashing Redeem Scripts

OP_HASH160 is also central to Pay-to-Script-Hash (P2SH), defined in BIP 16:

# P2SH locking script
OP_HASH160 <scriptHash> OP_EQUAL

# Where scriptHash = HASH160(redeemScript)

The spender must provide the original redeemScript and prove it hashes to scriptHash. This lets complex scripts be committed to compactly.

# P2SH unlocking script
<data pushes satisfying redeemScript> <redeemScript>

Bitcoin Address Generation Using HASH160

Step 1: Generate private key
private_key = random 256-bit number

Step 2: Compute public key
public_key = private_key * G  (elliptic curve multiplication)

Step 3: Apply HASH160
pubkey_hash = RIPEMD160(SHA256(public_key))

Step 4: Add version byte
versioned = 0x00 + pubkey_hash  (mainnet P2PKH)

Step 5: Compute checksum
checksum = SHA256(SHA256(versioned))[:4]

Step 6: Encode
address = Base58Check(versioned + checksum)
# Result: "1A1zP1eP5QGefi2DMPTfTL5SLmv7Divf..." style address

Security Properties of HASH160

The security of HASH160 comes from the combination. Even though RIPEMD-160 has a smaller output than SHA-256, the SHA-256 step first condenses any arbitrarily large input to 32 bytes of pseudo-random data, and then RIPEMD-160 hashes that. A collision on the final output requires either a collision in the RIPEMD-160 step (over uniform random inputs) or extremely unlikely structural attacks on both functions simultaneously.

☕ Help support TeachMeBitcoin

TeachMeBitcoin is an ad-free, open-source educational repository curated by a passionate team of Bitcoin researchers and educators for public benefit. If you found our articles helpful, please consider supporting our hosting and ongoing content updates with a clean donation:

Ethereum: 0x578417C51783663D8A6A811B3544E1f779D39A85
Bitcoin: bc1q77k9e95rn669kpzyjr8ke9w95zhk7pa5s63qzz
Solana: 4ycT2ayqeMucixj3wS8Ay8Tq9NRDYRPKYbj3UGESyQ4J
Address copied to clipboard!