def parse_fromwallet(cls, kds, vds): """Class method to parse entry from wallet entry :param kds: BCDatastream object for keys :type kds: BCDataStream :param vds: BCDataStream object for values :type vds: BCDataStream :return: KeyPair :rtype: KeyPair """ pubkeyraw = kds.read_bytes(kds.read_compact_size()) privkeyraw = vds.read_bytes(vds.read_compact_size()) if len(privkeyraw) == 279: sec = privkeyraw[9:41] else: sec = privkeyraw[8:40] privkey = PrivateKey(sec) pubkey = PublicKey(pubkeyraw) if len(pubkeyraw) == 33: compress = True else: compress = False if pubkey == privkey.public_key: pubkey = privkey.public_key.format(compressed=compress) return cls( rawkey=pubkeyraw, rawvalue=privkeyraw, pubkey=pubkey, privkey=privkey, sec=sec, compressed=compress, ) else: raise KeypairError(message="Pubkey {} error".format(pubkey.format(compressed=compress).hex()))
def verify_ecdsa(message, signature, pub): """Checks if the signature from signEcdsa is correct.""" if not isinstance(message, (bytes, bytearray)): raise TypeError(f"Invalid message") if len(message) != 32: raise ValueError(f"Invalid length message: {len(message)} != 32") if not isinstance(signature, (bytes, bytearray)): raise TypeError(f"Invalid signature key") if len(signature) != 65: raise ValueError(f"Invalid length signature key: {len(signature)} != 65") if not isinstance(pub, (bytes, bytearray)): raise TypeError(f"Invalid signature key") if len(pub) != 64: raise ValueError(f"Invalid length signature key: {len(pub)} != 64") pubkey = PublicKey(b"\x04" + pub) r = _big_endian_to_int(signature[0:32]) s = _big_endian_to_int(signature[32:64]) low_s = _coerce_low_s(s) der_encoded_signature = bytes(_two_int_sequence_encoder(r, low_s)) return verify_signature( der_encoded_signature, message, pubkey.format(compressed=False), hasher=None )
def _convert_key(public_key: bytes, compressed: bool) -> bytes: """Convert key between compressed and uncompressed keys :param public_key: compressed or uncompressed key :return: the counterpart key of a given public_key """ public_key_object = PublicKey(public_key) return public_key_object.format(compressed=not compressed)
def from_xpub( xpub: str, xpub_type: Optional[XpubType] = None, path: Optional[str] = None, ) -> 'HDKey': """ Instantiate an HDKey from an xpub. Populates all possible fields Args: xpub (str): the xpub path (str): the path if it's known. useful for calling derive_path Returns: (HDKey): the key object May raise: - XPUBError if there is a problem with decoding the xpub """ xpub_bytes = b58decode(xpub) if len(xpub_bytes) < 78: raise XPUBError(f'Given XPUB {xpub} is too small') try: pubkey = PublicKey(xpub_bytes[45:78]) except ValueError as e: raise XPUBError(str(e)) from e result = _parse_prefix(xpub_bytes[0:4]) if not result.is_public: raise XPUBError('Given xpub is an extended private key') if result.network != 'mainnet': raise XPUBError('Given xpub is not for the bitcoin mainnet') hint = result.hint if xpub_type is not None and xpub_type.matches_prefix( xpub[0:4]) is False: # the given type does not match the prefix, re-encode with correct pref new_xpub = bytearray() new_xpub.extend(xpub_type.prefix_bytes()) new_xpub.extend(xpub_bytes[4:]) new_xpub_bytes = new_xpub hint = xpub_type.prefix() xpub = b58encode(bytes(new_xpub_bytes)).decode('ascii') return HDKey( path=path, network=result.network, depth=xpub_bytes[4], parent_fingerprint=xpub_bytes[5:9], index=int.from_bytes(xpub_bytes[9:13], byteorder='big'), parent=None, chain_code=xpub_bytes[13:45], fingerprint=hash160(pubkey.format(COMPRESSED_PUBKEY))[:4], xpriv=None, xpub=xpub, privkey=None, pubkey=pubkey, hint=hint, )
def verify(self, message): pub = PublicKey(self.pub_key) message = VarInt(len(message)).encode() + message # LOGGER.debug("Comparing with %r" % (MESSAGE_TEMPLATE.format(message).encode())) try: good = pub.verify(self.sig_ser, MESSAGE_TEMPLATE.format(message).encode()) except Exception: LOGGER.exception("Verification failed") good = False return good
def verify(self, message): pub = PublicKey(self.pub_key) message = VarInt(len(message)).encode() + message try: # sig_raw = pub.ecdsa_deserialize(self.sig_ser) good = pub.verify(self.sig_ser, Define.MESSAGE_TEMPLATE % message) except Exception: print("Verification failed") good = False return good
def parse_fromckey(cls, pubkey, privkey, encryptedkey, crypted=True): """Parse keypair from ckey (encrypted) values from wallet :param pubkey: :type pubkey: :param privkey: :type privkey: :param encryptedkey: :type encryptedkey: :param crypted: :type crypted: :return: :rtype: """ pkey = PublicKey(pubkey) if len(pubkey) == 33: compress = True else: compress = False if crypted: return cls( rawkey=pubkey, rawvalue=None, pubkey=pkey.format(compressed=compress), sec=None, encryptedkey=encryptedkey, compressed=compress, ) else: if len(privkey) == 279: sec = privkey[9:41] else: sec = privkey[8:40] prkey = PrivateKey(sec) if pkey == prkey.public_key: pkey = prkey.public_key.format(compressed=compress) return cls( rawkey=pubkey, rawvalue=privkey, pubkey=pkey, privkey=prkey, sec=sec, compressed=compress, ) else: print("Wrong decryption password") return cls( rawkey=pubkey, rawvalue=None, pubkey=pkey, sec=None, encryptedkey=encryptedkey, compressed=compress, )
def verify(self, message): pub = PublicKey(self.pub_key) message = VarInt(len(message)).encode() + message LOGGER.debug("Comparing with %r" % (MESSAGE_TEMPLATE % message)) try: # sig_raw = pub.ecdsa_deserialize(self.sig_ser) good = pub.verify(self.sig_ser, MESSAGE_TEMPLATE % message) except Exception: LOGGER.exception("Verification failed") good = False return good
def obscured_commit_num(opener_payment_basepoint: coincurve.PublicKey, non_opener_payment_basepoint: coincurve.PublicKey, commitnum: int) -> int: # BOLT #3: # The 48-bit commitment number is obscured by `XOR` with the lower 48 bits of: # # SHA256(payment_basepoint from open_channel || payment_basepoint from accept_channel) shabytes = sha256(opener_payment_basepoint.format() + non_opener_payment_basepoint.format()).digest()[-6:] obscurer = struct.unpack('>Q', bytes(2) + shabytes)[0] return commitnum ^ obscurer
def load_keys(teos_pk_path, cli_sk_path, cli_pk_path): """ Loads all the keys required so sign, send, and verify the appointment. Args: teos_pk_path (:obj:`str`): path to the TEOS public key file. cli_sk_path (:obj:`str`): path to the client private key file. cli_pk_path (:obj:`str`): path to the client public key file. Returns: :obj:`tuple` or ``None``: a three item tuple containing a teos_pk object, cli_sk object and the cli_sk_der encoded key if all keys can be loaded. ``None`` otherwise. """ if teos_pk_path is None: logger.error( "TEOS's public key file not found. Please check your settings") return None if cli_sk_path is None: logger.error( "Client's private key file not found. Please check your settings") return None if cli_pk_path is None: logger.error( "Client's public key file not found. Please check your settings") return None try: teos_pk_der = Cryptographer.load_key_file(teos_pk_path) teos_pk = PublicKey(teos_pk_der) except ValueError: logger.error("TEOS public key is invalid or cannot be parsed") return None cli_sk_der = Cryptographer.load_key_file(cli_sk_path) cli_sk = Cryptographer.load_private_key_der(cli_sk_der) if cli_sk is None: logger.error("Client private key is invalid or cannot be parsed") return None try: cli_pk_der = Cryptographer.load_key_file(cli_pk_path) PublicKey(cli_pk_der) except ValueError: logger.error("Client public key is invalid or cannot be parsed") return None return teos_pk, cli_sk, cli_pk_der
def verify_hash(message, signature, public_key): if not isinstance(signature, bytes): raise TypeError("signature must be bytes") if not isinstance(public_key, bytes): raise TypeError("public_key must be bytes") pub_key = PublicKey(public_key) try: is_verified = pub_key.verify(signature, message) except ValueError as e: logger.error(str(e)) logger.error("Signature that could not be parsed %s, message: %s", signature, message) return False return is_verified
def sort_by_keys(key_one: coincurve.PublicKey, key_two: coincurve.PublicKey, val_one: Any, val_two: Any) -> Tuple[Any, Any]: """In many places we have to sort elements into key or nodeid order""" # BOLT #3: # ## Funding Transaction Output # # * The funding output script is a P2WSH to: `2 <pubkey1> <pubkey2> 2 # OP_CHECKMULTISIG` # * Where `pubkey1` is the lexicographically lesser of the two # `funding_pubkey` in compressed format, and where `pubkey2` is the # lexicographically greater of the two. if key_one.format() < key_two.format(): return val_one, val_two else: return val_two, val_one
def hex2pub(pub_hex: str) -> PublicKey: """ Convert ethereum hex to EllipticCurvePublicKey The hex should be 65 bytes, but ethereum public key only has 64 bytes So have to add \x04 Parameters ---------- pub_hex: str Ethereum public key hex string Returns ------- coincurve.PublicKey A secp256k1 public key calculated from ethereum public key hex string >>> data = b'0'*32 >>> data_hash = sha256(data) >>> eth_prv = generate_eth_key() >>> cc_prv = hex2prv(eth_prv.to_hex()) >>> eth_prv.sign_msg_hash(data_hash).to_bytes() == cc_prv.sign_recoverable(data) True >>> pubhex = eth_prv.public_key.to_hex() >>> computed_pub = hex2pub(pubhex) >>> computed_pub == cc_prv.public_key True """ uncompressed = decode_hex(pub_hex) if len(uncompressed) == 64: uncompressed = b"\x04" + uncompressed return PublicKey(uncompressed)
def derive(private_key: PrivateKey, peer_public_key: PublicKey) -> bytes: """ Key exchange between private key and peer's public key, `derive(k1, k2.public_key)` should be equal to `derive(k2, k1.public_key)`. Parameters ---------- private_key: coincurve.PrivateKey A secp256k1 private key peer_public_key: coincurve.PublicKey Peer's public key Returns ------- bytes A secret key used for symmetric encryption >>> from coincurve import PrivateKey >>> ke1 = generate_eth_key() >>> ke2 = generate_eth_key() >>> k1 = hex2prv(ke1.to_hex()) >>> k2 = hex2prv(ke2.to_hex()) >>> derive(k1, k2.public_key) == derive(k2, k1.public_key) True """ return private_key.ecdh(peer_public_key.format())
def recover_pubkey_from_signature(message: bytes, signature: Union[bytes, Signature], v_value_to_try: int, is_prehashed: bool = False) -> bytes: """ Recovers a serialized, compressed public key from a signature. It allows to specify a potential v value, in which case it assumes the signature has the traditional (r,s) raw format. If a v value is not present, it assumes the signature has the recoverable format (r, s, v). :param message: Signed message :param signature: The signature from which the pubkey is recovered :param v_value_to_try: A potential v value to try :param is_prehashed: True if the message is already pre-hashed. Default is False, and message will be hashed with SHA256 :return: The compressed byte-serialized representation of the recovered public key """ signature = bytes(signature) expected_signature_size = Signature.expected_bytes_length() if not len(signature) == expected_signature_size: raise ValueError( f"The signature size should be {expected_signature_size} B.") if v_value_to_try in (0, 1, 27, 28): if v_value_to_try >= 27: v_value_to_try -= 27 signature = signature + v_value_to_try.to_bytes(1, 'big') else: raise ValueError("Wrong v value. It should be 0, 1, 27 or 28.") kwargs = dict(hasher=None) if is_prehashed else {} pubkey = PublicKey.from_signature_and_message(serialized_sig=signature, message=message, **kwargs) return pubkey.format(compressed=True)
def update_fee(self, channel_id: ChannelId, new_fee: bytes, signature: bytes): """ Update the channel with a new fee. New_fee bytes are of the form '0.0012'.encode()""" # Fixme: I need a nonce for replay protection msg = new_fee signer = public_key_to_address( PublicKey.from_signature_and_message(signature, msg, hasher=sha256)) participant1, participant2 = self.channel_id_to_addresses[channel_id] if is_same_address(participant1, signer): sender = participant1 receiver = participant2 elif is_same_address(participant2, signer): sender = participant2 receiver = participant1 else: raise ValueError( 'Signature does not match any of the participants.') new_fee = float(new_fee) channel_view = self.G[sender][receiver]['view'] if new_fee >= self.max_fee: # Equal case is included to avoid a recalculation of the max fee. self.max_fee = new_fee channel_view.fee = new_fee elif channel_view.fee == self.max_fee: # O(n) operation but rarely called, amortized likely constant. channel_view.fee = new_fee self.max_fee = max(edge_data['view'].fee for _, _, edge_data in self.G.edges(data=True)) channel_view.fee = new_fee
def test_get_address(): raw_key = bytes.fromhex( '04fb0af727d1839557ea5214a7b7dd799c05dab9da63329a6c6d9836fd19a29ce' 'bc34f7ba31877b22f6767bb1d9f376a33fc0f28f37ada368611b011c01dbef90f' ) pubkey = PublicKey(raw_key) assert '0x80e0b0a7cc8001086a37648f993b2bd855d0ab59' == get_address(pubkey)
async def verify_signature(message): """Verifies a signature of a message, return True if verified, false if not""" try: chain_id, hrp = await get_chain_info(message["sender"]) except Exception: LOGGER.exception("Avalanche sender address deserialization error") return False try: signature = base58.b58decode(message["signature"]) signature, status = await validate_checksum(signature) if not status: LOGGER.exception("Avalanche signature checksum error") return False except Exception: LOGGER.exception("Solana signature deserialization error") return False try: verification = await get_verification_buffer(message) verification = await pack_message(verification) public_key = PublicKey.from_signature_and_message(signature, verification) address = await address_from_public_key(public_key.format()) address = await address_to_string(chain_id, hrp, address) result = address == message["sender"] except Exception as e: LOGGER.exception("Error processing signature for %s" % message["sender"]) result = False return result
def get_signature_recovery_value(message: bytes, signature: Union[bytes, Signature], public_key: Union[bytes, UmbralPublicKey], is_prehashed: bool = False) -> bytes: """ Obtains the recovery value of a standard ECDSA signature. :param message: Signed message :param signature: The signature from which the pubkey is recovered :param public_key: The public key for verifying the signature :param is_prehashed: True if the message is already pre-hashed. Default is False, and message will be hashed with SHA256 :return: The compressed byte-serialized representation of the recovered public key """ signature = bytes(signature) ecdsa_signature_size = Signature.expected_bytes_length() if len(signature) != ecdsa_signature_size: raise ValueError( f"The signature size should be {ecdsa_signature_size} B.") kwargs = dict(hasher=None) if is_prehashed else {} for v in (0, 1): v_byte = bytes([v]) recovered_pubkey = PublicKey.from_signature_and_message( serialized_sig=signature + v_byte, message=message, **kwargs) if bytes(public_key) == recovered_pubkey.format(compressed=True): return v_byte else: raise ValueError( "Signature recovery failed. " "Either the message, the signature or the public key is not correct" )
def getPubkey(new_prvkey, flag_compress): if flag_gmpy2: Ptmp = mul_ka(new_prvkey) Xcoord = Ptmp.x Ycoord = Ptmp.y elif flag_coincurve: Ptmp = PublicKey.from_valid_secret(int_to_bytes_padded(new_prvkey)) if flag_cffi: tmp_pubkey = ffi.buffer(Ptmp.public_key, 64)[:] Xcoord = bytes_to_int(tmp_pubkey[31::-1]) Ycoord = bytes_to_int(tmp_pubkey[:31:-1]) else: Xcoord, Ycoord = Ptmp.point() else: Ptmp = mul_ka(new_prvkey) Xcoord = Ptmp.x Ycoord = Ptmp.y if flag_compress: if (Ycoord % 2) == 0: new_pubkey = '02%064x' % int(hex(Xcoord)[2:66], 16) else: new_pubkey = '03%064x' % int(hex(Xcoord)[2:66], 16) else: new_pubkey = '04%064x%064x' % (int(hex(Xcoord)[2:66], 16), int(hex(Ycoord)[2:66], 16)) return new_pubkey
def generate(): gen = {} gen["private_key"] = keccak_256(token_bytes(32)).digest() gen["public_key"] = PublicKey.from_valid_secret( gen["private_key"]).format(compressed=False)[1:] gen["address"] = keccak_256(gen["public_key"]).digest()[-20:] return gen
def generate(clan_tag): try: _ = int(clan_tag, 16) except ValueError: print(f'Error: "{clan_tag}" is not valid hex.') exit(1) n = len(clan_tag) while True: # Generate a private key p_hash_obj = keccak.new(digest_bits=256) seed = secrets.token_bytes(32) p_hash_obj.update(seed) p = p_hash_obj.digest() # Derive the public key q = PublicKey.from_valid_secret(p).format(compressed=False)[1:] # Hash public key into account address addr_hash_obj = keccak.new(digest_bits=256) addr_hash_obj.update(q) address = addr_hash_obj.digest()[-20:] if address.hex()[-n:] == clan_tag: print('Seed : ' + seed.hex()) print('Private key: ' + p_hash_obj.hexdigest()) print('Public key : ' + q.hex()) print('Address : ' + address.hex()) print('Never share the seed or private key with anyone!') print('Never share the seed or private key with anyone!') print('Never share the seed or private key with anyone!') break
def generate(cls, xprv=None, prv=None, seed=None, child=None, username=None): mnemonic = Mnemonic('english') # generate 12 word mnemonic seed if not seed and not xprv and not prv: seed = mnemonic.generate(256) private_key = None if seed: # create bitcoin wallet entropy = mnemonic.to_entropy(seed) key = BIP32Key.fromEntropy(entropy) private_key = key.PrivateKey().hex() extended_key = key.ExtendedKey() else: raise Exception('No Seed') if prv: private_key = PrivateKey.from_hex(bytes.fromhex(prv)).to_hex() extended_key = '' if xprv: key = BIP32Key.fromExtendedKey(xprv) private_key = key.PrivateKey().hex() extended_key = key.ExtendedKey() if xprv and child: for x in child: key = key.ChildKey(int(x)) private_key = key.PrivateKey().hex() if not private_key: raise Exception('No key') return cls({ "seed": seed or '', "xprv": extended_key or '', "private_key": private_key, "wif": cls.generate_wif(private_key), "public_key": PublicKey.from_point(key.K.pubkey.point.x(), key.K.pubkey.point.y()).format().hex(), "address": str(key.Address()), "serve_host": "0.0.0.0", "serve_port": 8000, "use_pnp": True, "ssl": False, "origin": '', "polling": 0, "post_peer": False, # "public_ip": "", # TODO "peer_host": "", "peer_port": 8000, "web_server_host": "0.0.0.0", "web_server_port": 5000, "peer": "http://localhost:8000", "callbackurl": "http://0.0.0.0:5000/create-relationship", "fcm_key": "", "database": "yadacoin", "site_database": "yadacoinsite", "mongodb_host": "localhost", "mixpanel": "", "username": username or '', "network": "mainnet" })
def from_signature_and_message(sig_msg_str, msg_str): from coincurve import PublicKey pk = PublicKey.from_signature_and_message( bytes(bytearray.fromhex(sig_msg_str)), bytes(bytearray.fromhex(msg_str)), hasher=None) return pk.format(compressed=False).hex()
def load_teos_id(teos_pk_path): """ Loads the tower id from disk. Args: teos_pk_path (:obj:`str`): path to the tower's public key file. Returns: :obj:`str`: The tower id. Raises: :obj:`InvalidKey`: if the public key is invalid or cannot be loaded. """ if not teos_pk_path: raise InvalidKey( "TEOS's public key file not found. Have you registered with the tower?" ) try: teos_id = Cryptographer.get_compressed_pk( PublicKey(Cryptographer.load_key_file(teos_pk_path))) except (InvalidParameter, InvalidKey, ValueError): raise InvalidKey( "TEOS public key cannot be loaded. Try registering again") return teos_id
def _recover_key(msg_hash: bytes, signature: bytes, compressed: bool) -> Optional[bytes]: if isinstance(msg_hash, bytes) \ and len(msg_hash) == 32 \ and isinstance(signature, bytes) \ and len(signature) == 65: return PublicKey.from_signature_and_message(signature, msg_hash, hasher=None).format(compressed) return None
def test_sign(): msg = b'32' * 16 assert len(msg) == 32 sig = sign(SENDER_PRIVATE_KEY, msg) pubkey = PublicKey.from_signature_and_message(sig, msg, hasher=None) pubkey = pubkey.format(compressed=False) assert len(sig) == 65 assert is_same_address(pubkey_to_addr(pubkey), SENDER_ADDR)
def gen_keys(mnemonic): w = Wallet(mnemonic) sk, opk = w.derive_account("eth", account=0) sk = PrivateKey(sk) pk = PublicKey(opk) return sk, pk, opk
def generate_wallet(): """ simple function to generate a wallet address """ private_key = keccak_256(token_bytes(32)).digest() public_key = PublicKey.from_valid_secret(private_key).format(compressed=False)[1:] addr = keccak_256(public_key).digest()[-20:] return [private_key, public_key, addr]
def test_encode_public(self): secretkey = PrivateKey(secret=b16decode(self.secret_2)) publickey = PublicKey.from_secret(secretkey.secret) self.assertEqual(self.public_address, integrity.compute_public_address(publickey)) self.assertEqual(self.public_digest, b16encode(integrity.public_digest(publickey)))
def recover_publickey(messagedata, signature, hasher=sha3): if len(signature) != 65: raise ValueError('invalid signature') signature = signature[:-1] + chr(signature[-1] - 27).encode() publickey = PublicKey.from_signature_and_message( signature, messagedata, hasher=hasher, ) return publickey.format(compressed=False)
def addr_from_sig(sig: bytes, msg: bytes): assert len(sig) == 65 # Support Ethereum's EC v value of 27 and EIP 155 values of > 35. if sig[-1] >= 35: network_id = (sig[-1] - 35) // 2 sig = sig[:-1] + bytes([sig[-1] - 35 - 2 * network_id]) elif sig[-1] >= 27: sig = sig[:-1] + bytes([sig[-1] - 27]) receiver_pubkey = PublicKey.from_signature_and_message(sig, msg, hasher=None) return pubkey_to_addr(receiver_pubkey)