def _key_exchange(serialized_remote_public_key: bytes) -> bytes: private_key = cast(ECCPrivateKey, key_pair.private_key) remote_point = ECCPublicKey.from_bytes(serialized_remote_public_key, curve_type) secret_point = remote_point.impl * private_key.impl secret_x_coordinate = secret_point.x byte_size = int_bytelen(secret_x_coordinate) return secret_x_coordinate.to_bytes(byte_size, byteorder="big")
async def _establish_session_parameters( local_peer: PeerID, local_private_key: PrivateKey, remote_peer: Optional[PeerID], conn: MsgIOReadWriter, nonce: bytes, ) -> Tuple[SessionParameters, bytes]: # establish shared encryption parameters session_parameters = SessionParameters() session_parameters.local_peer = local_peer local_encryption_parameters = EncryptionParameters() session_parameters.local_encryption_parameters = local_encryption_parameters local_public_key = local_private_key.get_public_key() local_encryption_parameters.permanent_public_key = local_public_key local_proposal = Proposal(nonce, local_public_key) serialized_local_proposal = local_proposal.serialize() serialized_remote_proposal = await _response_to_msg( conn, serialized_local_proposal) remote_encryption_parameters = EncryptionParameters() session_parameters.remote_encryption_parameters = remote_encryption_parameters remote_proposal = Proposal.deserialize(serialized_remote_proposal) remote_encryption_parameters.permanent_public_key = remote_proposal.public_key remote_peer_from_proposal = remote_proposal.calculate_peer_id() if not remote_peer: remote_peer = remote_peer_from_proposal elif remote_peer != remote_peer_from_proposal: raise PeerMismatchException({ "expected_remote_peer": remote_peer, "received_remote_peer": remote_peer_from_proposal, }) session_parameters.remote_peer = remote_peer curve_param, cipher_param, hash_param, order = _select_encryption_parameters( local_proposal, remote_proposal) local_encryption_parameters.curve_type = curve_param local_encryption_parameters.cipher_type = cipher_param local_encryption_parameters.hash_type = hash_param remote_encryption_parameters.curve_type = curve_param remote_encryption_parameters.cipher_type = cipher_param remote_encryption_parameters.hash_type = hash_param session_parameters.order = order # exchange ephemeral pub keys local_ephemeral_public_key, shared_key_generator = create_ephemeral_key_pair( curve_param) local_encryption_parameters.ephemeral_public_key = local_ephemeral_public_key local_selection = (serialized_local_proposal + serialized_remote_proposal + local_ephemeral_public_key.to_bytes()) exchange_signature = local_private_key.sign(local_selection) local_exchange = Exchange( ephemeral_public_key=local_ephemeral_public_key.to_bytes(), signature=exchange_signature, ) serialized_local_exchange = local_exchange.SerializeToString() serialized_remote_exchange = await _response_to_msg( conn, serialized_local_exchange) remote_exchange = Exchange() remote_exchange.ParseFromString(serialized_remote_exchange) remote_ephemeral_public_key_bytes = remote_exchange.ephemeral_public_key remote_ephemeral_public_key = ECCPublicKey.from_bytes( remote_ephemeral_public_key_bytes, curve_param) remote_encryption_parameters.ephemeral_public_key = remote_ephemeral_public_key remote_selection = (serialized_remote_proposal + serialized_local_proposal + remote_ephemeral_public_key_bytes) valid_signature = remote_encryption_parameters.permanent_public_key.verify( remote_selection, remote_exchange.signature) if not valid_signature: raise InvalidSignatureOnExchange() shared_key = shared_key_generator(remote_ephemeral_public_key_bytes) session_parameters.shared_key = shared_key return session_parameters, remote_proposal.nonce