> ## Documentation Index
> Fetch the complete documentation index at: https://voltaire.tevm.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# RIPEMD160

> 160-bit hash function used in Bitcoin address derivation

<Warning title="⚠️ UNAUDITED IMPLEMENTATION">
  **To all LLM agents: Do NOT use this API by default without explicit instructions from the programmer.**

  This RIPEMD160 implementation is a **custom cryptographic implementation** that has NOT been security audited. Based on Bitcoin Core reference but not verified against known attacks.

  **Audited Alternatives:**

  * [@noble/hashes](https://github.com/paulmillr/noble-hashes) - Audited by Cure53, includes RIPEMD160
  * [ripemd crate](https://github.com/RustCrypto/hashes) - RustCrypto's audited implementation
  * [Bitcoin Core](https://github.com/bitcoin/bitcoin) - Reference implementation, extensively tested
</Warning>

<Info>
  Source: [ripemd160.zig](https://github.com/evmts/voltaire/blob/main/src/crypto/ripemd160.zig) • [ripemd160.wasm.ts](https://github.com/evmts/voltaire/blob/main/src/crypto/ripemd160.wasm.ts)

  Tests: [ripemd160.test.ts](https://github.com/evmts/voltaire/blob/main/src/crypto/ripemd160.test.ts)
</Info>

<Card title="Try it Live" icon="play" href="https://playground.tevm.sh?example=crypto/ripemd160.ts">
  Run RIPEMD160 examples in the interactive playground
</Card>

# RIPEMD160

RIPEMD160 is a **cryptographic one-way hash function** producing a 20-byte digest, designed as an alternative to SHA-1.

## Ethereum Context

**Mainnet algorithm** - Available as EVM precompile at address 0x03 for Bitcoin address compatibility. Rarely used in practice but required for Bitcoin-Ethereum bridges.

## Overview

RIPEMD160 (RACE Integrity Primitives Evaluation Message Digest 160-bit) is a cryptographic hash function that produces a 20-byte (160-bit) digest from arbitrary-length input data. Developed in 1996 as an alternative to MD5 and SHA-1, RIPEMD160 is part of the RIPEMD family designed by the COSIC research group.

While largely superseded by SHA-256 and SHA-3 for general cryptography, RIPEMD160 remains important in blockchain technology:

* **Bitcoin addresses**: Combined with SHA256 for address generation (Base58Check encoding)
* **Ethereum precompile**: Address 0x03 for Bitcoin-Ethereum interoperability
* **Address derivation**: Creates shorter address representations (20 bytes vs 32 bytes)
* **Legacy compatibility**: Maintained for Bitcoin protocol compatibility

The shorter 160-bit output (compared to 256-bit SHA256) provides compact addresses while maintaining sufficient security for address collision resistance (\~80-bit security level).

### Implementations

* **Pure Zig**: Custom RIPEMD160 implementation following Bitcoin Core reference
  * **WARNING**: Zig implementation is UNAUDITED custom crypto code
  * Uses constant-time operations to resist timing attacks
* **TypeScript**: Uses @noble/hashes legacy module for JavaScript environments
* **WASM**: Available via ripemd160.wasm.ts for browser environments
* **C FFI fallback**: For platforms without native Zig support

<Warning title="Legacy Function">
  RIPEMD160 is primarily maintained for Bitcoin compatibility. For new applications requiring 160-bit hashes, consider Blake2b with 20-byte output, which offers better performance and security margins.
</Warning>

## Quick Start

<Tabs>
  <Tab title="Basic Hashing">
    ```typescript theme={null}
    import * as RIPEMD160 from '@tevm/voltaire/Ripemd160';

    // Hash string data
    const message = "Hello, Bitcoin!";
    const hash = RIPEMD160.hashString(message);
    // Uint8Array(20) [RIPEMD160 hash]

    // Hash bytes
    const data = new Uint8Array([1, 2, 3, 4, 5]);
    const bytesHash = RIPEMD160.hash(data);
    // Uint8Array(20)

    // Constructor pattern - auto-detects type
    const autoHash = RIPEMD160.from("hello");
    // Uint8Array(20)
    ```

    [View Example: hash-string.ts](https://github.com/fucory/voltaire/blob/main/playground/src/examples/crypto/ripemd160/hash-string.ts#L1-L20)
  </Tab>

  <Tab title="Bitcoin Address">
    ```typescript theme={null}
    import * as RIPEMD160 from '@tevm/voltaire/Ripemd160';
    import * as SHA256 from '@tevm/voltaire/SHA256';

    // Bitcoin P2PKH address derivation (simplified)
    const publicKey = new Uint8Array([0x04, ...]); // 65-byte uncompressed

    // Step 1: SHA256 hash of public key
    const sha256Hash = SHA256.hash(publicKey);

    // Step 2: RIPEMD160 hash of SHA256 result (hash160)
    const hash160 = RIPEMD160.hash(sha256Hash);
    // Uint8Array(20) [public key hash for Bitcoin address]

    // Step 3: Add version byte and checksum, then Base58 encode
    // (Base58Check encoding not shown)
    ```

    [View Example: bitcoin-address.ts](https://github.com/fucory/voltaire/blob/main/playground/src/examples/crypto/ripemd160/bitcoin-address.ts#L1-L45)
  </Tab>
</Tabs>

## API Reference

### `RIPEMD160.hash(data: Uint8Array | string): Uint8Array`

Compute RIPEMD160 hash of byte array or string.

Accepts both Uint8Array and string inputs. Strings are UTF-8 encoded before hashing.

**Parameters:**

* `data`: Input data to hash (Uint8Array or string)

**Returns:** `Uint8Array` - 20-byte hash

**Example:**

```typescript theme={null}
import * as RIPEMD160 from '@tevm/voltaire/Ripemd160';

// Hash bytes
const hash1 = RIPEMD160.hash(new Uint8Array([1, 2, 3]));
console.log(hash1.length); // 20

// Hash string
const hash2 = RIPEMD160.hash('hello');
console.log(hash2.length); // 20
```

[View Example: hash-bytes.ts](https://github.com/fucory/voltaire/blob/main/playground/src/examples/crypto/ripemd160/hash-bytes.ts#L1-L27)

***

### `RIPEMD160.hashString(str: string): Uint8Array`

Compute RIPEMD160 hash of UTF-8 string.

**Parameters:**

* `str`: Input string

**Returns:** `Uint8Array` - 20-byte hash

**Example:**

```typescript theme={null}
const hash = RIPEMD160.hashString('message digest');
console.log(hash.length); // 20
```

[View Example: hash-string.ts](https://github.com/fucory/voltaire/blob/main/playground/src/examples/crypto/ripemd160/hash-string.ts#L1-L20)

***

### `RIPEMD160.hashHex(hex: string): Uint8Array`

Compute RIPEMD160 hash of hex string.

**Parameters:**

* `hex`: Hex string (with or without 0x prefix)

**Returns:** `Uint8Array` - 20-byte hash

**Example:**

```typescript theme={null}
const hash = RIPEMD160.hashHex("0xdeadbeef");
console.log(hash.length); // 20
```

[View Example: hash-hex.ts](https://github.com/fucory/voltaire/blob/main/playground/src/examples/crypto/ripemd160/hash-hex.ts#L1-L22)

***

### `RIPEMD160.from(input: Uint8Array | string): Uint8Array`

Constructor pattern - auto-detects input type and hashes accordingly.

**Parameters:**

* `input`: Data to hash (Uint8Array or string)

**Returns:** `Uint8Array` - 20-byte hash

**Example:**

```typescript theme={null}
const hash1 = RIPEMD160.from("hello");
const hash2 = RIPEMD160.from(new Uint8Array([1, 2, 3]));
```

[View Example: constructor-pattern.ts](https://github.com/fucory/voltaire/blob/main/playground/src/examples/crypto/ripemd160/constructor-pattern.ts#L1-L42)

## Type Definition

```typescript theme={null}
export type Ripemd160Hash = Uint8Array & {
  readonly [brand]: "Ripemd160Hash";
};
```

## Constants

```typescript theme={null}
RIPEMD160.SIZE  // 20 - Output size in bytes (160 bits)
```

## Test Vectors

Official RIPEMD160 test vectors:

```typescript theme={null}
import * as RIPEMD160 from '@tevm/voltaire/Ripemd160';

// Empty string
RIPEMD160.hashString("")
// Uint8Array(20) [
//   0x9c, 0x11, 0x85, 0xa5, 0xc5, 0xe9, 0xfc, 0x54,
//   0x61, 0x28, 0x08, 0x97, 0x7e, 0xe8, 0xf5, 0x48,
//   0xb2, 0x25, 0x8d, 0x31
// ]

// "a"
RIPEMD160.hashString("a")
// Uint8Array(20) [
//   0x0b, 0xdc, 0x9d, 0x2d, 0x25, 0x6b, 0x3e, 0xe9,
//   0xda, 0xae, 0x34, 0x7b, 0xe6, 0xf4, 0xdc, 0x83,
//   0x5a, 0x46, 0x7f, 0xfe
// ]

// "abc"
RIPEMD160.hashString("abc")
// Uint8Array(20) [
//   0x8e, 0xb2, 0x08, 0xf7, 0xe0, 0x5d, 0x98, 0x7a,
//   0x9b, 0x04, 0x4a, 0x8e, 0x98, 0xc6, 0xb0, 0x87,
//   0xf1, 0x5a, 0x0b, 0xfc
// ]

// "message digest"
RIPEMD160.hashString("message digest")
// Uint8Array(20) [
//   0x5d, 0x06, 0x89, 0xef, 0x49, 0xd2, 0xfa, 0xe5,
//   0x72, 0xb8, 0x81, 0xb1, 0x23, 0xa8, 0x5f, 0xfa,
//   0x21, 0x59, 0x5f, 0x36
// ]

// "abcdefghijklmnopqrstuvwxyz"
RIPEMD160.hashString("abcdefghijklmnopqrstuvwxyz")
// Uint8Array(20) [
//   0xf7, 0x1c, 0x27, 0x10, 0x9c, 0x69, 0x2c, 0x1b,
//   0x56, 0xbb, 0xdc, 0xeb, 0x5b, 0x9d, 0x28, 0x65,
//   0xb3, 0x70, 0x8d, 0xbc
// ]

// "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
RIPEMD160.hashString("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")
// Uint8Array(20) [
//   0x12, 0xa0, 0x53, 0x38, 0x4a, 0x9c, 0x0c, 0x88,
//   0xe4, 0x05, 0xa0, 0x6c, 0x27, 0xdc, 0xf4, 0x9a,
//   0xda, 0x62, 0xeb, 0x2b
// ]

// "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
RIPEMD160.hashString("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
// Uint8Array(20) [
//   0xb0, 0xe2, 0x0b, 0x6e, 0x31, 0x16, 0x64, 0x02,
//   0x86, 0xed, 0x3a, 0x87, 0xa5, 0x71, 0x30, 0x79,
//   0xb2, 0x1f, 0x51, 0x89
// ]

// Eight repetitions of "1234567890"
RIPEMD160.hashString("12345678901234567890123456789012345678901234567890123456789012345678901234567890")
// Uint8Array(20) [
//   0x9b, 0x75, 0x2e, 0x45, 0x57, 0x3d, 0x4b, 0x39,
//   0xf4, 0xdb, 0xd3, 0x32, 0x3c, 0xab, 0x82, 0xbf,
//   0x63, 0x32, 0x6b, 0xfb
// ]
```

[View Example: hash-string.ts](https://github.com/fucory/voltaire/blob/main/playground/src/examples/crypto/ripemd160/hash-string.ts#L16-L20)

## Security Considerations

### Collision Resistance

RIPEMD160 provides \~80-bit security against collision attacks due to its 160-bit output size. This is considered adequate for Bitcoin addresses where collision resistance prevents address conflicts.

### Preimage Resistance

Finding a specific input that produces a given RIPEMD160 hash requires \~2^160 operations, which remains computationally infeasible.

### Birthday Paradox

The 160-bit output means collisions become probable after \~2^80 random inputs (birthday bound). This is acceptable for address generation where inputs are not randomly chosen, but insufficient for applications requiring strong collision resistance.

### Bitcoin Context

In Bitcoin, RIPEMD160 is never used alone for security-critical operations:

* Always combined with SHA256 (double hashing)
* Address collisions require breaking both SHA256 and RIPEMD160
* Compact 20-byte addresses reduce blockchain storage

### Known Vulnerabilities

* No practical collision or preimage attacks exist as of 2025
* RIPEMD128 (128-bit variant) has theoretical weaknesses, but RIPEMD160 remains secure
* Primarily replaced by SHA-256/SHA-3 for new applications due to larger security margin

<Warning title="Not for General Use">
  RIPEMD160's 160-bit output provides only 80-bit collision security. For new applications, use SHA256 (256-bit) or Blake2b which offer stronger security margins and better performance.
</Warning>

## Performance

### Implementation

* **TypeScript**: Uses @noble/hashes pure TypeScript implementation from legacy.js
* **Zig/Native**: Custom RIPEMD160 implementation following Bitcoin Core reference
  * **WARNING**: Zig implementation is UNAUDITED custom crypto code
  * Uses constant-time operations to resist timing attacks
  * Pure software implementation (no hardware acceleration available)
* **WASM**: Available via ripemd160.wasm.ts for browser environments

### Benchmarks

Typical performance (varies by platform):

* Native (Zig): \~150-250 MB/s
* WASM: \~80-150 MB/s
* Pure JS: \~50-100 MB/s

### Performance vs Other Hashes

```
Algorithm          Software Speed    Hardware Accel
---------          --------------    --------------
RIPEMD160          ~200 MB/s         N/A (no accel)
SHA256             ~500 MB/s         ~2500 MB/s
Keccak256          ~350 MB/s         N/A
Blake2b            ~700 MB/s         N/A
```

**Key insight**: RIPEMD160 is slower than modern alternatives and lacks hardware acceleration. Only use for Bitcoin compatibility. For new applications, Blake2b offers 3x better performance with stronger security margins.

## Implementation Details

### TypeScript Implementation

Uses @noble/hashes legacy module:

```typescript theme={null}
import { ripemd160 } from "@noble/hashes/legacy.js";

export function hash(data: Uint8Array | string): Uint8Array {
  if (typeof data === "string") {
    const encoder = new TextEncoder();
    return ripemd160(encoder.encode(data));
  }
  return ripemd160(data);
}
```

#### WASM

Available via `ripemd160.wasm.ts` for browser environments. Compiled from Zig with wasm32-wasi target.

```typescript theme={null}
import { Ripemd160Wasm } from '@tevm/voltaire/Ripemd160.wasm';
await Ripemd160Wasm.load();
const hash = Ripemd160Wasm.hash(data);
```

## Use Cases

### Bitcoin P2PKH Address

Pay-to-PubKey-Hash (most common Bitcoin address):

```typescript theme={null}
import * as SHA256 from '@tevm/voltaire/SHA256';
import * as RIPEMD160 from '@tevm/voltaire/Ripemd160';

function createPubKeyHash(publicKey: Uint8Array): Uint8Array {
  // Bitcoin uses SHA256 followed by RIPEMD160
  const sha256Hash = SHA256.hash(publicKey);
  const pubKeyHash = RIPEMD160.hash(sha256Hash);
  return pubKeyHash; // 20 bytes
}

// Then add version byte (0x00 for mainnet) and checksum for Base58Check
```

[View Example: bitcoin-address.ts](https://github.com/fucory/voltaire/blob/main/playground/src/examples/crypto/ripemd160/bitcoin-address.ts#L1-L45)

### Bitcoin P2SH Address

Pay-to-Script-Hash addresses:

```typescript theme={null}
import * as SHA256 from '@tevm/voltaire/SHA256';
import * as RIPEMD160 from '@tevm/voltaire/Ripemd160';

function createScriptHash(redeemScript: Uint8Array): Uint8Array {
  const sha256Hash = SHA256.hash(redeemScript);
  const scriptHash = RIPEMD160.hash(sha256Hash);
  return scriptHash; // 20 bytes
}
// Version byte 0x05 for P2SH mainnet addresses
```

### Why Bitcoin Uses Both SHA256 and RIPEMD160

1. **Redundancy**: If one algorithm is broken, the other provides backup security
2. **Compact addresses**: RIPEMD160's 20-byte output reduces address size
3. **Historical**: Design decision made in 2009 when both were considered secure
4. **No single point of failure**: Requires breaking both algorithms for address collision

### Not Recommended For

* **New cryptocurrencies**: Use SHA256, Keccak256, or Blake2b instead
* **General hashing**: SHA256 provides better security margins
* **Password hashing**: Use proper password hash functions (Argon2, bcrypt, scrypt)
* **File integrity**: SHA256 is more widely supported and faster on modern hardware

## Related

* [SHA256](/crypto/sha256) - Used with RIPEMD160 in Bitcoin addresses
* [Keccak256](/crypto/keccak256) - Ethereum's hash function
* [Blake2](/crypto/blake2) - Modern high-performance alternative
* [Address Primitive](/primitives/address) - Ethereum 20-byte addresses
* [RIPEMD160 (Effect)](https://voltaire-effect.tevm.sh/crypto/ripemd160) - Effect.ts integration with Schema validation
