# RIPEMD-160 Compression

{% embed url="<https://youtu.be/ItO5YLrbUGw>" %}

#### Step 1: Initialization of Working Variables

RIPEMD-160 starts by initializing **two parallel computation paths**.

* Each path uses **five working variables** (a–e on one side, aa–ee on the other).
* Both paths begin with the **same initial values**, defined by Dobbertin et al.

Example setup in Go:

```
var InitialValues = []uint32{
    0x67452301, 0xefcdab89, 0x98badcfe,
    0x10325476, 0xc3d2e1f0,
}
```

&#x20;

👉 **Note:** If there is more than one message block (512 bits), only the **first round** starts with the initial values. Later rounds reuse the **chaining values** from the previous round.

***

#### Step 2: Mutation and Compression

This is where the “fun” begins — the **heart of RIPEMD-160**.

* The compression function runs for **80 steps**, divided into **5 rounds of 16 steps each**.
* Each round computes a **temporary word** on both sides of the algorithm (left and right).
* The words are calculated using:
  * **Logical functions** (XOR, AND, OR, NOT).
  * **Bit rotations** (left shifts by specific values).
  * **Constants** defined by the algorithm.

After computing the temporary word, the **working variables are rotated and mutated**.

Example (first round):

```
for i := 0; i < 16; i++ {
    tempWord = a + (b ^ c ^ d) + messageSchedule[word[i]] + 0x00000000
    tempWord = bits.RotateLeft32(tempWord, rotationLeft[i]) + e
    a, e, d, c, b = e, d, bits.RotateLeft32(c, 10), b, tempWord

    tempWordPrime = aa + (bb ^ (cc | ^dd)) + messageSchedule[wordPrime[i]] + 0x50a28be6
    tempWordPrime = bits.RotateLeft32(tempWordPrime, rotationLeftPrime[i]) + ee
    aa, ee, dd, cc, bb = ee, dd, bits.RotateLeft32(cc, 10), bb, tempWordPrime
}
```

&#x20;

👉 Each of the 5 rounds changes the **logical functions** and **constants** used, giving the algorithm strength against collisions and preimage attacks.

***

#### Step 3: Computing Chaining Variables

After completing all 80 steps, the two computation paths are **recombined**.

The chaining values are updated by **adding results from both sides** back into the hash state:

```
tempValue := h1 + c + dd
h1 = h2 + d + ee
h2 = h3 + e + aa
h3 = h4 + a + bb
h4 = h0 + b + cc
h0 = tempValue

chainingValues[0] = h0
chainingValues[1] = h1
chainingValues[2] = h2
chainingValues[3] = h3
chainingValues[4] = h4
```

&#x20;

👉 If this is the **last message block**, the chaining values represent the **final 160-bit digest**. Otherwise, they are carried forward to the next compression round.

***

✅ **Summary:**

* RIPEMD-160 compression uses **two parallel paths** of 80 steps.
* Each step combines **logical functions, rotations, and constants** to scramble input data.
* At the end of each block, **chaining variables** are updated, eventually producing the **final RIPEMD-160 hash value**.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://hub.bsvblockchain.org/higher-learning/bsv-academy/bitcoin-primitives-hash-functions/walkthrough-implementation-of-ripemd-160-in-golang-overview/ripemd-160-compression.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
