From dd8360d897c9b68212210d836603d9fa4b8ebc49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CPaulo?= Date: Thu, 15 Feb 2024 18:08:47 -0300 Subject: [PATCH] use local ripemd160 when not available --- bit/crypto.py | 10 +++- bit/ripemd160.py | 142 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 149 insertions(+), 3 deletions(-) create mode 100644 bit/ripemd160.py diff --git a/bit/crypto.py b/bit/crypto.py index 701700b..6538fe0 100644 --- a/bit/crypto.py +++ b/bit/crypto.py @@ -1,6 +1,10 @@ -from hashlib import new, sha256 as _sha256 +from hashlib import algorithms_available, new +from hashlib import sha256 as _sha256 -from coincurve import PrivateKey as ECPrivateKey, PublicKey as ECPublicKey +from coincurve import PrivateKey as ECPrivateKey +from coincurve import PublicKey as ECPublicKey + +from .ripemd160 import ripemd160 as r160 def sha256(bytestr): @@ -16,7 +20,7 @@ def double_sha256_checksum(bytestr): def ripemd160_sha256(bytestr): - return new('ripemd160', sha256(bytestr)).digest() + return new('ripemd160', sha256(bytestr)).digest() if "ripemd160" in algorithms_available else r160(sha256(bytestr)) hash160 = ripemd160_sha256 diff --git a/bit/ripemd160.py b/bit/ripemd160.py new file mode 100644 index 0000000..26814bd --- /dev/null +++ b/bit/ripemd160.py @@ -0,0 +1,142 @@ +# Copyright (c) 2021 Pieter Wuille +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# source: https://github.com/richardkiss/pycoin/blob/main/pycoin/contrib/ripemd160.py +# Grudgingly ported to python2 compatibility by Richard Kiss + +import binascii +import struct +import unittest + + +if struct.calcsize("> (32 - i))) & 0xffffffff + + +def compress(h0, h1, h2, h3, h4, block): + """Compress state (h0, h1, h2, h3, h4) with block.""" + # Left path variables. + al, bl, cl, dl, el = h0, h1, h2, h3, h4 + # Right path variables. + ar, br, cr, dr, er = h0, h1, h2, h3, h4 + # Message variables. + x = [struct.unpack("> 4 + # Perform left side of the transformation. + al = rol(al + fi(bl, cl, dl, rnd) + x[ML[j]] + KL[rnd], RL[j]) + el + al, bl, cl, dl, el = el, al, bl, rol(cl, 10), dl + # Perform right side of the transformation. + ar = rol(ar + fi(br, cr, dr, 4 - rnd) + x[MR[j]] + KR[rnd], RR[j]) + er + ar, br, cr, dr, er = er, ar, br, rol(cr, 10), dr + + # Compose old state, left transform, and right transform into new state. + return h1 + cl + dr, h2 + dl + er, h3 + el + ar, h4 + al + br, h0 + bl + cr + + +def ripemd160(data): + """Compute the RIPEMD-160 hash of data.""" + # Initialize state. + state = (0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0) + # Process full 64-byte blocks in the input. + for b in range(len(data) >> 6): + args = list(state) + [data[64*b:64*(b+1)]] + state = compress(*args) + # Construct final blocks (with padding and size). + pad = b"\x80" + b"\x00" * ((119 - len(data)) & 63) + fin = data[len(data) & ~63:] + pad + struct.pack("> 6): + args = list(state) + [fin[64*b:64*(b+1)]] + state = compress(*args) + # Produce output. + return b"".join(struct.pack("