Exemplo n.º 1
0
    def follow_treasure_map(self, hrac, using_dht=False):

        treasure_map = self.treasure_maps[hrac]
        number_of_known_treasure_ursulas = 0
        if not using_dht:
            for ursula_interface_id in treasure_map:
                pubkey = UmbralPublicKey.from_bytes(ursula_interface_id)
                if pubkey in self.known_nodes:
                    number_of_known_treasure_ursulas += 1

            newly_discovered_nodes = {}
            nodes_to_check = iter(self.known_nodes.values())

            while number_of_known_treasure_ursulas < treasure_map.m:
                try:
                    node_to_check = next(nodes_to_check)
                except StopIteration:
                    raise self.NotEnoughUrsulas(
                        "Unable to follow the TreasureMap; we just don't know enough nodes to ask about this.  Maybe try using the DHT instead."
                    )

                new_nodes = self.learn_about_nodes(node_to_check.ip_address,
                                                   node_to_check.rest_port)
                for new_node_pubkey in new_nodes.keys():
                    if new_node_pubkey in treasure_map:
                        number_of_known_treasure_ursulas += 1
                newly_discovered_nodes.update(new_nodes)

            self.known_nodes.update(newly_discovered_nodes)
            return newly_discovered_nodes, number_of_known_treasure_ursulas
        else:
            for ursula_interface_id in self.treasure_maps[hrac]:
                pubkey = UmbralPublicKey.from_bytes(ursula_interface_id)
                if ursula_interface_id in self.known_nodes:
                    # If we already know about this Ursula,
                    # we needn't learn about it again.
                    continue

                if using_dht:
                    # TODO: perform this part concurrently.
                    value = self.server.get_now(ursula_interface_id)

                    # TODO: Make this much prettier
                    header, signature, ursula_pubkey_sig, _hrac, (
                        port, interface,
                        ttl) = dht_value_splitter(value,
                                                  msgpack_remainder=True)

                    if header != constants.BYTESTRING_IS_URSULA_IFACE_INFO:
                        raise TypeError(
                            "Unknown DHT value.  How did this get on the network?"
                        )

                # TODO: If we're going to implement TTL, it will be here.
                self.known_nodes[ursula_interface_id] = \
                    Ursula.as_discovered_on_network(
                        dht_port=port,
                        dht_interface=interface,
                        powers_and_keys=({SigningPower: ursula_pubkey_sig})
                    )
Exemplo n.º 2
0
    def follow_treasure_map(self, hrac):
        for ursula_interface_id in self.treasure_maps[hrac]:
            if ursula_interface_id in self.known_nodes:
                # If we already know about this Ursula,
                # we needn't learn about it again.
                continue

            # TODO: perform this part concurrently.
            value = self.server.get_now(ursula_interface_id)

            # TODO: Make this much prettier
            header, signature, ursula_pubkey_sig, _hrac, (
                port, interface,
                ttl) = dht_value_splitter(value, msgpack_remainder=True)

            if header != constants.BYTESTRING_IS_URSULA_IFACE_INFO:
                raise TypeError(
                    "Unknown DHT value.  How did this get on the network?")

            # TODO: If we're going to implement TTL, it will be here.
            self.known_nodes[ursula_interface_id] = \
                Ursula.as_discovered_on_network(
                    dht_port=port,
                    dht_interface=interface,
                    powers_and_keys=({SigningPower: ursula_pubkey_sig})
                )
Exemplo n.º 3
0
    def get_treasure_map(self, policy_group):

        dht_key = policy_group.treasure_map_dht_key()

        ursula_coro = self.server.get(dht_key)
        event_loop = asyncio.get_event_loop()
        packed_encrypted_treasure_map = event_loop.run_until_complete(
            ursula_coro)

        # TODO: Make this prettier
        header, _signature_for_ursula, pubkey_sig_alice, hrac, encrypted_treasure_map =\
        dht_value_splitter(packed_encrypted_treasure_map, return_remainder=True)
        tmap_messaage_kit = MessageKit.from_bytes(encrypted_treasure_map)

        if header != BYTESTRING_IS_TREASURE_MAP:
            raise TypeError(
                "Unknown DHT value.  How did this get on the network?")

        verified, packed_node_list = self.verify_from(
            self.alice,
            tmap_messaage_kit,
            signature_is_on_cleartext=True,
            decrypt=True)

        if not verified:
            return NOT_FROM_ALICE
        else:
            from nkms.policy.models import TreasureMap
            self.treasure_maps[policy_group.hrac] = TreasureMap(
                msgpack.loads(packed_node_list))
            return self.treasure_maps[policy_group.hrac]
Exemplo n.º 4
0
    def follow_treasure_map(self, hrac):
        for ursula_interface_id in self.treasure_maps[hrac]:
            # TODO: perform this part concurrently.
            getter = self.server.get(ursula_interface_id)
            loop = asyncio.get_event_loop()
            value = loop.run_until_complete(getter)
            signature, ursula_pubkey_sig, hrac, (port, interface, ttl) = dht_value_splitter(value.lstrip(b"uaddr"),
                                                                                            msgpack_remainder=True)

            # TODO: If we're going to implement TTL, it will be here.
            self._ursulas[ursula_interface_id] = Ursula.as_discovered_on_network(port=port, interface=interface,
                                                                                 pubkey_sig_bytes=ursula_pubkey_sig)
Exemplo n.º 5
0
def test_alice_finds_ursula_via_dht(alice, ursulas):
    """
    With the help of any Ursula, Alice can find a specific Ursula.
    """
    ursula_index = 1
    all_ursulas = blockchain_client._ursulas_on_blockchain
    value = alice.server.get_now(all_ursulas[ursula_index])
    header, _signature, _ursula_pubkey_sig, interface_info = dht_value_splitter(
        value, return_remainder=True)

    assert header == constants.BYTESTRING_IS_URSULA_IFACE_INFO
    port = msgpack.loads(interface_info)[1]
    assert port == URSULA_PORT + ursula_index
def test_alice_finds_ursula(alice, ursulas):
    """
    With the help of any Ursula, Alice can find a specific Ursula.
    """
    ursula_index = 1
    all_ursulas = blockchain_client._ursulas_on_blockchain
    getter = alice.server.get(all_ursulas[ursula_index])
    loop = asyncio.get_event_loop()
    value = loop.run_until_complete(getter)
    _signature, _ursula_pubkey_sig, _hrac, interface_info = dht_value_splitter(value.lstrip(b"uaddr-"),
                                                                               return_remainder=True)
    port = msgpack.loads(interface_info)[0]
    assert port == URSULA_PORT + ursula_index
Exemplo n.º 7
0
def test_treaure_map_is_legit(enacted_policy):
    """
    Sure, the TreasureMap can get to Bob, but we also need to know that each Ursula in the TreasureMap is on the network.
    """
    alice = enacted_policy.alice
    for ursula_interface_id in enacted_policy.treasure_map:
        value = alice.server.get_now(ursula_interface_id)
        header, signature, ursula_pubkey_sig, hrac, interface_info = dht_value_splitter(value,
                                                                                return_remainder=True)
        assert header == BYTESTRING_IS_URSULA_IFACE_INFO
        port = msgpack.loads(interface_info)[0]
        legal_ports = range(NUMBER_OF_URSULAS_IN_NETWORK, NUMBER_OF_URSULAS_IN_NETWORK + URSULA_PORT)
        assert port in legal_ports
def test_treaure_map_is_legit(enacted_policy):
    """
    Sure, the TreasureMap can get to Bob, but we also need to know that each Ursula in the TreasureMap is on the network.
    """
    alice = enacted_policy.alice
    for ursula_interface_id in enacted_policy.treasure_map:
        getter = alice.server.get(ursula_interface_id)
        loop = asyncio.get_event_loop()
        value = loop.run_until_complete(getter)
        signature, ursula_pubkey_sig, hrac, interface_info = dht_value_splitter(value.lstrip(b"uaddr-"),
                                                                                return_remainder=True)
        port = msgpack.loads(interface_info)[0]
        legal_ports = range(NUMBER_OF_URSULAS_IN_NETWORK, NUMBER_OF_URSULAS_IN_NETWORK + URSULA_PORT)
        assert port in legal_ports
Exemplo n.º 9
0
    def get_treasure_map_from_known_ursulas(self, networky_stuff, map_id):
        """
        Iterate through swarm, asking for the TreasureMap.
        Return the first one who has it.
        TODO: What if a node gives a bunk TreasureMap?
        """
        from nkms.network.protocols import dht_value_splitter
        for node in self.known_nodes.values():
            response = networky_stuff.get_treasure_map_from_node(node, map_id)

            if response.status_code == 200 and response.content:
                # TODO: Make this prettier
                header, _signature_for_ursula, pubkey_sig_alice, hrac, encrypted_treasure_map = \
                    dht_value_splitter(response.content, return_remainder=True)
                tmap_messaage_kit = MessageKit.from_bytes(encrypted_treasure_map)
                return tmap_messaage_kit
            else:
                assert False
Exemplo n.º 10
0
    def get_treasure_map(self, policy_group):

        dht_key = policy_group.treasure_map_dht_key()

        ursula_coro = self.server.get(dht_key)
        event_loop = asyncio.get_event_loop()
        packed_encrypted_treasure_map = event_loop.run_until_complete(ursula_coro)
        _signature_for_ursula, pubkey_sig_alice, hrac, encrypted_treasure_map = dht_value_splitter(
            packed_encrypted_treasure_map[5::], msgpack_remainder=True)
        verified, cleartext = self.verify_from(self.alice, encrypted_treasure_map,
                                               signature_is_on_cleartext=True, decrypt=True)
        alices_signature, packed_node_list = BytestringSplitter(Signature)(cleartext, return_remainder=True)
        if not verified:
            return NOT_FROM_ALICE
        else:
            from nkms.policy.models import TreasureMap
            self.treasure_maps[policy_group.hrac] = TreasureMap(msgpack.loads(packed_node_list))
            return self.treasure_maps[policy_group.hrac]
def test_treasure_map_stored_by_ursula_is_the_correct_one_for_bob(alice, bob, ursulas, enacted_policy):
    """
    The TreasureMap given by Alice to Ursula is the correct one for Bob; he can decrypt and read it.
    """
    treasure_map_as_set_on_network = ursulas[0].server.storage[
        digest(enacted_policy.treasure_map_dht_key())]

    _signature_for_ursula, pubkey_sig_alice, hrac, encrypted_treasure_map = dht_value_splitter(
        treasure_map_as_set_on_network[5::], msgpack_remainder=True)  # 5:: to account for prepended "trmap"

    verified, cleartext = treasure_map_as_decrypted_by_bob = bob.verify_from(alice,
                                                                 encrypted_treasure_map,
                                                                 decrypt=True,
                                                                 signature_is_on_cleartext=True,
                                                                 )
    _alices_signature, treasure_map_as_decrypted_by_bob = BytestringSplitter(Signature)(cleartext, return_remainder=True)

    assert treasure_map_as_decrypted_by_bob == enacted_policy.treasure_map.packed_payload()
    assert verified is True
Exemplo n.º 12
0
def test_treasure_map_stored_by_ursula_is_the_correct_one_for_bob(alice, bob, ursulas, enacted_policy):
    """
    The TreasureMap given by Alice to Ursula is the correct one for Bob; he can decrypt and read it.
    """
    treasure_map_as_set_on_network = ursulas[0].server.storage[
        digest(enacted_policy.treasure_map_dht_key())]

    header, _signature_for_ursula, pubkey_sig_alice, hrac, encrypted_treasure_map = dht_value_splitter(
        treasure_map_as_set_on_network, return_remainder=True)

    assert header == BYTESTRING_IS_TREASURE_MAP

    tmap_message_kit = MessageKit.from_bytes(encrypted_treasure_map)
    verified, treasure_map_as_decrypted_by_bob = bob.verify_from(alice,
                                           tmap_message_kit,
                                           decrypt=True,
                                           signature_is_on_cleartext=True,
                                           )

    assert treasure_map_as_decrypted_by_bob == enacted_policy.treasure_map.packed_payload()
    assert verified is True
Exemplo n.º 13
0
    def receive_treasure_map(self, treasure_map_id_as_hex,
                             request: http.Request):
        # TODO: This function is the epitome of #172.
        treasure_map_id = binascii.unhexlify(treasure_map_id_as_hex)

        header, signature_for_ursula, pubkey_sig_alice, hrac, tmap_message_kit = \
            dht_value_splitter(request.body, return_remainder=True)
        # TODO: This next line is possibly the worst in the entire codebase at the moment.  #172.
        # Also TODO: TTL?
        do_store = self.server.protocol.determine_legality_of_dht_key(
            signature_for_ursula, pubkey_sig_alice, tmap_message_kit, hrac,
            digest(treasure_map_id), request.body)
        if do_store:
            # TODO: Stop storing things in the protocol storage.  Do this better.
            # TODO: Propagate to other nodes.
            self.server.protocol.storage[digest(
                treasure_map_id)] = request.body
            return  # TODO: Proper response here.
        else:
            # TODO: Make this a proper 500 or whatever.
            assert False
Exemplo n.º 14
0
    def follow_treasure_map(self, hrac):
        for ursula_interface_id in self.treasure_maps[hrac]:
            # TODO: perform this part concurrently.
            value = self.server.get_now(ursula_interface_id)

            # TODO: Make this much prettier
            header, signature, ursula_pubkey_sig, _hrac, (
                port, interface,
                ttl) = dht_value_splitter(value, msgpack_remainder=True)

            if header != BYTESTRING_IS_URSULA_IFACE_INFO:
                raise TypeError(
                    "Unknown DHT value.  How did this get on the network?")

            # TODO: If we're going to implement TTL, it will be here.
            self._ursulas[ursula_interface_id] =\
                    Ursula.as_discovered_on_network(
                            dht_port=port,
                            dht_interface=interface,
                            pubkey_sig_bytes=ursula_pubkey_sig
                    )