def verify_message_with_address(address: str, sig65: bytes, message: bytes, *, net=None): from electroncash.bitcoin import pubkey_to_address assert_bytes(sig65, message) if net is None: net = constants.net try: h = Hash(msg_magic(message)) public_key, compressed = ECPubkey.from_signature65(sig65, h) # check public key using the address pubkey_hex = public_key.get_public_key_hex(compressed) for txin_type in ['p2pkh', 'p2wpkh', 'p2wpkh-p2sh']: addr = pubkey_to_address(txin_type, pubkey_hex, net=net) if address == addr: break else: raise Exception("Bad signature") # check message public_key.verify_message_hash(sig65[1:], h) return True except Exception as e: print_error(f"Verification error: {repr(e)}") return False
def __init__(self, b: bytes): if b is not None: assert_bytes(b) point = _ser_to_python_ecdsa_point(b) self._pubkey = ecdsa.ecdsa.Public_key(generator_secp256k1, point) else: self._pubkey = _PubkeyForPointAtInfinity()
def verify_message_for_address(self, sig65: bytes, message: bytes) -> None: assert_bytes(message) h = Hash(msg_magic(message)) public_key, compressed = self.from_signature65(sig65, h) # check public key if public_key != self: raise Exception("Bad signature") # check message self.verify_message_hash(sig65[1:], h)
def verify_message_hash(self, sig_string: bytes, msg_hash: bytes) -> None: assert_bytes(sig_string) if len(sig_string) != 64: raise Exception('Wrong encoding') ecdsa_point = self._pubkey.point verifying_key = _MyVerifyingKey.from_public_point(ecdsa_point, curve=SECP256k1) verifying_key.verify_digest(sig_string, msg_hash, sigdecode=ecdsa.util.sigdecode_string)
def from_sig_string(cls, sig_string: bytes, recid: int, msg_hash: bytes): assert_bytes(sig_string) if len(sig_string) != 64: raise Exception('Wrong encoding') if recid < 0 or recid > 3: raise ValueError( 'recid is {}, but should be 0 <= recid <= 3'.format(recid)) ecdsa_verifying_key = _MyVerifyingKey.from_signature(sig_string, recid, msg_hash, curve=SECP256k1) ecdsa_point = ecdsa_verifying_key.pubkey.point return ECPubkey.from_point(ecdsa_point)
def __init__(self, privkey_bytes: bytes): assert_bytes(privkey_bytes) if len(privkey_bytes) != 32: raise Exception( 'unexpected size for secret. should be 32 bytes, not {}'. format(len(privkey_bytes))) secret = string_to_number(privkey_bytes) if not is_secret_within_curve_range(secret): raise InvalidECPointException( 'Invalid secret scalar (not within curve order)') self.secret_scalar = secret point = generator_secp256k1 * secret super().__init__(point_to_ser(point)) self._privkey = ecdsa.ecdsa.Private_key(self._pubkey, secret)
def encrypt_message(self, message: bytes, magic: bytes = b'BIE1'): """ ECIES encryption/decryption methods; AES-128-CBC with PKCS7 is used as the cipher; hmac-sha256 is used as the mac """ assert_bytes(message) randint = ecdsa.util.randrange(CURVE_ORDER) ephemeral_exponent = number_to_string(randint, CURVE_ORDER) ephemeral = ECPrivkey(ephemeral_exponent) ecdh_key = (self * ephemeral.secret_scalar).get_public_key_bytes( compressed=True) key = hashlib.sha512(ecdh_key).digest() iv, key_e, key_m = key[0:16], key[16:32], key[32:] ciphertext = aes_encrypt_with_iv(key_e, iv, message) ephemeral_pubkey = ephemeral.get_public_key_bytes(compressed=True) encrypted = magic + ephemeral_pubkey + ciphertext mac = hmac_oneshot(key_m, encrypted, hashlib.sha256) return base64.b64encode(encrypted + mac)