The RIPEMD-160 Algorithm
RIPEMD-160 is a 160-bit hash function that runs two independent lines of 80 steps over every block and then merges them. Learn how its padding, rounds, and combine step work, why Bitcoin still uses it, and how it compares with SHA-1.
Pashalis Laoutaris 18 min read
Try it
Interactive RIPEMD-160 Hash Visualizer
🔐 RIPEMD-160 Hash
The RIPEMD-160 Algorithm
Introduction
A hash function turns a message of any length into a short, fixed-size fingerprint. RIPEMD-160 makes a 160-bit fingerprint, which is 20 bytes or 40 hexadecimal digits. Change one bit of the message and about half of the output bits change.
Most hash functions of its generation have one chain of steps, but RIPEMD-160 has two. Each block of the message runs through a left line and a right line of 80 steps each. The lines use the same message words in different orders, with different rotations and different constants. At the end of the block, the results of the two lines are merged. This design was meant to make the attacks that broke MD4 and MD5 much harder. The FAQ explains why two lines help.
Table of Contents
- History and Standards
- Padding
- Functions and Constants
- The 80 Steps
- Merging the Two Lines
- Interactive Visualizer
- A Worked Example
- Python Implementation
- Security Status
- FAQ
- References
History and Standards
The original RIPEMD came from the European RIPE project in 1992. It was based on MD4 and had a 128-bit output. In 1995, Hans Dobbertin found collisions in a version of it with two of its three rounds. In 2004, Xiaoyun Wang and her colleagues found collisions for the full RIPEMD, along with MD4 and MD5.
Dobbertin, Antoon Bosselaers, and Bart Preneel designed RIPEMD-160 as a strengthened replacement. They published it in 1996, in a paper titled “RIPEMD-160, a strengthened version of RIPEMD”. The new function has a longer output, five chaining words instead of four, and more steps. A 128-bit hash can be attacked by a birthday search of about 2^64 steps, and the designers wanted more room than that.
RIPEMD-160 is one of the dedicated hash functions in ISO/IEC 10118-3. It is also a hash algorithm in OpenPGP (RFC 4880). Today it is best known from Bitcoin, where an address starts with the RIPEMD-160 hash of the SHA-256 hash of a public key. The family also has RIPEMD-128, RIPEMD-256, and RIPEMD-320. The last two only widen the output, and they do not add security.
Padding
Like MD4, MD5, and SHA-1, RIPEMD-160 is a Merkle-Damgard hash. It cuts the message into 64-byte blocks, and each block updates a 160-bit chaining value. A message rarely fills whole blocks, so it gets padded first:
- Append one byte
0x80, which is a single one bit followed by zeros. - Append zero bytes until the length is 8 bytes short of a multiple of 64.
- Append the original message length in bits, as an 8-byte little-endian number.
The padded length is always a multiple of 64 bytes. A message of 55 bytes or fewer needs one block. A message of 56 to 119 bytes needs two. Words are little-endian, as in MD4, and the final digest is the five chaining words written as little-endian bytes. SHA-1 and SHA-2 use big-endian order instead.
The chaining value starts from five fixed words:
h0 = 0x67452301 h1 = 0xEFCDAB89 h2 = 0x98BADCFE
h3 = 0x10325476 h4 = 0xC3D2E1F0
The first four are the starting values of MD5, and the fifth is the word that SHA-1 added.
Functions and Constants
Every block is split into 16 message words X[0] to X[15]. The 80 steps are split into five groups of 16. Each group has its own nonlinear function f, its own added constant K, and its own order of message words:
| Steps | Function f(x, y, z), left line | Constant K, left | Constant K, right |
|---|---|---|---|
| 0 to 15 | x xor y xor z |
0x00000000 |
0x50A28BE6 |
| 16 to 31 | (x and y) or (not x and z) |
0x5A827999 |
0x5C4DD124 |
| 32 to 47 | (x or not y) xor z |
0x6ED9EBA1 |
0x6D703EF3 |
| 48 to 63 | (x and z) or (y and not z) |
0x8F1BBCDC |
0x7A6D76E9 |
| 64 to 79 | x xor (y or not z) |
0xA953FD4E |
0x00000000 |
The left-line constants are square roots of 2, 3, 5, and 7, scaled by 2^30. The right-line constants are the cube roots of 2, 3, 5, and 7. The right line uses the five functions in reverse order. Its step j uses f(79 - j), so it starts with the last function and ends with the first.
Two more tables decide which message word each step reads and how far it rotates. The left line reads the words in the order 0 to 15 for the first group. After that, it follows a fixed permutation for each group. The right line has a different permutation for every group. The rotation amounts range from 5 to 15 bits. The Python code below lists all of these tables in full.
The 80 Steps
Each line keeps five words, A, B, C, D, and E. The left line starts from the chaining value, and so does the right line. One left step does this:
T = rol(A + f(j, B, C, D) + X[r(j)] + K(j), s(j)) + E
A = E
E = D
D = rol(C, 10)
C = B
B = T
The symbol rol is a rotation to the left, and all additions are modulo 2^32. The right line does the same, with its own tables r', s', and K', and with f(79 - j) in place of f(j).
Notice the rotation of C by 10 bits. It means the five words do not just move along. One of them is also scrambled at every step, so a difference in one word spreads quickly through the state.
Merging the Two Lines
After 80 steps, the two lines hold two different states. Neither line is added back to the chaining value on its own. Instead, the words are crossed over:
T = h1 + C + D'
h1 = h2 + D + E'
h2 = h3 + E + A'
h3 = h4 + A + B'
h4 = h0 + B + C'
h0 = T
Here A to E come from the left line and A' to E' from the right line. Each new chaining word adds one old chaining word, one word from the left line, and one word from the right line, and they are all from different positions. Because the lines are different, an attacker cannot analyze them one at a time.
After the last block, the five chaining words are the digest.
Interactive Visualizer
The visualizer above runs this exact algorithm. Type any message of up to 119 bytes and click Hash. The log shows the padding, the start of each block, all 80 steps with the left state in A to E and the right state in A' to E', and the merge. When it ends, it tells you how many of the 160 digest bits change when one bit of your message is flipped.
A Worked Example
This follows the message abc, which is the designers’ own test vector.
Padding. The three bytes are 61 62 63. The padding adds 80, then zeros, then the length 24 bits, which is 0x18. The 64-byte block is:
61626380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001800000000000000
As little-endian words, X[0] = 80636261, X[1] to X[13] are zero, and X[14] = 00000018, and X[15] is zero. The chaining value starts as 67452301, efcdab89, 98badcfe, 10325476, and c3d2e1f0.
The first left step. For j = 0 the function is x xor y xor z of the words B, C, and D, which gives 67452301. Adding A, X[0], and K(0) = 0 gives 4eeda863. Rotating left by 11 gives 6d431a77, and adding E gives the new B, 3115fc67. The state after this step is A B C D E = c3d2e1f0 3115fc67 efcdab89 eb73fa62 10325476.
The first right step. The right line starts with the last function, x xor (y or not z), which gives 10325476. It reads message word 5 and rotates by 8. The new B' is ddd63fb8, and the state is A' B' C' D' E' = c3d2e1f0 ddd63fb8 efcdab89 eb73fa62 10325476.
The second step. The left state becomes 10325476 b41192d5 3115fc67 36ae27bf eb73fa62. The right state becomes 10325476 322e7ae3 ddd63fb8 36ae27bf eb73fa62. Note how C takes the old B, and how D takes the old C rotated by 10 bits.
After 80 steps. The left line holds 641129ca d563bfdc 0b2cdc01 6e413468 fc433da8. The right line holds 81d4727d 5fccbade bf627814 fc0e2b04 739c4c7a.
Merging. The new h0 is h1 + C + D', which is efcdab89 + 0b2cdc01 + fc0e2b04. The new h1 is h2 + D + E', which is 98badcfe + 6e413468 + 739c4c7a. The five new words are f708b28e 7a985de0 8e4a049b 87b0c698 fc0b5af1. Written as little-endian bytes, they are the digest:
8eb208f7e05d987a9b044a8e98c6b087f15a0bfc
Avalanche. The digest of abc and the digest of the same message with one bit flipped differ in 85 of the 160 bits. The two sentences The quick brown fox jumps over the lazy dog and ... lazy cog give 37f332f68db77bd9d7edd4969571ad671cf9dd3b and 132072df690933835eb8b6ad0b77e7b6f14acad7, which differ in 76 bits. The empty message gives 9c1185a5c5e9fc54612808977ee8f548b2258d31.
Python Implementation
This is a complete RIPEMD-160. The tables were copied by a script from the designers’ pseudo-code, not typed by hand. The function lines runs both lines and keeps every state, so you can print the steps shown above.
# ripemd160.py
#
# RIPEMD-160, designed by Hans Dobbertin, Antoon Bosselaers and Bart Preneel.
# Like MD4 and MD5 it works on 32-bit little-endian words. Unlike them it runs
# two independent lines of 80 steps over every block and then merges the
# results. The tables below were copied by script from the designers' pseudo-code.
MASK = 0xFFFFFFFF
# the five initial chaining values
INITIAL = [
0x67452301,
0xEFCDAB89,
0x98BADCFE,
0x10325476,
0xC3D2E1F0,
]
# added constants: one for each group of 16 steps, for the left and the right line
K_LEFT = [0x00000000, 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xA953FD4E]
K_RIGHT = [0x50A28BE6, 0x5C4DD124, 0x6D703EF3, 0x7A6D76E9, 0x00000000]
# which message word each step uses
R_LEFT = [
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13,
]
R_RIGHT = [
5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11,
]
# how far each step rotates left
S_LEFT = [
11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6,
]
S_RIGHT = [
8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11,
]
def rol(x, n):
return ((x << n) | (x >> (32 - n))) & MASK
def f(j, x, y, z):
"""The nonlinear function of step j. The five groups use xor, mux, a mix with NOT, mux, and a mix again."""
if j < 16:
return x ^ y ^ z
if j < 32:
return (x & y) | (~x & MASK & z)
if j < 48:
return (x | (~y & MASK)) ^ z
if j < 64:
return (x & z) | (y & ~z & MASK)
return x ^ (y | (~z & MASK))
def pad(message):
"""Append a one bit, zeros, and the 64-bit little-endian bit length, to a multiple of 64 bytes."""
zeros = (55 - len(message)) % 64 # after the 0x80 byte, the length must end 8 bytes short of a multiple of 64
padded = message + b"\x80" + bytes(zeros)
return padded + (8 * len(message) % 2**64).to_bytes(8, "little")
def words(block):
return [int.from_bytes(block[4 * i:4 * i + 4], "little") for i in range(16)]
def lines(chain, x):
"""Run both lines for 80 steps. Returns the state (A, B, C, D, E) after every step of each line."""
a, b, c, d, e = chain
a2, b2, c2, d2, e2 = chain
left, right = [], []
for j in range(80):
t = (rol((a + f(j, b, c, d) + x[R_LEFT[j]] + K_LEFT[j // 16]) & MASK, S_LEFT[j]) + e) & MASK
a, b, c, d, e = e, t, b, rol(c, 10), d
left.append((a, b, c, d, e))
t = (rol((a2 + f(79 - j, b2, c2, d2) + x[R_RIGHT[j]] + K_RIGHT[j // 16]) & MASK, S_RIGHT[j]) + e2) & MASK
a2, b2, c2, d2, e2 = e2, t, b2, rol(c2, 10), d2
right.append((a2, b2, c2, d2, e2))
return left, right
def compress(chain, block):
"""Process one 64-byte block and return the new chaining value."""
left, right = lines(chain, words(block))
a, b, c, d, e = left[-1]
a2, b2, c2, d2, e2 = right[-1]
h0, h1, h2, h3, h4 = chain
return [
(h1 + c + d2) & MASK,
(h2 + d + e2) & MASK,
(h3 + e + a2) & MASK,
(h4 + a + b2) & MASK,
(h0 + b + c2) & MASK,
]
def ripemd160(message):
chain = list(INITIAL)
padded = pad(message)
for i in range(0, len(padded), 64):
chain = compress(chain, padded[i:i + 64])
return b"".join(h.to_bytes(4, "little") for h in chain)
if __name__ == "__main__":
for text in (b"", b"abc", b"message digest", b"The quick brown fox jumps over the lazy dog"):
print("RIPEMD-160(%r) = %s" % (text.decode(), ripemd160(text).hex()))
Running it produces this output:
RIPEMD-160('') = 9c1185a5c5e9fc54612808977ee8f548b2258d31
RIPEMD-160('abc') = 8eb208f7e05d987a9b044a8e98c6b087f15a0bfc
RIPEMD-160('message digest') = 5d0689ef49d2fae572b881b123a85ffa21595f36
RIPEMD-160('The quick brown fox jumps over the lazy dog') = 37f332f68db77bd9d7edd4969571ad671cf9dd3b
I checked this code against several independent sources before writing it up. The word order and rotation amounts of all 160 steps match the designers’ reference C code, which I only read and did not run. It reproduces the nine test vectors on the designers’ page, including one million repetitions of the letter a. It also agrees with the OpenSSL that ships with Python on 506 inputs, including every length from 0 to 199 bytes and many around the block boundaries.
Security Status
RIPEMD-160 has no known practical attack. A birthday search finds a collision in about 2^80 hashes, because the output has 160 bits. That is the same level as SHA-1 had on paper before its collisions appeared, and it is below the 128-bit target of modern designs. Finding a message for a given digest should take about 2^160 hashes.
The best published attacks reach only part of the 80 steps. There are two kinds. In a collision attack, the attacker starts from the normal initial values and finds two messages with the same reduced-step hash. This reached 34 steps at CRYPTO 2019, and 36 steps at EUROCRYPT 2023 with a cost of about 2^64.5. Then Li, Liu, and Wang reported a practical collision for 40 steps. They found a colliding pair in 16 hours on 115 threads. A 2026 preprint on the IACR ePrint archive claims 42 steps, at a theoretical cost of about 2^47.4. It has not been peer reviewed as far as I know.
In a semi-free-start attack, the attacker may also choose the starting chaining value, which is easier. These attacks reached 36 and 37 steps in 2019. They reached 41, 42, and 43 steps in 2024, and one 2025 paper reports 44 steps and practical pairs for 41 and 42 steps.
None of these threatens the full function. Even the best results cover about half of the steps, and no attack on all 80 steps is known. The two-line design has held up well. The progress is still steady, so the safety margin is smaller than it was.
Two limits remain, and the first is that, like every Merkle-Damgard hash, it allows length extension. Given the digest of an unknown message, anyone can compute the digest of that message followed by padding and more data. Use HMAC when you need a keyed hash. The second limit is that 160 bits is simply small. New systems usually choose SHA-256, SHA-3, or BLAKE2. RIPEMD-160 stays in use mostly where older formats require it.
FAQ
Why does RIPEMD-160 have two lines?
Two parallel lines force an attacker to deal with two different computations at once. A message difference that cancels in the left line is unlikely to cancel in the right line as well. The designers built the idea in after the attacks on MD4 and the original RIPEMD.
Is RIPEMD-160 secure?
No practical attack is known against the full function. Its 160-bit output gives about 80 bits of collision resistance, which is lower than modern standards require. It is acceptable for existing uses, such as Bitcoin addresses, but it is not a good choice for a new design.
Why does Bitcoin use it?
An address is derived by hashing a public key with SHA-256 and then with RIPEMD-160. That makes the address shorter, at 20 bytes, and it uses two different hash designs together. The same two-step hash, for the text abc instead of a key, gives bb1be98c142444d7a56aa3981c3942a978e4dc33.
How is it different from SHA-1?
Both give 160 bits and both build on the MD4 family. SHA-1 has one chain of 80 steps and uses big-endian words. RIPEMD-160 has two chains of 80 steps and uses little-endian words. SHA-1 has practical collisions today, and RIPEMD-160 does not.
What are RIPEMD-128, RIPEMD-256, and RIPEMD-320?
RIPEMD-128 is a 128-bit replacement for the original RIPEMD. RIPEMD-256 and RIPEMD-320 are extensions of the 128-bit and 160-bit versions. They have a wider output, but the designers state that they do not offer more security.
References
-
Dobbertin, H., Bosselaers, A., and Preneel, B. “RIPEMD-160: A Strengthened Version of RIPEMD.” Fast Software Encryption (FSE) 1996, Lecture Notes in Computer Science 1039, Springer. Available at: https://homes.esat.kuleuven.be/~bosselae/ripemd160.html
-
Bosselaers, A. “Pseudo-code for RIPEMD-160.” Available at: https://homes.esat.kuleuven.be/~bosselae/ripemd/rmd160.txt
-
Wang, X., Lai, X., Feng, D., Chen, H., and Yu, X. “Cryptanalysis of the Hash Functions MD4 and RIPEMD.” EUROCRYPT 2005, Lecture Notes in Computer Science 3494, Springer.
-
ISO/IEC 10118-3. “Information technology, Security techniques, Hash-functions, Part 3: Dedicated hash-functions.”
-
Callas, J., Donnerhacke, L., Finney, H., Shaw, D., and Thayer, R. “OpenPGP Message Format.” RFC 4880, 2007. Available at: https://www.rfc-editor.org/rfc/rfc4880
-
Liu, F., Wang, G., Sarkar, S., Anand, R., Meier, W., Li, Y., and Isobe, T. “Analysis of RIPEMD-160: New Collision Attacks and Finding Characteristics with MILP.” EUROCRYPT 2023. Available at: https://eprint.iacr.org/2023/277
-
Li, Y., Liu, F., and Wang, G. “New Records in Collision Attacks on RIPEMD-160 and SHA-256.” Cryptology ePrint Archive, Paper 2023/285. Available at: https://eprint.iacr.org/2023/285
-
Li, Y., Liu, F., and Wang, G. “Automating Collision Attacks on RIPEMD-160.” IACR Transactions on Symmetric Cryptology, 2023. Available at: https://eprint.iacr.org/2024/350
-
Zhang, Z., Li, M., Wang, H., Hou, S., Wang, W., and Wang, M. “Improved Semi-Free-Start Collision Attacks on RIPEMD-160.” ASIACRYPT 2025. Available at: https://eprint.iacr.org/2025/1531
-
Liu, F., Dobraunig, C., Mendel, F., Isobe, T., Wang, G., and Cao, Z. “New Semi-Free-Start Collision Attack Framework for Reduced RIPEMD-160.” FSE 2020. Available at: https://eprint.iacr.org/2019/668
-
Lu, Z., Yu, H., Li, Y., Zhang, X., and Lin, X. “Improved Collision Attack on RIPEMD-160.” Cryptology ePrint Archive, Paper 2026/1744, preprint. Available at: https://eprint.iacr.org/2026/1744