ivilata / pymultihash

Python implementation of the multihash specification
19 stars 8 forks source link

Base58 encoding seems to not work #11

Closed taxa-chris closed 4 years ago

taxa-chris commented 4 years ago
import multihash, hashlib

def do_multihash(item, encoding):
    dig = hashlib.sha256(item.encode()).digest()
    mh = multihash.Multihash(multihash.Func.sha2_256, dig)
    return mh.encode(encoding)

In [6]: do_multihash('abcdefgh', 'base64')                                                                                                                                  
Out[6]: b'EiCcVsxRs3TDuhiSENW21L9XeQ01HJbEfAIZDs8eQwY1qw=='

In [7]: do_multihash('abcdefgh', 'base58')                                                                                                                                  
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-7-c489b7421be2> in <module>
----> 1 lib_multihash('abcdefgh', 'base58')

~/SDK-Python/taxa_sdk/multihash.py in lib_multihash(item, encoding)
      9     dig = hashlib.sha256(item.encode()).digest()
     10     mh = multihash.Multihash(multihash.Func.sha2_256,dig)
---> 11     return mh.encode(encoding)

~/.virtualenvs/taxa3/lib/python3.7/site-packages/multihash/multihash.py in encode(self, encoding)
    142         mhash = bytes([fc, len(self.digest)]) + self.digest
    143         if encoding:
--> 144             mhash = CodecReg.get_encoder(encoding)(mhash)
    145         return mhash
    146 

~/.virtualenvs/taxa3/lib/python3.7/site-packages/multihash/codecs.py in <lambda>(s)
     49     if base58:
     50         _common_codec_data.append(
---> 51             ('base58', lambda s: bytes(base58.b58encode(s), 'ascii'), base58.b58decode))
     52 
     53     # Codec data: encoding and decoding functions (both from bytes to bytes).

TypeError: encoding without a string argument
ivilata commented 4 years ago

Hi @taxa-chris, thanks for the report. As you can see in the docstring of multihash/__init__.py, Multihash expects a bytes object as a second argument, not a str.

Actually, the call using the base64 encoding may have failed as well, it happened to work by pure chance of the Base64 call path being more permissive with accepted types…

I'm closing the issue but feel free to open another one regarding that behavior (but mind you, I don't have much time to take care of these issues anyway).

Cheers!

taxa-chris commented 4 years ago

The var dig is being passed into MultiHash.__init__ as the second argument, which is always a bytes object, since dig is the output of hashlib.digest()

Anyways, I think the problem is the "ascii" argument needs to be removed, as that seems to fix the problem:

In [5]: import base58                                                                                                                                                        

In [6]: base58.b58encode(b'34')                                                                                                                                              
Out[6]: b'4u1'

In [7]: base58.b58encode('34')                                                                                                                                               
Out[7]: b'4u1'

In [8]: bytes(base58.b58encode('34'))                                                                                                                                        
Out[8]: b'4u1'

In [9]: bytes(base58.b58encode('34'), 'ascii')                                                                                                                               
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-9-f5606cddfe84> in <module>
----> 1 bytes(base58.b58encode('34'), 'ascii')

TypeError: encoding without a string argument

In [10]:     

Why is 'ascii' there in the first place?