def from_sec(string, curve=curves.SECP256k1, hashfunc=sha1, validate_point=True): """Convert a public key in SEC binary format to a verifying key.""" # based on code from https://github.com/richardkiss/pycoin if string.startswith(b('\x04')): # uncompressed return VerifyingKey.from_string(string[1:], curve, hashfunc, validate_point) elif string.startswith(b('\x02')) or string.startswith(b('\x03')): # compressed is_even = string.startswith(b('\x02')) x = string_to_number(string[1:]) order = curve.order p = curve.curve.p() alpha = (pow(x, 3, p) + (curve.curve.a() * x) + curve.curve.b()) % p beta = square_root_mod_prime(alpha, p) if is_even == bool(beta & 1): y = p - beta else: y = beta if validate_point: assert ecdsa.point_is_valid(curve.generator, x, y) point = ellipticcurve.Point(curve.curve, x, y, order) return VerifyingKey.from_public_point(point, curve, hashfunc)
def get_ecdsa_verifying_key(pub): #some shenanigans required to validate a transaction sig; see #python.ecdsa PR #54. This will be a lot simpler when that's merged. #https://github.com/warner/python-ecdsa/pull/54/files if not pub[0] in ["\x02", "\x03"]: log.debug("Invalid pubkey") return None is_even = pub.startswith('\x02') x = string_to_number(pub[1:]) order = SECP256k1.order p = SECP256k1.curve.p() alpha = (pow(x, 3, p) + (SECP256k1.curve.a() * x) + SECP256k1.curve.b()) % p beta = square_root_mod_prime(alpha, p) if is_even == bool(beta & 1): y = p - beta else: y = beta if not point_is_valid(SECP256k1.generator, x, y): return None point = Point(SECP256k1.curve, x, y, order) return VerifyingKey.from_public_point(point, SECP256k1, hashfunc=hashlib.sha256)
def verify_point(G, p): """ Verifies a point on the elliptic curve G.curve :param G: elliptic curve base point, a generator of the elliptic curve with large prime order n :param p: point :return: boolean """ return point_is_valid(G, p.x(), p.y())
def from_sec(string, curve=curves.SECP256k1, hashfunc=sha1, validate_point=True): """Convert a public key in SEC binary format to a verifying key.""" # based on code from https://github.com/richardkiss/pycoin if string.startswith(b("\x04")): # uncompressed return VerifyingKey.from_string(string[1:], curve, hashfunc, validate_point) elif string.startswith(b("\x02")) or string.startswith(b("\x03")): # compressed is_even = string.startswith(b("\x02")) x = string_to_number(string[1:]) order = curve.order p = curve.curve.p() alpha = (pow(x, 3, p) + (curve.curve.a() * x) + curve.curve.b()) % p beta = square_root_mod_prime(alpha, p) if is_even == bool(beta & 1): y = p - beta else: y = beta if validate_point: assert ecdsa.point_is_valid(curve.generator, x, y) point = ellipticcurve.Point(curve.curve, x, y, order) return VerifyingKey.from_public_point(point, curve, hashfunc)
def uncompress(string: bytes, curve=SECP256k1) -> Point: if string[:1] not in (b'\x02', b'\x03'): raise MalformedPoint("Malformed compressed point encoding") is_even = string[:1] == b'\x02' x = string_to_number(string[1:]) order = curve.order p = curve.curve.p() alpha = (pow(x, 3, p) + (curve.curve.a() * x) + curve.curve.b()) % p try: beta = square_root_mod_prime(alpha, p) except SquareRootError as e: raise MalformedPoint( "Encoding does not correspond to a point on curve", e ) if is_even == bool(beta & 1): y = p - beta else: y = beta if not ecdsa.point_is_valid(curve.generator, x, y): raise MalformedPoint("Point does not lie on curve") return point_to_pubkey_bytes(Point(curve.curve, x, y, order))