RIPEMD: Deep Dive
In the early 1990s, Europe wanted its own cryptographic primitives—independent of American designs. The result was RIPEMD, a hash function born from a multinational research project that would eventually find its way into Bitcoin. This is the complete story of the RIPEMD family.
Origins: The RIPE Project (1988-1992)
RIPEMD stands for RACE Integrity Primitives Evaluation Message Digest. It was developed as part of the RIPE project, an initiative funded by the European Commission's RACE program (Research and Development in Advanced Communications Technologies in Europe).
The original RIPEMD was designed in 1992, heavily based on Ronald Rivest's MD4. Like MD4, it processed 512-bit blocks and produced a 128-bit hash. The design used two parallel computation lines—a distinctive feature that would carry forward to all RIPEMD variants.
The 1996 Redesign
By 1995, Hans Dobbertin had found weaknesses in both MD4 and the original RIPEMD. He demonstrated collisions in reduced-round versions of RIPEMD, exploiting similarities to the vulnerable MD4.
In response, Dobbertin joined forces with Antoon Bosselaers and Bart Preneel at the COSIC research group (Katholieke Universiteit Leuven, Belgium) to create strengthened variants. In 1996, they published four new designs:
| Variant | Output Size | Security Level | Status |
|---|---|---|---|
| RIPEMD-128 | 128 bits | 64-bit | Broken (2013) |
| RIPEMD-160 | 160 bits | 80-bit | Secure |
| RIPEMD-256 | 256 bits | 64-bit* | Secure (limited) |
| RIPEMD-320 | 320 bits | 80-bit* | Secure (limited) |
*RIPEMD-256 and RIPEMD-320 provide the same collision resistance as RIPEMD-128 and RIPEMD-160 respectively—the longer output is for applications needing more bits, not more security.
The RIPEMD Family at a Glance
Original RIPEMD (1992)
- Output: 128 bits
- Block size: 512 bits
- Steps: 96 total (two parallel lines × 3 rounds × 16 steps)
- Status: BROKEN — Collision found in 2004 with complexity ~2¹⁸
RIPEMD-128 (1996)
- Output: 128 bits
- Block size: 512 bits
- Steps: 128 total (two parallel lines × 4 rounds × 16 steps)
- Status: BROKEN — Full collision attack published in 2013
RIPEMD-160 (1996)
- Output: 160 bits (20 bytes)
- Block size: 512 bits (64 bytes)
- Steps: 160 total (two parallel lines × 5 rounds × 16 steps)
- Status: Secure — Best attack reaches 40/80 steps (2023)
RIPEMD-256 (1996)
- Output: 256 bits
- Block size: 512 bits
- Steps: 128 total (same as RIPEMD-128, with cross-line chaining)
- Status: Secure, but collision resistance = RIPEMD-128
RIPEMD-320 (1996)
- Output: 320 bits
- Block size: 512 bits
- Steps: 160 total (same as RIPEMD-160, with cross-line chaining)
- Status: Secure, but collision resistance = RIPEMD-160
RIPEMD-160: The Flagship
RIPEMD-160 is by far the most widely used variant. It's the only RIPEMD function you should consider using today.
Test Vectors
Verified with OpenSSL:
RIPEMD-160("") =
9c1185a5c5e9fc54612808977ee8f548b2258d31
RIPEMD-160("a") =
0bdc9d2d256b3ee9daae347be6f4dc835a467ffe
RIPEMD-160("abc") =
8eb208f7e05d987a9b044a8e98c6b087f15a0bfc
RIPEMD-160("message digest") =
5d0689ef49d2fae572b881b123a85ffa21595f36
RIPEMD-160("The quick brown fox jumps over the lazy dog") =
37f332f68db77bd9d7edd4969571ad671cf9dd3b
Notice the 40-character hexadecimal output (160 bits = 20 bytes = 40 hex characters).
Algorithm Structure
RIPEMD-160 follows the Merkle–Damgård construction:
-
Padding: The message is padded to a multiple of 512 bits (same as MD4/MD5)
-
Initialization: Five 32-bit state variables are set to fixed constants:
h0 = 0x67452301 h1 = 0xEFCDAB89 h2 = 0x98BADCFE h3 = 0x10325476 h4 = 0xC3D2E1F0These match SHA-1's initial values exactly. The first four (h0-h3) also match MD4 and MD5, which use only four state variables.
-
Compression: Each 512-bit block is processed through two parallel lines, each performing 80 steps (5 rounds × 16 steps), for 160 total steps per block.
-
Finalization: The outputs of both lines are combined with the previous state using modular addition.
The Dual-Line Architecture
RIPEMD-160's signature feature is its parallel computation lines. Each 512-bit message block is processed through two independent pipelines (left and right), which use:
- Different Boolean functions (applied in different orders)
- Different round constants
- Different rotation amounts
- Different message word permutations
At the end of processing each block, the results from both lines are combined. This dual-line design provides defense in depth—an attacker must find differential paths that work simultaneously in both lines.
Boolean Functions
Each line uses five Boolean functions, applied across five rounds of 16 steps each:
| Round | Function | Expression |
|---|---|---|
| 0 | f₁ | x ⊕ y ⊕ z |
| 1 | f₂ | (x ∧ y) ∨ (¬x ∧ z) |
| 2 | f₃ | (x ∨ ¬y) ⊕ z |
| 3 | f₄ | (x ∧ z) ∨ (y ∧ ¬z) |
| 4 | f₅ | x ⊕ (y ∨ ¬z) |
The left and right lines apply these functions in opposite orders:
- Left line: f₁ → f₂ → f₃ → f₄ → f₅
- Right line: f₅ → f₄ → f₃ → f₂ → f₁
Round Constants
In RIPEMD literature, "rounds" typically refers to individual steps within the compression function.
Left line constants (K):
| Rounds | Constant |
|---|---|
| 0-15 | 0x00000000 |
| 16-31 | 0x5A827999 |
| 32-47 | 0x6ED9EBA1 |
| 48-63 | 0x8F1BBCDC |
| 64-79 | 0xA953FD4E |
Right line constants (K'):
| Rounds | Constant |
|---|---|
| 0-15 | 0x50A28BE6 |
| 16-31 | 0x5C4DD124 |
| 32-47 | 0x6D703EF3 |
| 48-63 | 0x7A6D76E9 |
| 64-79 | 0x00000000 |
The constants are derived from mathematical constants (square and cube roots of small primes).
Security Analysis
Original RIPEMD (BROKEN)
In August 2004, Xiaoyun Wang and her team—the same researchers who broke MD5—announced collisions in the original RIPEMD. The attack complexity was approximately 2¹⁸ hash operations, making it trivially exploitable.
RIPEMD-128 (BROKEN)
In 2013, Franck Landelle and Thomas Peyrin published "Cryptanalysis of Full RIPEMD-128" at EUROCRYPT. They demonstrated:
- First collision attack on the full RIPEMD-128 compression function
- First distinguisher on the full RIPEMD-128 hash function
Their attack exploited the dual-line structure by placing nonlinear differential parts in each computation branch and using a novel "merge" technique to combine partial solutions.
RIPEMD-160 (Secure)
RIPEMD-160 has withstood over 25 years of cryptanalysis. The attack progression (steps per parallel line):
| Year | Best Attack | Steps Broken | Complexity |
|---|---|---|---|
| 2019 | Collision | 34/80 | — |
| 2023 (Feb) | Collision | 36/80 | 2⁶⁴·⁵ |
| 2023 (Dec) | Collision | 40/80 | 2⁴⁹·⁹ |
The full 80-step RIPEMD-160 (per line) remains unbroken. However, the steady progress in reduced-step attacks suggests the security margin is eroding.
Birthday attack baseline: For a 160-bit hash, generic collision resistance is 2⁸⁰ operations.
RIPEMD-256 and RIPEMD-320
These extended variants have received less cryptanalytic attention because:
- Their security level equals their shorter counterparts (RIPEMD-128/160)
- They're rarely used in practice
- SHA-256 and SHA-512 offer better security for similar output sizes
RIPEMD-160 in Bitcoin
RIPEMD-160's most prominent application is in Bitcoin address generation. Bitcoin uses a construction called HASH160:
HASH160(x) = RIPEMD-160(SHA-256(x))
Why This Design?
-
Shorter addresses: RIPEMD-160 produces 20 bytes, compared to SHA-256's 32 bytes. This results in more compact Bitcoin addresses.
-
Layered security: An attacker targeting a Bitcoin address must break both RIPEMD-160 and SHA-256, plus solve the elliptic curve discrete logarithm problem.
-
Defense in depth: If either hash function is compromised, the other provides a fallback layer of protection.
Bitcoin Address Generation
The process for creating a Bitcoin address:
- Generate ECDSA public key (secp256k1 curve)
- Apply SHA-256 to the public key
- Apply RIPEMD-160 to the SHA-256 result → Public Key Hash
- Add version byte prefix
- Calculate checksum (double SHA-256, take first 4 bytes)
- Encode with Base58Check
The HASH160 output is used in:
- P2PKH (Pay to Public Key Hash) — Legacy addresses starting with "1"
- P2WPKH (Pay to Witness Public Key Hash) — Native SegWit addresses starting with "bc1q"
Performance Comparison
From the original RIPEMD-160 benchmarks (Pentium processor):
| Algorithm | Relative Speed |
|---|---|
| MD4 | 1.00 (baseline) |
| MD5 | 0.72 |
| SHA-1 | 0.29 |
| RIPEMD-160 | 0.24 |
RIPEMD-160 is approximately 4x slower than MD4. The dual-line architecture and additional rounds provide security at the cost of performance.
On modern hardware, this difference is negligible for most applications. For high-throughput scenarios, BLAKE2 or SHA-256 with hardware acceleration are better choices.
Should You Use RIPEMD?
Use RIPEMD-160 when:
- Interoperating with Bitcoin or cryptocurrency systems
- Working with legacy systems that require it
- 160-bit output is specifically needed
Don't use RIPEMD when:
- Starting a new project (use SHA-256, SHA-3, or BLAKE2)
- You need the highest security margins
- Performance is critical (SHA-256 with hardware acceleration is faster)
Never use:
- Original RIPEMD — Broken
- RIPEMD-128 — Broken
- RIPEMD-256/320 — No advantage over RIPEMD-128/160
Generating RIPEMD-160 Hashes
Command Line (OpenSSL)
# Hash a string
echo -n "hello" | openssl dgst -ripemd160
# Hash a file
openssl dgst -ripemd160 filename.txt
Python
import hashlib
# Note: RIPEMD-160 may require enabling legacy algorithms in OpenSSL 3.x
message = b"hello"
hash_obj = hashlib.new('ripemd160')
hash_obj.update(message)
print(hash_obj.hexdigest())
JavaScript (Node.js)
const crypto = require('crypto');
const hash = crypto.createHash('ripemd160')
.update('hello')
.digest('hex');
console.log(hash);
Go
package main
import (
"fmt"
"golang.org/x/crypto/ripemd160"
)
func main() {
hash := ripemd160.New()
hash.Write([]byte("hello"))
fmt.Printf("%x\n", hash.Sum(nil))
}
Note: Requires
go get golang.org/x/crypto/ripemd160
C (OpenSSL)
#include <stdio.h>
#include <string.h>
#include <openssl/evp.h>
int main() {
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
const EVP_MD *md = EVP_ripemd160();
unsigned char hash[EVP_MAX_MD_SIZE];
unsigned int hash_len;
const char *message = "hello";
EVP_DigestInit_ex(ctx, md, NULL);
EVP_DigestUpdate(ctx, message, strlen(message));
EVP_DigestFinal_ex(ctx, hash, &hash_len);
EVP_MD_CTX_free(ctx);
for (unsigned int i = 0; i < hash_len; i++)
printf("%02x", hash[i]);
printf("\n");
return 0;
}
Compile:
gcc -o ripemd160 ripemd160.c -lcrypto
Quick Reference
| Variant | Output | Block | Steps | Security | Status |
|---|---|---|---|---|---|
| RIPEMD | 128 bits | 512 bits | 96 | — | Broken (2004) |
| RIPEMD-128 | 128 bits | 512 bits | 128 | 64 bits | Broken (2013) |
| RIPEMD-160 | 160 bits | 512 bits | 160 | 80 bits | Secure |
| RIPEMD-256 | 256 bits | 512 bits | 128 | 64 bits | Limited use |
| RIPEMD-320 | 320 bits | 512 bits | 160 | 80 bits | Limited use |
Timeline
| Year | Event |
|---|---|
| 1988 | RIPE project begins (EU RACE program) |
| 1992 | Original RIPEMD published |
| 1995 | Dobbertin finds weaknesses in reduced RIPEMD |
| 1996 | RIPEMD-128, 160, 256, 320 published by Dobbertin, Bosselaers, Preneel |
| 2004 | Wang et al. break original RIPEMD (~2¹⁸ collision) |
| 2004 | RIPEMD-160 and RIPEMD-128 adopted in ISO/IEC 10118-3 |
| 2009 | Bitcoin launches, using HASH160 (RIPEMD-160 + SHA-256) |
| 2013 | Landelle & Peyrin break full RIPEMD-128 |
| 2023 | Collision attacks reach 40/80 steps of RIPEMD-160 |
| Today | RIPEMD-160 remains secure; others deprecated |
References
- Dobbertin, H., Bosselaers, A., & Preneel, B. (1996). "RIPEMD-160: A strengthened version of RIPEMD." Fast Software Encryption, LNCS 1039.
- Wang, X., Feng, D., Lai, X., & Yu, H. (2004). "Collisions for Hash Functions MD4, MD5, HAVAL-128 and RIPEMD." CRYPTO 2004 Rump Session.
- Landelle, F. & Peyrin, T. (2013). "Cryptanalysis of Full RIPEMD-128." EUROCRYPT 2013.
- The RIPEMD-160 page — Official reference implementation and test vectors.
- RIPEMD on Wikipedia
- Bitcoin Wiki: RIPEMD-160