diff --git a/electrum/ecc.py b/electrum/ecc.py index e459512a3..5531309de 100644 --- a/electrum/ecc.py +++ b/electrum/ecc.py @@ -65,32 +65,73 @@ def string_to_number(b: bytes) -> int: return int.from_bytes(b, byteorder='big', signed=False) -def sig_string_from_der_sig(der_sig: bytes, order=CURVE_ORDER) -> bytes: # TODO use libsecp? - r, s = ecdsa.util.sigdecode_der(der_sig, order) - return ecdsa.util.sigencode_string(r, s, order) +def sig_string_from_der_sig(der_sig: bytes, order=CURVE_ORDER) -> bytes: + r, s = get_r_and_s_from_der_sig(der_sig) + return sig_string_from_r_and_s(r, s) def der_sig_from_sig_string(sig_string: bytes, order=CURVE_ORDER) -> bytes: - r, s = ecdsa.util.sigdecode_string(sig_string, order) - return ecdsa.util.sigencode_der_canonize(r, s, order) + r, s = get_r_and_s_from_sig_string(sig_string) + return der_sig_from_r_and_s(r, s) def der_sig_from_r_and_s(r: int, s: int, order=CURVE_ORDER) -> bytes: - return ecdsa.util.sigencode_der_canonize(r, s, order) + sig_string = (int.to_bytes(r, length=32, byteorder="big") + + int.to_bytes(s, length=32, byteorder="big")) + sig = create_string_buffer(64) + ret = _libsecp256k1.secp256k1_ecdsa_signature_parse_compact(_libsecp256k1.ctx, sig, sig_string) + if not ret: + raise Exception("Bad signature") + ret = _libsecp256k1.secp256k1_ecdsa_signature_normalize(_libsecp256k1.ctx, sig, sig) + der_sig = create_string_buffer(80) # this much space should be enough + der_sig_size = c_size_t(len(der_sig)) + ret = _libsecp256k1.secp256k1_ecdsa_signature_serialize_der(_libsecp256k1.ctx, der_sig, byref(der_sig_size), sig) + if not ret: + raise Exception("failed to serialize DER sig") + der_sig_size = der_sig_size.value + return bytes(der_sig)[:der_sig_size] def get_r_and_s_from_der_sig(der_sig: bytes, order=CURVE_ORDER) -> Tuple[int, int]: - r, s = ecdsa.util.sigdecode_der(der_sig, order) + assert isinstance(der_sig, bytes) + sig = create_string_buffer(64) + ret = _libsecp256k1.secp256k1_ecdsa_signature_parse_der(_libsecp256k1.ctx, sig, der_sig, len(der_sig)) + if not ret: + raise Exception("Bad signature") + ret = _libsecp256k1.secp256k1_ecdsa_signature_normalize(_libsecp256k1.ctx, sig, sig) + compact_signature = create_string_buffer(64) + _libsecp256k1.secp256k1_ecdsa_signature_serialize_compact(_libsecp256k1.ctx, compact_signature, sig) + r = int.from_bytes(compact_signature[:32], byteorder="big") + s = int.from_bytes(compact_signature[32:], byteorder="big") return r, s def get_r_and_s_from_sig_string(sig_string: bytes, order=CURVE_ORDER) -> Tuple[int, int]: - r, s = ecdsa.util.sigdecode_string(sig_string, order) + if not (isinstance(sig_string, bytes) and len(sig_string) == 64): + raise Exception("sig_string must be bytes, and 64 bytes exactly") + sig = create_string_buffer(64) + ret = _libsecp256k1.secp256k1_ecdsa_signature_parse_compact(_libsecp256k1.ctx, sig, sig_string) + if not ret: + raise Exception("Bad signature") + ret = _libsecp256k1.secp256k1_ecdsa_signature_normalize(_libsecp256k1.ctx, sig, sig) + compact_signature = create_string_buffer(64) + _libsecp256k1.secp256k1_ecdsa_signature_serialize_compact(_libsecp256k1.ctx, compact_signature, sig) + r = int.from_bytes(compact_signature[:32], byteorder="big") + s = int.from_bytes(compact_signature[32:], byteorder="big") return r, s def sig_string_from_r_and_s(r: int, s: int, order=CURVE_ORDER) -> bytes: - return ecdsa.util.sigencode_string_canonize(r, s, order) + sig_string = (int.to_bytes(r, length=32, byteorder="big") + + int.to_bytes(s, length=32, byteorder="big")) + sig = create_string_buffer(64) + ret = _libsecp256k1.secp256k1_ecdsa_signature_parse_compact(_libsecp256k1.ctx, sig, sig_string) + if not ret: + raise Exception("Bad signature") + ret = _libsecp256k1.secp256k1_ecdsa_signature_normalize(_libsecp256k1.ctx, sig, sig) + compact_signature = create_string_buffer(64) + _libsecp256k1.secp256k1_ecdsa_signature_serialize_compact(_libsecp256k1.ctx, compact_signature, sig) + return bytes(compact_signature) def point_to_ser(point, compressed=True) -> Optional[bytes]: # TODO rm? diff --git a/electrum/ecc_fast.py b/electrum/ecc_fast.py index 3fb63b3c1..ee7b3d40a 100644 --- a/electrum/ecc_fast.py +++ b/electrum/ecc_fast.py @@ -79,6 +79,12 @@ def load_library(): secp256k1.secp256k1_ecdsa_signature_serialize_compact.argtypes = [c_void_p, c_char_p, c_char_p] secp256k1.secp256k1_ecdsa_signature_serialize_compact.restype = c_int + secp256k1.secp256k1_ecdsa_signature_parse_der.argtypes = [c_void_p, c_char_p, c_char_p, c_size_t] + secp256k1.secp256k1_ecdsa_signature_parse_der.restype = c_int + + secp256k1.secp256k1_ecdsa_signature_serialize_der.argtypes = [c_void_p, c_char_p, c_void_p, c_char_p] + secp256k1.secp256k1_ecdsa_signature_serialize_der.restype = c_int + secp256k1.secp256k1_ec_pubkey_tweak_mul.argtypes = [c_void_p, c_char_p, c_char_p] secp256k1.secp256k1_ec_pubkey_tweak_mul.restype = c_int