Class: BSV::Primitives::Ripemd160

Inherits:
Object
  • Object
show all
Defined in:
lib/bsv/primitives/ripemd160.rb

Overview

Pure-Ruby implementation of RIPEMD-160.

Ported from the reference C implementation by Hans Dobbertin, Antoon Bosselaers, and Bart Preneel (homes.esat.kuleuven.be/~bosselae/ripemd160/).

RIPEMD-160 processes data in 512-bit (64-byte) blocks with 80 rounds split across two parallel paths (left and right). The five 32-bit state words are initialised to standard IV constants and updated via a Merkle-Damgård construction with Merkle-Damgård strengthening.

All arithmetic is 32-bit unsigned (masked with 0xFFFFFFFF after additions).

Usage:

BSV::Primitives::Ripemd160.digest(data) # => 20-byte binary String

Constant Summary collapse

IV =

Initial hash values (little-endian words).

[0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0].freeze
MASK32 =

Mask for 32-bit unsigned arithmetic.

0xFFFFFFFF
RL =

Left-path message word selection (rounds 0-79).

[
  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, # round 0-15
  7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,  # round 16-31
  3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,  # round 32-47
  1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,  # round 48-63
  4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13   # round 64-79
].freeze
RR =

Right-path message word selection (rounds 0-79).

[
  5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,  # round 0-15
  6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,  # round 16-31
  15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,  # round 32-47
  8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,  # round 48-63
  12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11   # round 64-79
].freeze
SL =

Left-path rotation amounts (rounds 0-79).

[
  11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,  # round 0-15
  7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,  # round 16-31
  11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,  # round 32-47
  11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,  # round 48-63
  9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6   # round 64-79
].freeze
SR =

Right-path rotation amounts (rounds 0-79).

[
  8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,  # round 0-15
  9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,  # round 16-31
  9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,  # round 32-47
  15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,  # round 48-63
  8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11   # round 64-79
].freeze
KL =

Left-path round constants (K_l).

[
  0x00000000, # rounds 0-15:  f(j) = x XOR y XOR z
  0x5A827999, # rounds 16-31: f(j) = (x AND y) OR (NOT x AND z)
  0x6ED9EBA1, # rounds 32-47: f(j) = (x OR NOT y) XOR z
  0x8F1BBCDC, # rounds 48-63: f(j) = (x AND z) OR (y AND NOT z)
  0xA953FD4E  # rounds 64-79: f(j) = x XOR (y OR NOT z)
].freeze
KR =

Right-path round constants (K_r).

[
  0x50A28BE6, # rounds 0-15:  f(j) = x XOR (y OR NOT z)
  0x5C4DD124, # rounds 16-31: f(j) = (x AND z) OR (y AND NOT z)
  0x6D703EF3, # rounds 32-47: f(j) = (x OR NOT y) XOR z
  0x7A6D76E9, # rounds 48-63: f(j) = (x AND y) OR (NOT x AND z)
  0x00000000  # rounds 64-79: f(j) = x XOR y XOR z
].freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(data) ⇒ Ripemd160

Returns a new instance of Ripemd160.

Parameters:

  • data (String)

    input data

Raises:

  • (TypeError)

    if data is not a String



92
93
94
95
96
# File 'lib/bsv/primitives/ripemd160.rb', line 92

def initialize(data)
  raise TypeError, "no implicit conversion of #{data.class} into String" unless data.is_a?(String)

  @data = data.b # force binary encoding
end

Class Method Details

.digest(data) ⇒ String

Compute the RIPEMD-160 digest of data.

Parameters:

  • data (String)

    input data (any encoding; treated as binary)

Returns:

  • (String)

    20-byte binary digest (ASCII-8BIT encoding)



85
86
87
# File 'lib/bsv/primitives/ripemd160.rb', line 85

def digest(data)
  new(data).digest
end

Instance Method Details

#digestString

Returns 20-byte binary digest.

Returns:

  • (String)

    20-byte binary digest



99
100
101
102
103
104
# File 'lib/bsv/primitives/ripemd160.rb', line 99

def digest
  state = IV.dup
  blocks, = padded_blocks
  blocks.each { |block| compress!(state, block) }
  state.pack('V5')
end