ebellocchia / bip_utils

Generation of mnemonics, seeds, private/public keys and addresses for different types of cryptocurrencies
MIT License
324 stars 86 forks source link

Traceback on python #56

Closed 3venturesio closed 2 years ago

3venturesio commented 2 years ago

Hi, I'm getting this traceback when creating a wallet in python:


    bip44_def_ctx = bip_utils.Bip44.FromSeed(
  File ".tox/devel/lib/python3.9/site-packages/bip_utils/bip/bip44/bip44.py", line 144, in DeriveDefaultPath
    return self._DeriveDefaultPathGeneric(self, Bip44Const.PURPOSE)
  File ".tox/devel/lib/python3.9/site-packages/bip_utils/bip/bip44_base/bip44_base.py", line 275, in _DeriveDefaultPathGeneric
    bip_obj = cls._PurposeGeneric(bip_obj, purpose)
  File ".tox/devel/lib/python3.9/site-packages/bip_utils/bip/bip44_base/bip44_base.py", line 306, in _PurposeGeneric
    return cls(bip_obj.m_bip32.ChildKey(purpose),
  File ".tox/devel/lib/python3.9/site-packages/bip_utils/bip/bip32/bip32_base.py", line 336, in ChildKey
    return self._ValidateAndCkdPriv(index) if not self.IsPublicOnly() else self._ValidateAndCkdPub(index)
  File ".tox/devel/lib/python3.9/site-packages/bip_utils/bip/bip32/bip32_base.py", line 477, in _ValidateAndCkdPriv
    return self._CkdPriv(index)
  File ".tox/devel/lib/python3.9/site-packages/bip_utils/bip/bip32/bip32_secp256k1.py", line 87, in _CkdPriv
    return self._CkdPrivEcdsa(self, index)
  File ".tox/devel/lib/python3.9/site-packages/bip_utils/bip/bip32/bip32_ecdsa_base.py", line 114, in _CkdPrivEcdsa
    fprint=bip32_obj.m_pub_key.FingerPrint(),
  File ".tox/devel/lib/python3.9/site-packages/bip_utils/bip/bip32/bip32_keys.py", line 162, in FingerPrint
    return Bip32FingerPrint(self.KeyIdentifier())
  File ".tox/devel/lib/python3.9/site-packages/bip_utils/bip/bip32/bip32_keys.py", line 172, in KeyIdentifier
    return CryptoUtils.Hash160(self.m_pub_key.RawCompressed().ToBytes())
  File ".tox/devel/lib/python3.9/site-packages/bip_utils/utils/misc/crypto.py", line 222, in Hash160
    return CryptoUtils.Ripemd160(CryptoUtils.Sha256(data))
  File ".tox/devel/lib/python3.9/site-packages/bip_utils/utils/misc/crypto.py", line 199, in Ripemd160
    return hashlib.new("ripemd160", AlgoUtils.Encode(data)).digest()
  File "/usr/lib64/python3.9/hashlib.py", line 166, in __hash_new
    return __get_builtin_constructor(name)(data)
  File "/usr/lib64/python3.9/hashlib.py", line 123, in __get_builtin_constructor
    raise ValueError('unsupported hash type ' + name)
ValueError: unsupported hash type ripemd160

The code I'm using is

        mnemonic = bip_utils.Bip39MnemonicGenerator().FromWordsNumber(
            bip_utils.Bip39WordsNum.WORDS_NUM_24
        )
        is_valid = bip_utils.Bip39MnemonicValidator().IsValid(mnemonic)
        # Validate a mnemonic, raise exceptions
        try:
            bip_utils.Bip39MnemonicValidator().Validate(mnemonic)
            # Valid...
        except bip_utils.Bip39ChecksumError:
            # Invalid checksum...
            pass
        except ValueError:
            # Invalid length or language...
            pass

        if is_valid:

            seed_bytes = bip_utils.Bip39SeedGenerator(mnemonic).Generate()
            bip44_def_ctx = bip_utils.Bip44.FromSeed(
                seed_bytes, bip_utils.Bip44Coins.CHIHUAHUA
            ).DeriveDefaultPath()
            wallet = bip44_def_ctx.PublicKey().ToAddress()

This worked fine with python 3.9 on F35 (and still does), so I assume it's something in the python side on F36, so any hint will be appreciated. (both are on Python 3.9.10)

Thanks

ebellocchia commented 2 years ago

Hi, thanks for the finding, there is always something new to learn. Basically, your hashlib (that is a standard Python library) doesn't implement the ripemd160 algorithm, which is used by some coins for computing the address. I found this by googling:

https://stackoverflow.com/questions/42601709/hashlib-cant-find-ripemd160 https://solveforums.msomimaktaba.com/threads/solved-python-3-9-8-hashlib-and-ripemd160.288028/

So it seems that the ripemd160 implementation is optional in hashlib, depending on the SSL library installed. I'll add some code in order to use Cryptodome to compute it in case it's not implemented.

Regards, Emanuele

3venturesio commented 2 years ago

You're damn fast!, thanks a lot!

3venturesio commented 2 years ago

Hi, one question, I was testing this installing bip_utils from the github repo and I'm still getting something like this:

Traceback (most recent call last):
  File "/usr/lib64/python3.9/hashlib.py", line 160, in __hash_new
    return _hashlib.new(name, data, **kwargs)
ValueError: [digital envelope routines] unsupported

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
, in walletcommands
    bip44_def_ctx = bip_utils.Bip44.FromSeed(
  File ".tox/devel/lib/python3.9/site-packages/bip_utils/bip/bip44/bip44.py", line 144, in DeriveDefaultPath
    return self._DeriveDefaultPathGeneric(self, Bip44Const.PURPOSE)
  File ".tox/devel/lib/python3.9/site-packages/bip_utils/bip/bip44_base/bip44_base.py", line 275, in _DeriveDefaultPathGeneric
    bip_obj = cls._PurposeGeneric(bip_obj, purpose)
  File ".tox/devel/lib/python3.9/site-packages/bip_utils/bip/bip44_base/bip44_base.py", line 306, in _PurposeGeneric
    return cls(bip_obj.m_bip32.ChildKey(purpose),
  File ".tox/devel/lib/python3.9/site-packages/bip_utils/bip/bip32/bip32_base.py", line 336, in ChildKey
    return self._ValidateAndCkdPriv(index) if not self.IsPublicOnly() else self._ValidateAndCkdPub(index)
  File ".tox/devel/lib/python3.9/site-packages/bip_utils/bip/bip32/bip32_base.py", line 477, in _ValidateAndCkdPriv
    return self._CkdPriv(index)
  File ".tox/devel/lib/python3.9/site-packages/bip_utils/bip/bip32/bip32_secp256k1.py", line 87, in _CkdPriv
    return self._CkdPrivEcdsa(self, index)
  File ".tox/devel/lib/python3.9/site-packages/bip_utils/bip/bip32/bip32_ecdsa_base.py", line 114, in _CkdPrivEcdsa
    fprint=bip32_obj.m_pub_key.FingerPrint(),
  File ".tox/devel/lib/python3.9/site-packages/bip_utils/bip/bip32/bip32_keys.py", line 162, in FingerPrint
    return Bip32FingerPrint(self.KeyIdentifier())
  File ".tox/devel/lib/python3.9/site-packages/bip_utils/bip/bip32/bip32_keys.py", line 172, in KeyIdentifier
    return CryptoUtils.Hash160(self.m_pub_key.RawCompressed().ToBytes())
  File ".tox/devel/lib/python3.9/site-packages/bip_utils/utils/misc/crypto.py", line 236, in Hash160
    return CryptoUtils.Ripemd160(CryptoUtils.Sha256(data))
  File ".tox/devel/lib/python3.9/site-packages/bip_utils/utils/misc/crypto.py", line 207, in Ripemd160
    return hashlib.new("ripemd160", AlgoUtils.Encode(data)).digest()
  File "/usr/lib64/python3.9/hashlib.py", line 166, in __hash_new
    return __get_builtin_constructor(name)(data)
  File "/usr/lib64/python3.9/hashlib.py", line 123, in __get_builtin_constructor
    raise ValueError('unsupported hash type ' + name)
ValueError: unsupported hash type ripemd160
ebellocchia commented 2 years ago

That's strange, can you print in a Python console the value of hashlib.algorithms_available ?

3venturesio commented 2 years ago
>>> import hashlib
>>> hashlib.algorithms_available
{'sha256', 'sha512', 'ripemd160', 'sha512_256', 'sha3_256', 'sha512_224', 'sm3', 'shake_128', 'md5', 'shake_256', 'blake2s', 'md5-sha1', 'sha1', 'sha3_384', 'sha3_224', 'sha224', 'whirlpool', 'blake2b', 'md4', 'sha3_512', 'sha384'}
Package               Version
--------------------- -----------
aiocron               1.8
aiohttp               3.7.4.post0
alembic               1.7.7
asn1crypto            1.5.1
async-timeout         3.0.1
attrs                 21.4.0
Automat               20.2.0
autopage              0.5.0
Babel                 2.9.1
base58                2.1.1
beautifulsoup4        4.10.0
bip-utils             2.3.0
certifi               2021.10.8
cffi                  1.15.0
chardet               4.0.0
charset-normalizer    2.0.12
click                 4.1
cliff                 3.10.1
cmd2                  2.4.0
coincurve             17.0.0
constantly            15.1.0
coverage              6.3.2
crcmod                1.7
crochet               2.0.0
croniter              1.3.4
cryptography          36.0.2
cssselect             1.1.0
decorator             5.1.1
deep-translator       1.8.1
dill                  0.3.4
discord.py            1.7.3
ecdsa                 0.17.0
ed25519-blake2b       1.4
extras                1.0.0
feedparser            6.0.8
filelock              3.6.0
fixtures              3.0.0
flake8                4.0.1
free-proxy            1.0.6
future                0.18.2
gearbest-api          0.0.4
greenlet              1.1.2
html-parser           0.2
hyperlink             21.0.0
icalendar             4.0.9
idna                  3.3
incremental           21.3.0
itemadapter           0.5.0
itemloaders           1.0.4
jmespath              1.0.0
joblib                1.1.0
langdetect            1.0.9
lxml                  4.8.0
Mako                  1.2.0
MarkupSafe            2.1.1
mccabe                0.6.1
misspellings          1.5
more-itertools        8.12.0
multidict             6.0.2
nltk                  3.7
nose                  1.3.7
numpy                 1.22.3
os-testr              2.0.1
pandas                1.4.1
parsel                1.6.0
pbr                   5.8.1
pip                   21.3.1
ply                   3.11
prettytable           3.2.0
Protego               0.2.1
py-sr25519-bindings   0.1.4
pyasn1                0.4.8
pyasn1-modules        0.2.8
pycodestyle           2.8.0
pycparser             2.21
pycryptodome          3.14.1
PyDispatcher          2.0.5
pyflakes              2.4.0
pymarkdownlint        0.3.1
PyNaCl                1.5.0
pyOpenSSL             22.0.0
pyparsing             3.0.7
pyperclip             1.8.2
python-amazon-paapi   4.2.1
python-coveralls      2.9.3
python-dateutil       2.8.2
python-ldap           3.4.0
python-subunit        1.4.0
pytz                  2022.1
pytz-deprecation-shim 0.1.0.post0
PyYAML                6.0
queuelib              1.6.2
regex                 2022.3.15
requests              2.27.1
requests-file         1.5.1
river                 0.10.1
scalecodec            1.0.34
scipy                 1.8.0
Scrapy                2.6.1
service-identity      21.1.0
setuptools            60.9.3
sgmllib3k             1.0.0
six                   1.16.0
soupsieve             2.3.1
SQLAlchemy            1.4.32
stestr                3.2.1
stevedore             3.5.0
testrepository        0.0.20
testresources         2.0.1
testtools             2.5.0
tldextract            3.2.0
tqdm                  4.63.0
Twisted               22.2.0
typing_extensions     4.1.1
tzdata                2022.1
tzlocal               4.1
unshortenit           0.1.8
urlexpander           0.0.37
urllib3               1.26.9
validators            0.18.2
voluptuous            0.12.2
w3lib                 1.22.0
wcwidth               0.2.5
wheel                 0.37.1
wrapt                 1.14.0
yarl                  1.7.2
zope.interface        5.4.0

Thanks!

ebellocchia commented 2 years ago

Is it the same machine where you get the exception? If yes, there is no reason why it should fail. ripemd160 is present among the available algorithms, so the library calls it. You can force it to use Cryptodome by setting HASHLIB_USE_RIPEMD160 to false in utils/mic/crypto.py

3venturesio commented 2 years ago

I've tested something, as I'm using tox, and I thought that I was using the same interpreter, so fouble checked... the right output inside 'tox' is:

{'sha256', 'sha1', 'sha3_512', 'sm3', 'md4', 'sha384', 'sha3_256', 'sha512_224', 'md5', 'sha512', 'ripemd160', 'md5-sha1', 'sha224', 'shake_128', 'blake2s', 'shake_256', 'whirlpool', 'blake2b', 'sha3_384', 'sha512_256', 'sha3_224'} but as you can see, it really shows ripemd160

Hardcoding it to be 'False' makes it work and returns a valid wallet address, so... your code is fine, ripemd is listed by hashlib, but something with it is not supporting the hash type raise ValueError('unsupported hash type ' + name)

Seem similar to this: https://stackoverflow.com/questions/69922525/python-3-9-8-hashlib-and-ripemd160

3venturesio commented 2 years ago

https://www.openssl.org/docs/manmaster/man3/RIPEMD160.html

ebellocchia commented 2 years ago

Ok, yes that's most probably a problem of the SSL library installed in the machine

3venturesio commented 2 years ago

The library is the latest one available in the host (Fedora 36), would make sense, as it's listed in the openssl library that it's going to be deprecated to always use the 'fallback' ? TY!

ebellocchia commented 2 years ago

Ok, well I can just remove hashlib for ripemd160 and always use Cryptodome so that no one will have the same problem