RIPEMD-160: The Hash Function That Shortens Bitcoin Addresses
Complete guide with Theory, Mathematics, and Code โ understand how Bitcoin creates user-friendly addresses
1.1 What is RIPEMD-160?
RIPEMD-160 (RACE Integrity Primitives Evaluation Message Digest 160-bit) is a cryptographic hash function developed in 1996 by Hans Dobbertin, Antoon Bosselaers, and Bart Preneel. It was created as a backup hash function to SHA-1 in case SHA-1 was compromised.
Think of RIPEMD-160 as a fingerprint shortener. While SHA-256 produces a 64-character fingerprint, RIPEMD-160 produces a 40-character version. Both uniquely identify data, but the shorter one is much easier for humans to read, write, and share โ perfect for Bitcoin addresses.
- RIPE โ RACE Integrity Primitives Evaluation (a European research project)
- MD โ Message Digest
- 160 โ Output size in bits (20 bytes / 40 hex characters)
1.2 Why Does Bitcoin Use RIPEMD-160?
Bitcoin uses RIPEMD-160 for one specific but crucial purpose: shortening addresses.
1.2.1 The Address Length Problem
A SHA-256 hash of a public key is 64 hexadecimal characters (256 bits). If Bitcoin used SHA-256 directly for addresses, addresses would look like:
That's far too long for users to comfortably read, write, or share โ and highly prone to typos!
1.2.2 The Solution: RIPEMD-160
By applying RIPEMD-160 to the SHA-256 hash, we get a 40-character output (160 bits):
- SHA-256 alone: 64 hex characters (256 bits) โ too long for manual entry
- RIPEMD-160: 40 hex characters (160 bits) โ much more user-friendly
- Savings: 24 characters shorter! (37.5% reduction)
1.2.3 Why 160 Bits Specifically?
160 bits provides 2ยนโถโฐ possible addresses โ about 1.46 ร 10โดโธ (1.46 septillion). That's more than enough for every person on Earth to have billions of addresses. It's the perfect balance between security and usability.
1.3 The HASH160 Process (Combining SHA-256 and RIPEMD-160)
Bitcoin combines SHA-256 and RIPEMD-160 in a process called HASH160:
- If SHA-256 is compromised โ RIPEMD-160 provides backup security
- If RIPEMD-160 is compromised โ SHA-256 provides backup security
- Together they are stronger than either alone โ an attacker would need to break both!
1.4 The Unique Parallel Design
RIPEMD-160 has a unique double-branch parallel structure โ two independent processing lines that run simultaneously and then combine their results.
80 steps total
80 steps total
The parallel design makes certain cryptographic attacks much harder. An attacker would need to break both lines simultaneously to compromise the hash function โ a significantly more difficult task than attacking a single line.
1.5 Security Analysis
1.5.1 RIPEMD-160 vs SHA-1
RIPEMD-160 was designed as a backup to SHA-1. SHA-1 was broken in 2017 (researchers found two different PDF files with the same SHA-1 hash). RIPEMD-160 remains secure because its parallel design makes attacks much harder.
| Hash Function | Output Size | Status | Why? |
|---|---|---|---|
| SHA-1 | 160 bits | โ Broken (2017) | Collision attack discovered |
| RIPEMD-160 | 160 bits | โ Still Secure | Parallel design resists attacks |
1.5.2 Why Bitcoin Still Uses It
Despite being developed in 1996, RIPEMD-160 remains secure for Bitcoin's use case because:
- The HASH160 combination adds SHA-256 as a first layer of defense
- Even if RIPEMD-160 had weaknesses, the SHA-256 layer provides backup security
- No practical attacks against RIPEMD-160 exist in Bitcoin's context
- The parallel design has aged remarkably well
SHA-1 was broken because its design had structural weaknesses that allowed collisions. RIPEMD-160's parallel design creates a much larger "attack surface" โ an attacker would need to find vulnerabilities in both lines simultaneously, which has proven to be computationally infeasible.
1.6 Real Bitcoin Address Example
Let's trace how Satoshi's public key became a Bitcoin address using RIPEMD-160:
# Step 1: Public Key (Satoshi's Genesis block)
pubkey = "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac"
# Step 2: SHA-256 hash
sha256_hash = "0f715b7b5e67e0adabfca9b8b6d1e1f2f3e4f5f6f7f8f9fafbfcfdfeff0f1f2"
# Step 3: RIPEMD-160 hash (HASH160)
ripemd160_hash = "62e907b15cbf27d5425399ebf6f0fb50ebb88f18"
# Step 4: Add version byte (0x00 for mainnet)
versioned = "00" + ripemd160_hash
# Step 5: Add checksum (first 4 bytes of double SHA-256)
checksum = "88f0e1d2"
with_checksum = versioned + checksum
# Step 6: Base58Check encode
address = "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"
print(f"Satoshi's Address: {address}")
This address (1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa) belongs to Satoshi Nakamoto. It contains the 50 BTC genesis reward โ which is unspendable due to a quirk in the code. Those coins sit there forever as a historical artifact, and the address is now iconic in Bitcoin history.
1.7 Common Misconceptions
Truth: RIPEMD-160 is NOT broken. While SHA-1 (also 160 bits) was broken in 2017, RIPEMD-160's parallel design has prevented similar attacks. No practical collisions have ever been found.
Truth: SHA-256 would produce 64-character addresses โ too long for practical use. Bitcoin addresses are meant to be shared between humans; shorter is better. RIPEMD-160 provides the perfect balance.
Truth: RIPEMD-160 is still actively used in Bitcoin and remains secure. Every Bitcoin address (billions of them) depends on RIPEMD-160. It's far from obsolete โ it's battle-tested!
1.8 Comparison with Other Hash Functions
| Hash Function | Output Size | Block Size | Rounds | Status | Used In |
|---|---|---|---|---|---|
| RIPEMD-160 | 160 bits | 512 bits | 80 | โ Secure | Bitcoin addresses (HASH160) |
| SHA-256 | 256 bits | 512 bits | 64 | โ Secure | Bitcoin mining, TXIDs, blocks |
| SHA-1 | 160 bits | 512 bits | 80 | โ Broken (2017) | Git (legacy), SSL (deprecated) |
| MD5 | 128 bits | 512 bits | 64 | โ Broken (2004) | Checksums only |
2.1 Overview of the RIPEMD-160 Algorithm
RIPEMD-160 processes data in 512-bit chunks (64 bytes). It uses a unique parallel processing design with two independent lines of 5 registers each (10 registers total).
2.2 MD5 Initial Values (The Starting Point)
RIPEMD-160 uses the same initial values as MD5 for compatibility. These values are the fractional parts of the square roots of 2, 3, 5, and 7, converted to 32-bit integers.
| Register | Initial Value (Hex) | Derivation |
|---|---|---|
| A / A' | 0x67452301 | fractional part of โ2: 0.41421356237 ร 2ยณยฒ |
| B / B' | 0xEFCDAB89 | fractional part of โ3: 0.73205080756 ร 2ยณยฒ |
| C / C' | 0x98BADCFE | fractional part of โ5: 0.23606797749 ร 2ยณยฒ |
| D / D' | 0x10325476 | fractional part of โ7: 0.64575131106 ร 2ยณยฒ |
| E / E' | 0xC3D2E1F0 | MD5 constant (derived from ฯ) |
These constants are "nothing up my sleeve" numbers โ derived from irrational square roots, proving no backdoor was hidden. Using the same values as MD5 allowed developers to reuse code and hardware implementations.
A = 0x67452301 = 01100111010001010010001100000001 (32 bits)
B = 0xEFCDAB89 = 11101111110011011010101110001001
C = 0x98BADCFE = 10011000101110101101110011111110
D = 0x10325476 = 00010000001100100101010001110110
E = 0xC3D2E1F0 = 11000011110100101110000111110000
2.3 The Two Parallel Lines (Left and Right)
RIPEMD-160 processes data on two independent lines simultaneously:
- Increased security: An attacker would need to break both lines simultaneously
- Defense in depth: Even if one line has a weakness, the other provides backup
- Resistance to cryptanalysis: Many attacks target single-line hash functions
2.4 Step 1: Input Padding
The input message must be padded to a multiple of 512 bits (same as SHA-256, but with different endianness).
1. Append a '1' bit to the message
2. Append '0' bits until length โก 448 (mod 512)
3. Append L as a 64-bit integer (little-endian) โ different from SHA-256!
Result: Total length = multiple of 512 bits
SHA-256 uses big-endian for length padding.
RIPEMD-160 uses little-endian for length padding.
SHA-256: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x18 (big-endian)
RIPEMD-160: 0x18 0x00 0x00 0x00 0x00 0x00 0x00 0x00 (little-endian)
This is a common source of bugs when implementing RIPEMD-160!
2.5 Step 2: Message Decomposition
The padded message is split into 512-bit chunks. Each chunk is divided into 16 words of 32 bits each.
Each X[j] is a 32-bit unsigned integer (0 to 4,294,967,295)
Note: RIPEMD-160 uses little-endian word ordering!
2.6 Step 3: The 5 Boolean Functions
Each round uses a different Boolean function. These functions are applied to three 32-bit inputs and produce one 32-bit output.
| Round | Function Name | Formula | Truth Table (1 bit example) |
|---|---|---|---|
| 1 | F1 | X โ Y โ Z | XOR all three bits: 1 if odd number of 1s |
| 2 | F2 | (X โง Y) โจ (ยฌX โง Z) | If X=1, output Y; if X=0, output Z (selector) |
| 3 | F3 | (X โจ ยฌY) โ Z | Majority-like function |
| 4 | F4 | (X โง Z) โจ (Y โง ยฌZ) | If Z=1, output X; if Z=0, output Y (selector, swapped) |
| 5 | F5 | X โ (Y โจ ยฌZ) | XOR with OR |
F2: (0b1100 โง 0b1010) โจ (ยฌ0b1100 โง 0b0111) = 0b1000 โจ 0b0011 = 0b1011
2.7 Step 4: Round Constants K[r]
Five constants, one for each round, derived from the cube roots of small integers:
K[1] = 0x5A827999 (for rounds 16-31) โ floor(2ยณโฐ ร โ2)
K[2] = 0x6ED9EBA1 (for rounds 32-47) โ floor(2ยณโฐ ร โ3)
K[3] = 0x8F1BBCDC (for rounds 48-63) โ floor(2ยณโฐ ร โ5)
K[4] = 0xA953FD4E (for rounds 64-79) โ floor(2ยณโฐ ร โ7)
Both lines use the same constants but in different orders:
- Left line: K[0], K[1], K[2], K[3], K[4] (ascending)
- Right line: K[4], K[3], K[2], K[1], K[0] (descending)
2.8 Step 5: Rotation Amounts s[j]
Each of the 80 steps uses a specific rotation amount. The left and right lines use different rotation schedules.
| Round | Left Line Rotation Amounts (s values) | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 11 | 14 | 15 | 12 | 5 | 8 | 7 | 9 | 11 | 13 | 14 | 15 | 6 | 7 | 9 | 8 |
| 2 | 7 | 6 | 8 | 13 | 11 | 9 | 7 | 15 | 7 | 12 | 15 | 9 | 11 | 7 | 13 | 12 |
| 3 | 11 | 13 | 6 | 7 | 14 | 9 | 13 | 15 | 14 | 8 | 13 | 6 | 5 | 12 | 7 | 5 |
| 4 | 11 | 12 | 14 | 15 | 14 | 15 | 9 | 8 | 9 | 14 | 5 | 6 | 8 | 6 | 5 | 12 |
| 5 | 9 | 15 | 5 | 11 | 6 | 8 | 13 | 12 | 5 | 12 | 13 | 14 | 11 | 8 | 5 | 6 |
A rotation moves bits to the right; bits that "fall off" reappear on the left.
0b10110010 โ 2 = 0b10101100
Step by step:
Original: 1 0 1 1 0 0 1 0
Last 2 bits (10) move to front: 1 0
Remaining bits shift right: 1 0 1 1 0 0
Result: 1 0 1 0 1 1 0 0
0x12345678 = 00010010 00110100 01010110 01111000
โ 8 = 01111000 00010010 00110100 01010110 = 0x78123456
2.9 Step 6: Message Word Order (Permutations)
The 16 message words are permuted differently for each round. This ensures each word affects the hash in multiple ways.
| Round | Left Line Word Order (r[j]) | Right Line Word Order (r'[j]) | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 | 5,14,7,0,9,2,11,4,13,6,15,8,1,10,3,12 | ||||||||||||||
| 2 | 7,4,13,1,10,6,15,3,12,0,9,5,2,14,11,8 | 6,11,3,7,0,13,5,10,14,15,8,12,4,9,1,2 | ||||||||||||||
| 3 | 3,10,14,4,9,15,8,1,2,7,0,6,13,11,5,12 | 15,5,1,3,7,14,6,9,11,8,12,2,10,0,4,13 | ||||||||||||||
| 4 | 1,9,11,10,0,8,12,4,13,3,7,15,14,5,6,2 | 8,6,4,1,3,11,15,0,5,12,2,13,9,7,10,14 | ||||||||||||||
| 5 | 4,0,5,9,7,12,2,10,14,1,3,8,11,6,15,13 | 12,15,10,4,1,5,8,7,6,2,13,14,0,3,9,11 | ||||||||||||||
2.10 Step 7: The Round Function (Per-Step)
Each step updates the registers on both lines independently:
T = (a + F(b, c, d) + X[r[j]] + K[round]) โ s[j]
a = d
d = c
c = b
b = T
Right line calculation (parallel):
T' = (a' + F(b', c', d') + X[r'[j]] + K'[round]) โ s'[j]
a' = d'
d' = c'
c' = b'
b' = T'
2.11 Step 8: The 5 Rounds (80 Steps Total)
Each round consists of 16 steps with:
- A specific Boolean function (F1 through F5)
- A specific constant (K[0] through K[4])
- A specific rotation schedule
- A specific word permutation
2.12 Step 9: Combining Left and Right Results
After all 80 steps, the results from both lines are added to the initial values:
B_final = B_initial + B + B'
C_final = C_initial + C + C'
D_final = D_initial + D + D'
E_final = E_initial + E + E'
Final Hash = A_final || B_final || C_final || D_final || E_final
(20 bytes / 160 bits / 40 hex characters)
Adding the results from both lines ensures that an attacker cannot simply attack just one line. The final output depends on both parallel computations โ making the hash stronger than either line alone. Even if an attacker breaks one line, they would still need to break the other.
2.13 Why Parallel Design Is More Secure
Single line: Attack complexity = 2โธโฐ
Both lines: Attack complexity = 2ยนโถโฐ (impossible)
The parallel design ensures that even if cryptanalysts find a weakness in one line, the other line provides backup security. This "defense in depth" approach is why RIPEMD-160 has outlived SHA-1 despite both having 160-bit outputs.
2.14 Complete Example: Hash of "abc" (Step by Step)
Let's walk through the entire RIPEMD-160 algorithm using the message "abc" โ the classic test vector. This example shows every step from the original ASCII characters to the final 160-bit hash.
Step 2.14.1: Original Message (ASCII to Binary)
The message "abc" consists of three ASCII characters. Let's convert each to binary:
| Character | ASCII (Decimal) | ASCII (Hex) | ASCII (Binary) | Meaning |
|---|---|---|---|---|
| a | 97 | 0x61 | 01100001 | First character |
| b | 98 | 0x62 | 01100010 | Second character |
| c | 99 | 0x63 | 01100011 | Third character |
01100001 01100010 01100011
Total length: 3 characters ร 8 bits = 24 bits
Text: "abc"
Hex: 61 62 63
Binary: 01100001 01100010 01100011
Step 2.14.2: Padding (to 512 bits)
Rule 1: Append a '1' bit
Hex: 61 62 63 80 (because 10000000 binary = 0x80)
Length: 25 bits
Rule 2: Append zeros until length โก 448 (mod 512)
Current length: 25 bits. We need 448 bits. Zeros to add: 448 - 25 = 423 zeros
Length: 448 bits
Rule 3: Append original length as 64-bit integer (little-endian!)
Original length = 24 bits = 0x18 in hex
Final padded message (512 bits / 64 bytes):
Row 2: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Row 3: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Row 4: 00 00 00 00 00 00 00 00 00 00 00 00 18 00 00 00
- 61 62 63 = "abc" in ASCII
- 80 = the appended '1' bit (10000000 in binary)
- 00 00 ... 00 = 423 zeros (padding)
- 18 00 00 00 00 00 00 00 = original length 24 (0x18) in little-endian format
61 = 01100001 (a)
62 = 01100010 (b)
63 = 01100011 (c)
80 = 10000000 (the appended '1' bit)
Step 2.14.3: Message Decomposition (16 words of 32 bits)
The 512-bit block is split into 16 words (X[0] to X[15]), each 32 bits (4 bytes):
| Word | Bytes (Hex) | 32-bit Value (Hex) | Decimal |
|---|---|---|---|
| X[0] | 61 62 63 80 | 0x61626380 | 1,634,762,624 |
| X[1] | 00 00 00 00 | 0x00000000 | 0 |
| X[2] | ... all zeros ... | ||
| ... | ... | ||
| X[14] | 00 00 00 00 | 0x00000000 | 0 |
| X[15] | 18 00 00 00 | 0x18000000 | 402,653,184 |
X[15] = 0x18000000 because the length (24) is stored in little-endian format:
The bytes are: 18 00 00 00 โ when read as a 32-bit little-endian integer, this becomes 0x18000000
Step 2.14.4: Initialize Working Variables (10 registers)
The initial values for both left and right lines (from MD5):
A = 0x67452301
B = 0xEFCDAB89
C = 0x98BADCFE
D = 0x10325476
E = 0xC3D2E1F0
Right Line (A', B', C', D', E') start with the SAME values!
Step 2.14.5: Round Constants Used
K[1] = 0x5A827999 (Rounds 16-31)
K[2] = 0x6ED9EBA1 (Rounds 32-47)
K[3] = 0x8F1BBCDC (Rounds 48-63)
K[4] = 0xA953FD4E (Rounds 64-79)
Step 2.14.6: Round 1 โ First Few Steps (Left Line)
Round 1 uses: Function F1 (XOR), Constant K[0] = 0x00000000, Rotation schedule for steps 0-15
| Step | Word Index | Word Value (X[r[j]]) | Rotation (s) | Operation |
|---|---|---|---|---|
| 0 | 0 | 0x61626380 | 11 | T = (A + F1(B,C,D) + X[0] + K[0]) โ 11 |
| 1 | 1 | 0x00000000 | 14 | T = (A + F1(B,C,D) + X[1] + K[0]) โ 14 |
| 2 | 2 | 0x00000000 | 15 | T = (A + F1(B,C,D) + X[2] + K[0]) โ 15 |
= 0xEFCDAB89 โ 0x98BADCFE โ 0x10325476
= (0xEFCDAB89 โ 0x98BADCFE) โ 0x10325476
= 0x77777777 โ 0x10325476
= 0x67452303
temp = A + F1 + X[0] + K[0]
= 0x67452301 + 0x67452303 + 0x61626380 + 0x00000000
= 0x67545184 (after modulo 2ยณยฒ)
T = temp โ 11 = rotate right 11 bits = 0xE452C0CD
Then the register rotation occurs.
Step 2.14.7: After All 80 Steps (Both Lines)
After processing all 5 rounds (80 steps) on both the left and right lines, we have final values for all 10 registers.
A = 0x67452301 (but modified through 80 steps)
B = 0xEFCDAB89 (modified)
C = 0x98BADCFE (modified)
D = 0x10325476 (modified)
E = 0xC3D2E1F0 (modified)
Right Line final values:
A' = (different values)
B' = (different values)
C' = (different values)
D' = (different values)
E' = (different values)
Step 2.14.8: Combining Left and Right Results
The final hash is computed by adding the initial values, left line results, and right line results:
B_final = B_initial + B + B'
C_final = C_initial + C + C'
D_final = D_initial + D + D'
E_final = E_initial + E + E'
Step 2.14.9: The Final 160-bit Hash
After all calculations, the RIPEMD-160 hash of "abc" is:
import hashlib
# Compute RIPEMD-160 hash of "abc"
hash_result = hashlib.new('ripemd160', b"abc").hexdigest()
print(f"RIPEMD-160('abc') = {hash_result}")
# Output: 8eb208f7e05d987a9b044a8e98c6b087f15a0bfc
Step 2.14.10: Comparison โ RIPEMD-160 vs SHA-1
Both produce 40-character hashes, but they are completely different:
| Algorithm | Hash of "abc" |
|---|---|
| RIPEMD-160 | 8eb208f7e05d987a9b044a8e98c6b087f15a0bfc |
| SHA-1 (broken) | a9993e364706816aba3e25717850c26c9cd0d89d |
- Input: "abc" (3 bytes / 24 bits)
- After padding: 64 bytes (512 bits)
- Number of 512-bit blocks: 1
- Rounds processed: 80 steps on left line + 80 steps on right line
- Final hash length: 160 bits (20 bytes / 40 hex characters)
- Output: 8eb208f7e05d987a9b044a8e98c6b087f15a0bfc
3.1 Installation (No external dependencies needed)
The code below uses only Python's built-in libraries. RIPEMD-160 is available in Python's hashlib module.
hashlibโ includes RIPEMD-160 supportstructโ for byte packing
3.2 Simple Hash Example
import hashlib
# Basic RIPEMD-160 hash
message = b"Hello, Bitcoin!"
hash_result = hashlib.new('ripemd160', message).hexdigest()
print(f"RIPEMD-160: {hash_result}")
# Bitcoin's HASH160 (SHA-256 then RIPEMD-160)
def hash160(data):
sha256_hash = hashlib.sha256(data).digest()
return hashlib.new('ripemd160', sha256_hash).hexdigest()
bitcoin_hash = hash160(b"Hello, Bitcoin!")
print(f"HASH160: {bitcoin_hash}")
3.3 Complete Implementation
#!/usr/bin/env python3
"""
RIPEMD-160 Implementation in Python
Uses hashlib (built-in) for simplicity
"""
import hashlib
import struct
def ripemd160(data):
"""RIPEMD-160 hash function"""
if isinstance(data, str):
data = data.encode('utf-8')
return hashlib.new('ripemd160', data).hexdigest()
def hash160(data):
"""Bitcoin's HASH160: SHA-256 then RIPEMD-160"""
if isinstance(data, str):
data = data.encode('utf-8')
# Step 1: SHA-256
sha256_hash = hashlib.sha256(data).digest()
# Step 2: RIPEMD-160
return hashlib.new('ripemd160', sha256_hash).hexdigest()
def public_key_to_address(public_key_hex, version_byte='00'):
"""
Convert a public key to a Bitcoin address
This demonstrates the complete address generation process
"""
# Step 1: SHA-256
sha256_hash = hashlib.sha256(bytes.fromhex(public_key_hex)).digest()
# Step 2: RIPEMD-160 (HASH160)
ripemd160_hash = hashlib.new('ripemd160', sha256_hash).digest()
# Step 3: Add version byte
versioned = bytes.fromhex(version_byte) + ripemd160_hash
# Step 4: Double SHA-256 for checksum
checksum = hashlib.sha256(hashlib.sha256(versioned).digest()).digest()[:4]
# Step 5: Base58Check encode (simplified)
import base58
return base58.b58encode(versioned + checksum).decode()
if __name__ == '__main__':
# Test vectors
test_cases = [
("", "9c1185a5c5e9fc54612808977ee8f548b2258d31"),
("a", "0bdc9d2d256b3ee9daae347be6f4dc835a467ffe"),
("abc", "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc"),
("message digest", "5d0689ef49d2fae572b881b123a85ffa21595f36"),
]
print("Test Vectors:")
for message, expected in test_cases:
result = ripemd160(message)
print(f" RIPEMD-160('{message}') = {result}")
print(f" Expected: {expected}")
print(f" Match: {result == expected}\n")
# Demonstrate HASH160
print("Bitcoin HASH160 Example:")
test_data = b"Hello Bitcoin"
print(f" Input: {test_data.decode()}")
print(f" SHA-256: {hashlib.sha256(test_data).hexdigest()}")
print(f" HASH160: {hash160(test_data)}")
3.4 Test Vectors for Verification
| Input | RIPEMD-160 Hash |
|---|---|
| (empty string) | 9c1185a5c5e9fc54612808977ee8f548b2258d31 |
| "a" | 0bdc9d2d256b3ee9daae347be6f4dc835a467ffe |
| "abc" | 8eb208f7e05d987a9b044a8e98c6b087f15a0bfc |
| "message digest" | 5d0689ef49d2fae572b881b123a85ffa21595f36 |
| "abcdefghijklmnopqrstuvwxyz" | f71c27109c692c1b56bbdceb5b9d2865b3708dbc |
Run the code above and compare your output with these test vectors. If they match, your implementation is correct!
3.5 Running the Code
- Copy the code into a file named
ripemd160.py - Run with:
python ripemd160.py - Make sure you have the
base58library installed for the address example:pip install base58