Closed yashasvi-ranawat closed 1 year ago
How does this impact BitCash?
BitCash uses the hash160 (ripemd160_sha256) function to convert public keys to cashaddress and public key hashes for output locking script of P2PKH outputs. This affects the primary functionality of BitCash as a P2PKH wallet.
hash160 uses the hashlib of python, which uses the OpenSSL implementation of ripemd160 which no longer works by default (as tested on OpenSSL 3.0.2, Python 3.10, Linux Ubuntu 22.04 LTS).
I am unable to reproduce this.
Can you send a minimal reproducible example?
from hashlib import new, sha256
new("ripemd160", sha256(b"a").digest()).digest()
I tested this on OpenSSL 3.0.2, Python 3.10.6. Apparently OpenSSL had already marked ripemd160 as legacy algorithm. Do check if you have already enabled legacy_sect as noted here, if you are on the same version of OpenSSL.
This is what my default openssl.cnf file looked like. (only showing relevant options)
openssl_conf = openssl_init
[openssl_init] providers = provider_sect
[provider_sect] default = default_sect
[default_sect] # activate = 1
This led the above python code to give "ValueError: unsupported hash type ripemd160"
After when I enabled legacy algorithms, as given here, the ripemd160 code gave no errors.
from hashlib import new, sha256 new("ripemd160", sha256(b"a").digest()).digest()
This works on my environment (macOS, Python 3.10.6, LibreSSL 3.3.6).
In [1]: from hashlib import new, sha256
...: new("ripemd160", sha256(b"a").digest()).digest()
Out[1]: b'\x99CU\x19\x9eQo\xf7lO\xa4\xaa\xb3\x937\xb9\xd8L\xf1+'
I can try to reproduce in a different environment.
What would be a way to solve this within BitCash? And how much work would that involve?
It seems its a OpenSSl only problem. Other bitcoin libraries have dealt with the same: https://github.com/bitcoin/bitcoin/issues/23710.
Most straightforward way would be to code python native ripemd160 code, as done here
Seems pretty straightforward:
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):
state = compress(*state, data[64*b:64*(b+1)])
# Construct final blocks (with padding and size).
pad = b"\x80" + b"\x00" * ((119 - len(data)) & 63)
fin = data[len(data) & ~63:] + pad + (8 * len(data)).to_bytes(8, 'little')
# Process final blocks.
for b in range(len(fin) >> 6):
state = compress(*state, fin[64*b:64*(b+1)])
# Produce output.
return b"".join((h & 0xffffffff).to_bytes(4, 'little') for h in state)
Would you be willing to submit a PR for that?
I am able to reproduce. Looking forward to merging this change 👍🏻
Tested on OpenSSL 3.0.2, Python 3.10, Linux Ubuntu 22.04 LTS.
Hashlib raises ValueError: unsupported hash type ripemd160, in ripemd160_sha256 function in crypto.py. Found the reason for the issue here.
The stackoverflow answer details how to enable legacy crypto algorithms, but I think a default solution is needed to use ripemd160.