Example
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:
-
Size reduction: A 256-bit hash is large for addresses. RIPEMD-160 reduces it to 160 bits, resulting in shorter addresses.
-
Security layering: Even if one hash function is found to have weaknesses, the attacker must also break the other.
-
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.
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: