Search code examples
pythonblockchainbitcoinecdsa

Having troubles with the ecdsa library for python


I wanted to test out if the elliptic curve code (to derive a public key from a private key) from the book Mastering Bitcoin by Andreas Antonopolous would work...so I copied and pasted the code in the book to my VSC editor. It prompted a few errors that made me delete the 'L's at the end of the parameters and inserted the necessary parenthesis after the print statements. Now I am still encountering errors such as "unable to import ecdsa.util"...

Below is the code I am using and attached is the snapshot of the error it shows:


import ecdsa
import random

from ecdsa.util import string_to_number, number_to_string

_p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
_r = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
_b = 0x0000000000000000000000000000000000000000000000000000000000000007
_a = 0x0000000000000000000000000000000000000000000000000000000000000000
_Gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798
_Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8
curve_secp256k1 = ecdsa.ellipticcurve.CurveFp(_p, _a, _b)
generator_secp256k1 = ecdsa.ellipticcurve.Point(curve_secp256k1, _Gx, _Gy, _r)
oid_secp256k1 = (1, 3, 132, 0, 10)
SECP256k1 = ecdsa.curves.Curve("SECP256k1", curve_secp256k1, generator_secp256k1,
oid_secp256k1)
ec_order = _r

curve = curve_secp256k1
generator = generator_secp256k1

def random_secret():
    random_char = lambda: chr(random.randint(0, 255))
    convert_to_int = lambda array: int("".join(array).encode("hex"), 16)
    byte_array = [random_char() for i in range(32)]
    return convert_to_int(byte_array)

def get_point_pubkey(point):
    if point.y() & 1:
        key = '03' + '%064x' % point.x()
    else:
        key = '02' + '%064x' % point.x()
    return key.decode('hex')

def get_point_pubkey_uncompressed(point):
    key = '04' + \
          '%064x' % point.x() + \
          '%064x' % point.y()
    return key.decode('hex')

secret = random_secret()
print ("Secret: ", secret)

point = secret * generator
print ("EC point:", point)

print ("BTC public key:", get_point_pubkey(point).encode("hex"))

point1 = ecdsa.ellipticcurve.Point(curve, point.x(), point.y(), ec_order)
assert point1 == point


Solution

  • Because Mastering Bitcoin's python code is based by python2 and python3 has changed string encode and decode.

    this is right activated code with python3

    import ecdsa
    import os
    import binascii
    from ecdsa.util import string_to_number, number_to_string
    
    _p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
    _r = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
    _b = 0x0000000000000000000000000000000000000000000000000000000000000007
    _a = 0x0000000000000000000000000000000000000000000000000000000000000000
    _Gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798
    _Gy = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8
    curve_secp256k1 = ecdsa.ellipticcurve.CurveFp(_p, _a, _b)
    generator_secp256k1 = ecdsa.ellipticcurve.Point(curve_secp256k1, _Gx, _Gy, _r)
    oid_secp256k1 = (1, 3, 132, 0, 10)
    SECP256k1 = ecdsa.curves.Curve(
        "SECP256k1", curve_secp256k1, generator_secp256k1, oid_secp256k1
    )
    ec_order = _r
    
    curve = curve_secp256k1
    generator = generator_secp256k1
    
    
    def random_secret():
        convert_to_int = lambda array: int(binascii.hexlify(array), 16)
        byte_array = os.urandom(32)
        return convert_to_int(byte_array)
    
    
    def get_point_pubkey(point):
        if point.y() & 1:
            key = "03" + "%064x" % point.x()
        else:
            key = "02" + "%064x" % point.x()
        return binascii.unhexlify(key)
    
    
    def get_point_pubkey_uncompressed(point):
        key = "04" + "%064x" % point.x() + "%064x" % point.y()
        return binascii.unhexlify(key)
    
    
    secret = random_secret()
    print("Secret: ", secret)
    
    point = secret * generator
    print("EC point: ", point)
    
    print("BTC public key: ", binascii.hexlify(get_point_pubkey(point)))
    
    point1 = ecdsa.ellipticcurve.Point(curve, point.x(), point.y(), ec_order)
    assert point1 == point
    

    and the result is this

    Secret:  45144777120122405140812796301557992803916792041985925168483786699489296135626
    EC point:  (97022596039543818601440182171533278426801313043337446429800654678890979695199,53586405348987121115764110810505844890885198959743315511392863714433787991327)
    BTC public key:  b'03d680d7e3daf984534507c6ddd7d7cfa07864daf6b78d5b52bf657ecb636a9a5f'