Module refinery.lib.ripemd128

Implementation of RIPEMD128 in pure Python.

Expand source code Browse git
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Implementation of RIPEMD128 in pure Python.
"""
import itertools

from refinery.lib.crypto import rotl32 as rol
from refinery.lib import chunks


def _ripemd128_blocks(msg):
    N = len(msg)
    P = (56 - N) % 64
    msg += b'\x80' + b'\x00' * (P - 1) + (N << 3).to_bytes(8, 'little')
    it = iter(chunks.unpack(msg, 4))
    while True:
        block = list(itertools.islice(it, 16))
        if not block:
            break
        assert len(block) == 16
        yield block


def ripemd128(message):

    R_ = [
        0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF,
        0x7, 0x4, 0xD, 0x1, 0xA, 0x6, 0xF, 0x3, 0xC, 0x0, 0x9, 0x5, 0x2, 0xE, 0xB, 0x8,
        0x3, 0xA, 0xE, 0x4, 0x9, 0xF, 0x8, 0x1, 0x2, 0x7, 0x0, 0x6, 0xD, 0xB, 0x5, 0xC,
        0x1, 0x9, 0xB, 0xA, 0x0, 0x8, 0xC, 0x4, 0xD, 0x3, 0x7, 0xF, 0xE, 0x5, 0x6, 0x2,
    ]
    RP = [
        0x5, 0xE, 0x7, 0x0, 0x9, 0x2, 0xB, 0x4, 0xD, 0x6, 0xF, 0x8, 0x1, 0xA, 0x3, 0xC,
        0x6, 0xB, 0x3, 0x7, 0x0, 0xD, 0x5, 0xA, 0xE, 0xF, 0x8, 0xC, 0x4, 0x9, 0x1, 0x2,
        0xF, 0x5, 0x1, 0x3, 0x7, 0xE, 0x6, 0x9, 0xB, 0x8, 0xC, 0x2, 0xA, 0x0, 0x4, 0xD,
        0x8, 0x6, 0x4, 0x1, 0x3, 0xB, 0xF, 0x0, 0x5, 0xC, 0x2, 0xD, 0x9, 0x7, 0xA, 0xE,
    ]
    S_ = [
        0xB, 0xE, 0xF, 0xC, 0x5, 0x8, 0x7, 0x9, 0xB, 0xD, 0xE, 0xF, 0x6, 0x7, 0x9, 0x8,
        0x7, 0x6, 0x8, 0xD, 0xB, 0x9, 0x7, 0xF, 0x7, 0xC, 0xF, 0x9, 0xB, 0x7, 0xD, 0xC,
        0xB, 0xD, 0x6, 0x7, 0xE, 0x9, 0xD, 0xF, 0xE, 0x8, 0xD, 0x6, 0x5, 0xC, 0x7, 0x5,
        0xB, 0xC, 0xE, 0xF, 0xE, 0xF, 0x9, 0x8, 0x9, 0xE, 0x5, 0x6, 0x8, 0x6, 0x5, 0xC,
    ]
    SP = [
        0x8, 0x9, 0x9, 0xB, 0xD, 0xF, 0xF, 0x5, 0x7, 0x7, 0x8, 0xB, 0xE, 0xE, 0xC, 0x6,
        0x9, 0xD, 0xF, 0x7, 0xC, 0x8, 0x9, 0xB, 0x7, 0x7, 0xC, 0x7, 0x6, 0xF, 0xD, 0xB,
        0x9, 0x7, 0xF, 0xB, 0x8, 0x6, 0x6, 0xE, 0xC, 0xD, 0x5, 0xE, 0xD, 0xD, 0x7, 0x5,
        0xF, 0x5, 0x8, 0xB, 0xE, 0xE, 0x6, 0xE, 0x6, 0x9, 0xC, 0x9, 0xC, 0x5, 0xF, 0x8,
    ]

    def F0(x, y, z): return (x ^ y ^ z)
    def F1(x, y, z): return (x & y) | (z & ~x)
    def F2(x, y, z): return (x | (0xffffffff & ~y)) ^ z
    def F3(x, y, z): return (x & z) | (y & ~z)

    F = [F0, F1, F2, F3]

    K_ = [0x00000000, 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC]
    Kp = [0x50A28BE6, 0x5C4DD124, 0x6D703EF3, 0x00000000]

    h0 = 0x67452301
    h1 = 0xEFCDAB89
    h2 = 0x98BADCFE
    h3 = 0x10325476

    for block in _ripemd128_blocks(message):
        A_, B_, C_, D_ = h0, h1, h2, h3
        Ap, Bp, Cp, Dp = h0, h1, h2, h3
        for j in range(64):
            k = 63 - j
            tv = rol(A_ + F[j // 0x10](B_, C_, D_) + block[R_[j]] + K_[j // 0x10] & 0xFFFFFFFF, S_[j])
            A_, D_, C_, B_ = D_, C_, B_, tv
            tv = rol(Ap + F[k // 0x10](Bp, Cp, Dp) + block[RP[j]] + Kp[j // 0x10] & 0xFFFFFFFF, SP[j])
            Ap, Dp, Cp, Bp = Dp, Cp, Bp, tv
        tv = h1 + C_ + Dp & 0xFFFFFFFF
        h1 = h2 + D_ + Ap & 0xFFFFFFFF
        h2 = h3 + A_ + Bp & 0xFFFFFFFF
        h3 = h0 + B_ + Cp & 0xFFFFFFFF
        h0 = tv

    return chunks.pack((h0, h1, h2, h3), 4)

Functions

def ripemd128(message)
Expand source code Browse git
def ripemd128(message):

    R_ = [
        0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF,
        0x7, 0x4, 0xD, 0x1, 0xA, 0x6, 0xF, 0x3, 0xC, 0x0, 0x9, 0x5, 0x2, 0xE, 0xB, 0x8,
        0x3, 0xA, 0xE, 0x4, 0x9, 0xF, 0x8, 0x1, 0x2, 0x7, 0x0, 0x6, 0xD, 0xB, 0x5, 0xC,
        0x1, 0x9, 0xB, 0xA, 0x0, 0x8, 0xC, 0x4, 0xD, 0x3, 0x7, 0xF, 0xE, 0x5, 0x6, 0x2,
    ]
    RP = [
        0x5, 0xE, 0x7, 0x0, 0x9, 0x2, 0xB, 0x4, 0xD, 0x6, 0xF, 0x8, 0x1, 0xA, 0x3, 0xC,
        0x6, 0xB, 0x3, 0x7, 0x0, 0xD, 0x5, 0xA, 0xE, 0xF, 0x8, 0xC, 0x4, 0x9, 0x1, 0x2,
        0xF, 0x5, 0x1, 0x3, 0x7, 0xE, 0x6, 0x9, 0xB, 0x8, 0xC, 0x2, 0xA, 0x0, 0x4, 0xD,
        0x8, 0x6, 0x4, 0x1, 0x3, 0xB, 0xF, 0x0, 0x5, 0xC, 0x2, 0xD, 0x9, 0x7, 0xA, 0xE,
    ]
    S_ = [
        0xB, 0xE, 0xF, 0xC, 0x5, 0x8, 0x7, 0x9, 0xB, 0xD, 0xE, 0xF, 0x6, 0x7, 0x9, 0x8,
        0x7, 0x6, 0x8, 0xD, 0xB, 0x9, 0x7, 0xF, 0x7, 0xC, 0xF, 0x9, 0xB, 0x7, 0xD, 0xC,
        0xB, 0xD, 0x6, 0x7, 0xE, 0x9, 0xD, 0xF, 0xE, 0x8, 0xD, 0x6, 0x5, 0xC, 0x7, 0x5,
        0xB, 0xC, 0xE, 0xF, 0xE, 0xF, 0x9, 0x8, 0x9, 0xE, 0x5, 0x6, 0x8, 0x6, 0x5, 0xC,
    ]
    SP = [
        0x8, 0x9, 0x9, 0xB, 0xD, 0xF, 0xF, 0x5, 0x7, 0x7, 0x8, 0xB, 0xE, 0xE, 0xC, 0x6,
        0x9, 0xD, 0xF, 0x7, 0xC, 0x8, 0x9, 0xB, 0x7, 0x7, 0xC, 0x7, 0x6, 0xF, 0xD, 0xB,
        0x9, 0x7, 0xF, 0xB, 0x8, 0x6, 0x6, 0xE, 0xC, 0xD, 0x5, 0xE, 0xD, 0xD, 0x7, 0x5,
        0xF, 0x5, 0x8, 0xB, 0xE, 0xE, 0x6, 0xE, 0x6, 0x9, 0xC, 0x9, 0xC, 0x5, 0xF, 0x8,
    ]

    def F0(x, y, z): return (x ^ y ^ z)
    def F1(x, y, z): return (x & y) | (z & ~x)
    def F2(x, y, z): return (x | (0xffffffff & ~y)) ^ z
    def F3(x, y, z): return (x & z) | (y & ~z)

    F = [F0, F1, F2, F3]

    K_ = [0x00000000, 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC]
    Kp = [0x50A28BE6, 0x5C4DD124, 0x6D703EF3, 0x00000000]

    h0 = 0x67452301
    h1 = 0xEFCDAB89
    h2 = 0x98BADCFE
    h3 = 0x10325476

    for block in _ripemd128_blocks(message):
        A_, B_, C_, D_ = h0, h1, h2, h3
        Ap, Bp, Cp, Dp = h0, h1, h2, h3
        for j in range(64):
            k = 63 - j
            tv = rol(A_ + F[j // 0x10](B_, C_, D_) + block[R_[j]] + K_[j // 0x10] & 0xFFFFFFFF, S_[j])
            A_, D_, C_, B_ = D_, C_, B_, tv
            tv = rol(Ap + F[k // 0x10](Bp, Cp, Dp) + block[RP[j]] + Kp[j // 0x10] & 0xFFFFFFFF, SP[j])
            Ap, Dp, Cp, Bp = Dp, Cp, Bp, tv
        tv = h1 + C_ + Dp & 0xFFFFFFFF
        h1 = h2 + D_ + Ap & 0xFFFFFFFF
        h2 = h3 + A_ + Bp & 0xFFFFFFFF
        h3 = h0 + B_ + Cp & 0xFFFFFFFF
        h0 = tv

    return chunks.pack((h0, h1, h2, h3), 4)