Пример #1
0
 def _parse_initial_node_table(initial_node_table: bfcp_pb2.NodeTable)\
         -> Dict[bytes, bfcp_pb2.NodeTableEntry]:
     result = RandomDict()
     for entry in initial_node_table.entries:
         pub_key = proto_to_pubkey(entry.node.public_key)
         result[pubkey_to_deterministic_string(pub_key)] = entry
     return result
Пример #2
0
    async def on_end_node_found(self, conn_resp: bfcp_pb2.ConnectionResponse):
        if self._tcp_state is not None:
            return

        # Verify the challenge
        end_node_key = proto_to_pubkey(conn_resp.selected_end_node.public_key)
        pkcs1_15.new(end_node_key).verify(
            SHA256.new(self._challenge_bytes),
            conn_resp.signature_challenge_response)

        rsa_cipher = PKCS1_OAEP.new(self._sender_connection_key)
        self._session_key = rsa_cipher.decrypt(conn_resp.session_key.key)

        # Start the TCP channel
        self._tcp_state = BouncyTcpTrafficHandler(self._session_key)

        # Found an EN, now try to establish channels
        for i in range(GLOBAL_VARS['CHANNELS_PER_CONNECTION']):
            channel_uuid = str(uuid4())
            channel_request = bfcp_pb2.ChannelRequest()
            channel_request.end_node.CopyFrom(conn_resp.selected_end_node)
            channel_request.channel_uuid = channel_uuid
            channel_request.connection_params.uuid = self.uuid
            channel_request.connection_params.remaining_hops = self._make_channel_length(
            )

            await self._traffic_manager.send(channel_request)
Пример #3
0
    async def on_channel_request(self, msg: bfcp_pb2.ChannelRequest,
                                 sender_key: RsaKey):
        channel_id = bfcp_pb2.ChannelID()
        channel_id.connection_uuid = msg.connection_params.uuid
        channel_id.channel_uuid = msg.channel_uuid

        channel_type = self._check_channel_type(channel_id)
        print('OnChannelRequest', channel_type)
        if channel_type == ConnectionType.end:
            # I am the end node
            self._en_conn[msg.connection_params.uuid][1].append(
                (msg.channel_uuid, sender_key))
            response = bfcp_pb2.ChannelResponse()
            response.channel_id.CopyFrom(channel_id)
            await self._traffic_manager.send(response, sender_key)
        else:
            msg.connection_params.remaining_hops -= 1
            next_node = self._trust_table.get_random_node().node \
                if msg.connection_params.remaining_hops > 0 else msg.end_node
            if channel_type == ConnectionType.neither:
                # This is a new ChannelRequest, forward it
                self._relay_channels[((channel_id.connection_uuid,
                                       channel_id.channel_uuid))] = (
                                           sender_key,
                                           proto_to_pubkey(
                                               next_node.public_key))
            elif channel_type == ConnectionType.relay:
                # This request was here already. Remove the cycle
                (prev_node,
                 _) = self._relay_channels[(channel_id.connection_uuid,
                                            channel_id.channel_uuid)]
                self._relay_channels[(channel_id.connection_uuid,
                                      channel_id.channel_uuid)] = (
                                          prev_node,
                                          proto_to_pubkey(
                                              next_node.public_key))
            else:
                # This is the original sender, no relaying needed
                pass
            await self._traffic_manager.send(
                msg, proto_to_pubkey(next_node.public_key))
Пример #4
0
    async def _become_end_node(self, conn_request: bfcp_pb2.ConnectionRequest,
                               sender_key: RsaKey):
        """
        Respond to a ConnectionRequest, saying that "I'll be the end node". And prepare to be one.
        """
        # solve the challenge
        h = SHA256.new(conn_request.signature_challenge)
        solved_challenge = pkcs1_15.new(self._bfc_node.rsa_key).sign(h)

        conn_resp = bfcp_pb2.ConnectionResponse()
        conn_resp.uuid = conn_request.connection_params.uuid
        conn_resp.selected_end_node.public_key.CopyFrom(
            pubkey_to_proto(self._bfc_node.rsa_key.publickey()))
        conn_resp.selected_end_node.last_known_address = self._bfc_node.host[0]
        conn_resp.selected_end_node.last_port = self._bfc_node.host[1]

        conn_resp.signature_challenge_response = solved_challenge

        # Prepare the session key
        session_key = utils.generate_aes_key(GLOBAL_VARS['OS_EN_KEY_SIZE'])

        original_sender_pub_key = proto_to_pubkey(
            conn_request.sender_connection_key)
        cipher_rsa = PKCS1_OAEP.new(original_sender_pub_key)
        encrypted_session_key = cipher_rsa.encrypt(session_key)
        conn_resp.session_key.key = encrypted_session_key

        # TODO: prev hops and en_conn are bound. This is quite nasty and hard to read.
        prev_hops = []
        en_conn = EndNodeConnection(self._traffic_manager,
                                    conn_request.connection_params.uuid,
                                    prev_hops, session_key)
        self._en_conn[conn_request.connection_params.uuid] = (en_conn,
                                                              prev_hops)
        await self._traffic_manager.send(conn_resp, sender_key)
        ensure_future(
            en_conn.initiate_connection((conn_request.target_server_address,
                                         conn_request.target_server_port)))
Пример #5
0
 def test_pub_key_encoding(self):
     key = RSA.generate(1024).publickey()
     self.assertEqual(protocol.proto_to_pubkey(protocol.pubkey_to_proto(key)), key)