AntonKueltz / fastecdsa

Python library for fast elliptic curve crypto
https://pypi.python.org/pypi/fastecdsa
The Unlicense
264 stars 77 forks source link

Issue with running it on python 2 #37

Closed kpachhai closed 5 years ago

kpachhai commented 5 years ago

The function bytes_to_int at https://github.com/AntonKueltz/fastecdsa/blob/master/fastecdsa/encoding/util.py uses a function indexbytes from the library called six. It looks like this function call is not compatible with python version 2.

six.py

def indexbytes(buf, i):
        return ord(buf[i])

fastecdsa/encoding/util.py

def bytes_to_int(bytestr):
    """Make an integer from a big endian bytestring."""
    value = 0
    for i in range(len(bytestr)):
        value = value * 256 + indexbytes(bytestr, i)
    return value

This is causing some runtime errors. I had to manually update the util.py method to the following:

def bytes_to_int(bytestr):
    """Make an integer from a big endian bytestring."""
    value = 0
    for i in range(len(bytestr)):
        value = value * 256 + bytestr[i]
    return value

And everything started working again. Is it possible to make a change to this so those of us using python 2 don't run into this issue?

AntonKueltz commented 5 years ago

Do you have a trace / error log you can provide. I can't replicate (with python 2.7.14) -

In [1]: from six import indexbytes

In [2]: bytestr = b'\xc0\xde'

In [3]: from fastecdsa.encoding.util import bytes_to_int

In [4]: bytes_to_int(bytestr)
Out[4]: 49374

In [5]: hex(_)
Out[5]: '0xc0de'
kpachhai commented 5 years ago

Below is what I'm trying to do and i get the following error:

>>> client_public_key = "0314b24c119be7e3109939482c39b751b6baf68bc65aa26e331087ff30a6dc51ee"
>>> from fastecdsa.encoding.sec1 import SEC1Encoder
>>> from fastecdsa import ecdsa, curve
>>> public_key = SEC1Encoder.decode_public_key(bytearray.fromhex(client_public_key), curve.P256)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/fastecdsa/encoding/sec1.py", line 58, in decode_public_key
    x = bytes_to_int(key[1:])
  File "/usr/local/lib/python2.7/dist-packages/fastecdsa/encoding/util.py", line 29, in bytes_to_int
    value = value * 256 + indexbytes(bytestr, i)
  File "/usr/lib/python2.7/dist-packages/six.py", line 661, in indexbytes
    return ord(buf[i])
TypeError: ord() expected string of length 1, but int found
>>> 

Below is what I'm supposed to get(and I get this if I modify the code to "bytestr[i]"

>>> client_public_key = "0314b24c119be7e3109939482c39b751b6baf68bc65aa26e331087ff30a6dc51ee"
>>> from fastecdsa.encoding.sec1 import SEC1Encoder
>>> from fastecdsa import ecdsa, curve
>>> public_key = SEC1Encoder.decode_public_key(bytearray.fromhex(client_public_key), curve.P256)
>>> public_key
X: 0x14b24c119be7e3109939482c39b751b6baf68bc65aa26e331087ff30a6dc51ee
Y: 0x89a73915cd720d9f54b8c77569d7836630bbd1b2fed97770efdc7c4dee483ad9
(On curve <P256>)
>>> 
AntonKueltz commented 5 years ago

bytearray is a bit of a strange interface in python2, prefer to work on bytes which is the type this library (and most other python crypto libs) operate on. You can use binascii.unhexlify to get bytes from a hex string. See below for a working example

In [1]: from fastecdsa.encoding.sec1 import SEC1Encoder

In [2]: from fastecdsa import ecdsa, curve

In [3]: from binascii import unhexlify

In [4]: client_public_key = "0314b24c119be7e3109939482c39b751b6baf68bc65aa26e331
   ...: 087ff30a6dc51ee"

In [5]: public_key = SEC1Encoder.decode_public_key(unhexlify(client_public_key),
   ...:  curve.P256)

In [6]: public_key
Out[6]:
X: 0x14b24c119be7e3109939482c39b751b6baf68bc65aa26e331087ff30a6dc51ee
Y: 0x89a73915cd720d9f54b8c77569d7836630bbd1b2fed97770efdc7c4dee483ad9
(On curve <P256>)
kpachhai commented 5 years ago

Thanks for the suggestion. This works!