示例#1
0
    def test_validate_authorization(self):
        Crypto.check_signature = Mock(return_value=True)
        value = Mock()
        value.data = 'data'
        value.authorization.sign = 'sign'
        value.authorization.pub_key.exp_time = None
        value.authorization.pub_key.key = 'key'
        value.persist_mode = PersistMode.SECURED
        dkey = hashlib.sha1('key'.encode('utf8')).digest()
        dval = digest(dkey.hex() + value.data +
                      str(value.authorization.pub_key.exp_time) +
                      str(value.persist_mode))
        validate_authorization(dkey, value)
        Crypto.check_signature.assert_called_with(dval, 'sign', 'key')

        value.authorization.pub_key.exp_time = 6
        dval = digest(dkey.hex() + value.data +
                      str(value.authorization.pub_key.exp_time) +
                      str(value.persist_mode))
        validate_authorization(dkey, value)
        Crypto.check_signature.assert_called_with(dval, 'sign', 'key')

        value.authorization.pub_key.exp_time = 4
        with self.assertRaises(AssertionError):
            validate_authorization(
                hashlib.sha1('key'.encode('utf8')).digest(), value)

        value.authorization.pub_key.exp_time = 6
        Crypto.check_signature = Mock(return_value=False)
        with self.assertRaises(InvalidSignException):
            validate_authorization(
                hashlib.sha1('key'.encode('utf8')).digest(), value)
示例#2
0
    def __init__(self,
                 ksize=20,
                 alpha=3,
                 node_id=None,
                 storage=None,
                 discovery_mode='neighborhood',
                 loop=None,
                 max_peers=64,
                 dht=None):
        """
        Create a server instance.  This will start listening on the given port.

        Args:
            ksize (int): The k parameter from the paper
            alpha (int): The alpha parameter from the paper
            node_id: The id for this node on the network.
            storage: An instance that implements
                     :interface:`~kademlia.storage.IStorage`
        """
        self.loop = loop if loop else asyncio.get_event_loop()
        asyncio.set_event_loop(self.loop)
        self.ksize = ksize
        self.alpha = alpha
        self.port = os.getenv('NETWORK_PORT', 5678)
        self.storage = storage or ForgetfulStorage()
        self.node = Node(digest(node_id) or digest(random.getrandbits(255)))
        self.dht = dht
        self.transport = None
        self.protocol = None
        self.refresh_loop = None
        self.save_state_loop = None
        self.max_peers = max_peers
        self.setup_stethoscope()
示例#3
0
    def turn_evil(self, evilPort):
        old_ping = self.rpc_ping
        old_find_node = self.rpc_find_node
        old_find_value = self.rpc_find_value
        self.router.node.port = evilPort;
        if self.evilType == "poison":
            self.rpc_find_node = self.poison_rpc_find_node
            self.rpc_find_value = self.poison_rpc_find_value
            self.false_neighbour_list = []
            for i in range(0, 30):
                fakeid = hashlib.sha1(str(random.getrandbits(255))).digest()
                fake_neighbour = [fakeid,
                                 '10.0.0.9',
                                 self.router.node.port]
                self.false_neighbour_list.append(fake_neighbour)
            _log.debug("Node with port {} prepared to execute "
                       "poisoning attack".format(self.router.node.port))
        elif self.evilType == "insert":
            self.rpc_find_node = self.sybil_rpc_find_node
            self.rpc_find_value = self.poison_rpc_find_value
            ends = bytearray([0x01, 0x02, 0x03])
            self.false_neighbour_list = []
            for i in range(0, 9):
                if i < 3:
                    key = digest("APA")
                elif i > 5:
                    key = digest("KANIN")
                else:
                    key = digest("KOALA")
                key = key[:-1] + bytes(ends[i % 3])
                self.false_neighbour_list.append((key,
                                                 '10.0.0.9',
                                                 self.router.node.port))
            _log.debug("Node with port {} prepared to execute node "
                       "insertion attack".format(self.router.node.port))
        elif self.evilType == "eclipse":
            self.rpc_find_node = self.eclipse_rpc_find_node
            self.rpc_find_value = self.eclipse_rpc_find_value
            self.closest_neighbour = map(list,
                                        self.router.findNeighbors((self.router.node)))
            self.false_neighbour_list = []
            for i in range(0, 10):
                fakeid = hashlib.sha1(str(random.getrandbits(255))).digest()

                self.false_neighbour_list.append((fakeid,
                                                 '10.0.0.9',
                                                 self.router.node.port))
            _log.debug("Node with port {} prepared to execute eclipse "
                       "attack on {}".format(self.router.node.port,
                                            self.closest_neighbour[0][2]))
        elif self.evilType == "sybil":
            self.rpc_find_node = self.sybil_rpc_find_node
            self.rpc_find_value = self.poison_rpc_find_value
            self.false_neighbour_list = []
            for i in range(0, 30):
                fakeid = [hashlib.sha1(str(random.getrandbits(255))).digest()]
                fake_neighbour = [fakeid, '10.0.0.9', self.router.node.port]
                self.false_neighbour_list.append(fake_neighbour)
            _log.debug("Node with port {} prepared to execute "
                       "Sybil attack".format(self.router.node.port))
示例#4
0
    def test_check_signature(self):
        """
        check_signature should validate signature
        """
        public_key = '0224d2079e86e937224f08aa37a857ca6116546868edde549d0bd6b8536af9d554'
        tcs_sig = '749625f8d70efae75ffd4a62e22c6534b2cbaa49212c454e6cfb7c5215e39ef01d0388999b2d38a24ad379245e1b4c69b9259b1c8c86bb011712999b4565192d'
        value = digest('some_key').hex() + 'some_data' + str(None) + str(PersistMode.SECURED)

        self.assertTrue(self.crypto.check_signature(digest(value), tcs_sig, public_key))
    def turn_evil(self, evilPort):
        old_ping = self.rpc_ping
        old_find_node = self.rpc_find_node
        old_find_value = self.rpc_find_value
        self.router.node.port = evilPort
        if self.evilType == "poison":
            self.rpc_find_node = self.poison_rpc_find_node
            self.rpc_find_value = self.poison_rpc_find_value
            self.false_neighbour_list = []
            for i in range(0, 30):
                fakeid = hashlib.sha1(str(random.getrandbits(255))).digest()
                fake_neighbour = [fakeid, '10.0.0.9', self.router.node.port]
                self.false_neighbour_list.append(fake_neighbour)
            _log.debug("Node with port {} prepared to execute "
                       "poisoning attack".format(self.router.node.port))
        elif self.evilType == "insert":
            self.rpc_find_node = self.sybil_rpc_find_node
            self.rpc_find_value = self.poison_rpc_find_value
            ends = bytearray([0x01, 0x02, 0x03])
            self.false_neighbour_list = []
            for i in range(0, 9):
                if i < 3:
                    key = digest("APA")
                elif i > 5:
                    key = digest("KANIN")
                else:
                    key = digest("KOALA")
                key = key[:-1] + bytes(ends[i % 3])
                self.false_neighbour_list.append(
                    (key, '10.0.0.9', self.router.node.port))
            _log.debug("Node with port {} prepared to execute node "
                       "insertion attack".format(self.router.node.port))
        elif self.evilType == "eclipse":
            self.rpc_find_node = self.eclipse_rpc_find_node
            self.rpc_find_value = self.eclipse_rpc_find_value
            self.closest_neighbour = map(
                list, self.router.findNeighbors((self.router.node)))
            self.false_neighbour_list = []
            for i in range(0, 10):
                fakeid = hashlib.sha1(str(random.getrandbits(255))).digest()

                self.false_neighbour_list.append(
                    (fakeid, '10.0.0.9', self.router.node.port))
            _log.debug("Node with port {} prepared to execute eclipse "
                       "attack on {}".format(self.router.node.port,
                                             self.closest_neighbour[0][2]))
        elif self.evilType == "sybil":
            self.rpc_find_node = self.sybil_rpc_find_node
            self.rpc_find_value = self.poison_rpc_find_value
            self.false_neighbour_list = []
            for i in range(0, 30):
                fakeid = [hashlib.sha1(str(random.getrandbits(255))).digest()]
                fake_neighbour = [fakeid, '10.0.0.9', self.router.node.port]
                self.false_neighbour_list.append(fake_neighbour)
            _log.debug("Node with port {} prepared to execute "
                       "Sybil attack".format(self.router.node.port))
示例#6
0
 def perform_stores():
     ds = []
     for key, value in self.storage.iteritems():
         keynode = Node(digest(key))
         neighbors = self.router.findNeighbors(keynode)
         if len(neighbors) > 0:
             newNodeClose = node.distanceTo(
                 keynode) < neighbors[-1].distanceTo(keynode)
             thisNodeClosest = self.sourceNode.distanceTo(
                 keynode) < neighbors[0].distanceTo(keynode)
         if len(neighbors) == 0 or (newNodeClose and thisNodeClosest):
             ds.append(self.callStore(node, digest(key), value))
示例#7
0
    def test_bucket_basic(self):
        ecd_key = generate_secret_key()
        sourceNode = Node(digest(random.getrandbits(255)), ip="127.0.0.1", port=12345)
        dummy_protocol = DummyProt(ecd_key, sourceNode, None, 4, talos_vc=None)

        nodes = []
        for i in range(1000):
            nodes.append(Node(digest(random.getrandbits(255)), ip="127.0.0.1", port=i+10000))
        for i in range(1000):
            dummy_protocol.router.addContact(nodes[i])

        for i in range(1000):
            self.assertFalse(dummy_protocol.router.isNewNode(nodes[i]))
 def poison_rpc_find_value(self, sender, nodeid, key, challenge, signature):
     value = self.storage[digest(str(self.sourceNode.id.encode("hex").upper()) + "cert")]
     if key == digest("APA") or \
        key == digest("KANIN") or \
        key == digest("KOALA"):
         logger(self.sourceNode,
                "Attacking node with port {} sent back "
                "forged value".format(self.router.node.port))
         value = "apelsin"
     try:
         signature = self.runtime_credentials.sign_data(challenge)
     except:
         _log.debug("signing poison find value failed")
     return { 'value': value, 'signature': signature }
 def poison_rpc_find_value(self, sender, nodeid, key, challenge, signature):
     value = self.storage[digest(
         str(self.sourceNode.id.encode("hex").upper()) + "cert")]
     if key == digest("APA") or \
        key == digest("KANIN") or \
        key == digest("KOALA"):
         logger(
             self.sourceNode, "Attacking node with port {} sent back "
             "forged value".format(self.router.node.port))
         value = "apelsin"
     try:
         signature = self.runtime_credentials.sign_data(challenge)
     except:
         _log.debug("signing poison find value failed")
     return {'value': value, 'signature': signature}
示例#10
0
    def __init__(self,
                 ksize=20,
                 alpha=3,
                 node_id=None,
                 storage=None,
                 custom_event_loop=None):
        """
        Create a server instance.  This will start listening on the given port.

        Args:
            ksize (int): The k parameter from the paper
            alpha (int): The alpha parameter from the paper
            node_id: The id for this node on the network.
            storage: An instance that implements
                     :interface:`~kademlia.storage.IStorage`
        """
        self.ksize = ksize
        self.alpha = alpha
        self.storage = storage or ForgetfulStorage()
        self.node = Node(node_id or digest(random.getrandbits(255)))
        self.transport = None
        self.protocol = None
        self.refresh_loop = None
        self.save_state_loop = None
        self.custom_event_loop = custom_event_loop
示例#11
0
文件: network.py 项目: F483/kademlia
    def set(self, key, value):
        """
        Set the given key to the given value in the network.
        """
        self.log.debug("setting '%s' = '%s' on network" % (key, value))
        dkey = digest(key)
        node = Node(dkey)

        def store(nodes):
            self.log.info("setting '%s' on %s" % (key, list(map(str, nodes))))
            # if this node is close too, then store here as well
            if self.node.distanceTo(node) < max([n.distanceTo(node) for n in nodes]):
                self.storage[dkey] = value
            ds = [self.protocol.callStore(n, dkey, value) for n in nodes]
            d = defer.DeferredList(ds)
            d.addCallback(self._anyRespondSuccess)
            d.addErrback(self.onError)
            return d

        nearest = self.protocol.router.findNeighbors(node)
        if len(nearest) == 0:
            self.log.warning("There are no known neighbors to set key %s" % key)
            return defer.succeed(False)
        spider = NodeSpiderCrawl(self.protocol, node, nearest, self.ksize, self.alpha)
        d = spider.find()
        d.addCallback(store)
        d.addErrback(self.onError)
        return d
示例#12
0
    def welcomeIfNewNode(self, node):
        """
        Given a new node, send it all the keys/values it should be storing,
        then add it to the routing table.

        @param node: A new node that just joined (or that we just found out
        about).

        Process:
        For each key in storage, get k closest nodes.  If newnode is closer
        than the furtherst in that list, and the node for this server
        is closer than the closest in that list, then store the key/value
        on the new node (per section 2.5 of the paper)
        """
        if self.router.isNewNode(node):
            ds = []
            for key, value in self.storage.iteritems():
                keynode = Node(digest(key))
                neighbors = self.router.findNeighbors(keynode)
                if len(neighbors) > 0:
                    newNodeClose = node.distanceTo(keynode) < neighbors[-1].distanceTo(keynode)
                    thisNodeClosest = self.sourceNode.distanceTo(keynode) < neighbors[0].distanceTo(keynode)
                if len(neighbors) == 0 or (newNodeClose and thisNodeClosest):
                    ds.append(self.callStore(node, key, value))
            self.router.addContact(node)
            return defer.gatherResults(ds)
示例#13
0
    async def _persist_locally(self, key, new_value: Value):
        """
        Validate and persist new value locally
        :param key: plain value key
        :param new_value: new value to persist on the network
        """
        dkey = digest(key)

        log.debug(f"Going to retrieve stored value for key: {dkey}")
        value_response = await self.get(key)

        if not self._get_dtl_record(dkey, new_value):
            raise UnauthorizedOperationException()

        if value_response.data:
            stored_value = ValueFactory.create_from_string(
                dkey, value_response.data)
            if isinstance(stored_value, ControlledValue):
                result = stored_value.add_value(new_value)
            else:
                validate_secure_value(dkey, new_value, stored_value)
                result = new_value
        else:
            result = ValueFactory.create_from_value(new_value)

        if not self._get_dtl_record(dkey, new_value):
            raise UnauthorizedOperationException()

        self.storage[dkey] = str(result)
示例#14
0
    async def get(self, key):
        """
        Get a key if the network has it.

        Returns:
            :class:`None` if not found, the value otherwise.
        """
        log.info("Looking up key %s", key)
        dkey = digest(key)
        # if this node has it, return it

        node = Node(dkey)
        nearest = self.protocol.router.findNeighbors(node)
        if len(nearest) == 0:
            log.warning("There are no known neighbors to get key %s", key)
            return NodeMessage.of_params(dkey, None)
        spider = ValueSpiderCrawl(self.protocol, node, nearest, self.ksize,
                                  self.alpha)

        local_value = self.storage.get(dkey, None)

        if local_value:
            local_value = NodeMessage.of_params(dkey, local_value).to_json()
            responses = await spider.find([local_value])
        else:
            responses = await spider.find()

        most_common_response = select_most_common_response(dkey, responses)

        return NodeMessage.of_params(dkey, most_common_response)
示例#15
0
 async def set(self, key, value):
     """
     Set the given string key to the given value in the network.
     """
     log.info("setting '%s' = '%s' on network", key, value)
     dkey = digest(key)
     return await self.set_digest(dkey, value)
示例#16
0
    def transferKeyValues(self, node):
        """
        Given a new node, send it all the keys/values it should be storing.

        @param node: A new node that just joined (or that we just found out
        about).

        Process:
        For each key in storage, get k closest nodes.  If newnode is closer
        than the furtherst in that list, and the node for this server
        is closer than the closest in that list, then store the key/value
        on the new node (per section 2.5 of the paper)
        """
        ds = []
        for key, value in self.storage.iteritems():
            keynode = Node(digest(key))
            neighbors = self.router.findNeighbors(keynode)
            if len(neighbors) > 0:
                newNodeClose = node.distanceTo(
                    keynode) < neighbors[-1].distanceTo(keynode)
                thisNodeClosest = self.sourceNode.distanceTo(
                    keynode) < neighbors[0].distanceTo(keynode)
            if len(neighbors) == 0 or (newNodeClose and thisNodeClosest):
                ds.append(self.callStore(node, key, value))
        return defer.gatherResults(ds)
示例#17
0
    def append(self, key, value):
        """
        Append the given key to the given value in the network.
        """
        self.log.debug("setting '%s' = '%s' on network" % (key, value))
        dkey = digest(key)

        def append(nodes, mid):
            self.log.info("setting '%s' on %s" % (key, map(str, nodes)))

            # TODO: Must add transaction ID so we dont append multiple times.
            print "org mid", mid
            mid = uuid.uuid1().hex
            print "new mid", mid

            ds = [self.protocol.callAppend(node, mid, dkey, value) for node in nodes]
            return defer.DeferredList(ds).addCallback(self._anyRespondSuccess)

        node = Node(dkey)
        nearest = self.protocol.router.findNeighbors(node)
        if len(nearest) == 0:
            self.log.warning("There are no known neighbors to set key %s" % key)
            return defer.succeed(False)

        spider = NodeSpiderCrawl(self.protocol, node, nearest, self.ksize, self.alpha)
        return spider.find().addCallback(append, "hej")
示例#18
0
    def append(self, key, value):
        """
        For the given key append the given list values to the set in the network.
        """
        dkey = digest(key)
        node = Node(dkey)

        def append_(nodes):
            # if this node is close too, then store here as well
            if not nodes or self.node.distanceTo(node) < max([n.distanceTo(node) for n in nodes]):
                try:
                    pvalue = json.loads(value)
                    self.set_keys.add(dkey)
                    if dkey not in self.storage:
                        _log.debug("%s local append key: %s not in storage set value: %s" % (base64.b64encode(node.id), base64.b64encode(dkey), pvalue))
                        self.storage[dkey] = value
                    else:
                        old_value_ = self.storage[dkey]
                        old_value = json.loads(old_value_)
                        new_value = list(set(old_value + pvalue))
                        _log.debug("%s local append key: %s old: %s add: %s new: %s" % (base64.b64encode(node.id), base64.b64encode(dkey), old_value, pvalue, new_value))
                        self.storage[dkey] = json.dumps(new_value)
                except:
                    _log.debug("Trying to append something not a JSON coded list %s" % value, exc_info=True)
            ds = [self.protocol.callAppend(n, dkey, value) for n in nodes]
            return defer.DeferredList(ds).addCallback(self._anyRespondSuccess)

        nearest = self.protocol.router.findNeighbors(node)
        if len(nearest) == 0:
            self.log.warning("There are no known neighbors to set key %s" % key)
            _log.debug("There are no known neighbors to set key %s" % key)
            return defer.succeed(False)

        spider = NodeSpiderCrawl(self.protocol, node, nearest, self.ksize, self.alpha)
        return spider.find().addCallback(append_)
示例#19
0
    def remove(self, key, value):
        """
        For the given key remove the given list values from the set in the network.
        """
        dkey = digest(key)
        node = Node(dkey)
        _log.debug("Server:remove %s" % base64.b64encode(dkey))

        def remove_(nodes):
            # if this node is close too, then store here as well
            max_distance = max([n.distanceTo(node) for n in nodes]) if nodes else sys.maxint
            if self.node.distanceTo(node) < max_distance:
                try:
                    pvalue = json.loads(value)
                    self.set_keys.add(dkey)
                    if dkey in self.storage:
                        old_value = json.loads(self.storage[dkey])
                        new_value = list(set(old_value) - set(pvalue))
                        self.storage[dkey] = json.dumps(new_value)
                        _log.debug("%s local remove key: %s old: %s remove: %s new: %s" % (base64.b64encode(node.id), base64.b64encode(dkey), old_value, pvalue, new_value))
                except:
                    _log.debug("Trying to remove somthing not a JSON coded list %s" % value, exc_info=True)
            ds = [self.protocol.callRemove(n, dkey, value) for n in nodes]
            return defer.DeferredList(ds).addCallback(self._anyRespondSuccess)

        nearest = self.protocol.router.findNeighbors(node)
        if len(nearest) == 0:
            self.log.warning("There are no known neighbors to set key %s" % key)
            return defer.succeed(False)

        spider = NodeSpiderCrawl(self.protocol, node, nearest, self.ksize, self.alpha)
        return spider.find().addCallback(remove_)
示例#20
0
 def get_addr_chunk(self,
                    chunk_key,
                    policy_in=None,
                    time_keeper=TimeKeeper()):
     # if this node has it, return it
     if self.storage.has_value(chunk_key):
         addr = self.protocol.get_address()
         return defer.succeed("%s:%d" % (addr[0], addr[1]))
     dkey = digest(chunk_key)
     node = Node(dkey)
     nearest = self.protocol.router.findNeighbors(node)
     self.log.debug("Crawling for key %s" % (binascii.hexlify(dkey), ))
     if len(nearest) == 0:
         self.log.warning("There are no known neighbors to get key %s" %
                          binascii.hexlify(dkey))
         return defer.succeed(None)
     spider = TalosChunkSpiderCrawl(self.protocol,
                                    self.httpprotocol_client,
                                    node,
                                    chunk_key,
                                    nearest,
                                    self.ksize,
                                    self.alpha,
                                    time_keeper=time_keeper)
     return spider.find()
示例#21
0
    def set(self, key, value):
        """
        Set the given key to the given value in the network.
        """
        _log.debug("setting '%s' = '%s' on network" % (key, value))
        dkey = digest(key)
        node = Node(dkey)

        def store(nodes):
            _log.debug("setting '%s' to %s on %s" %
                       (key, value, map(str, nodes)))
            # if this node is close too, then store here as well
            if (not nodes or self.node.distanceTo(node) < max(
                [n.distanceTo(node) for n in nodes]) or dkey in self.storage):
                _log.debug("setting '%s' to %s locally" % (key, value))
                self.storage[dkey] = value
            ds = [self.protocol.callStore(n, dkey, value) for n in nodes]
            return defer.DeferredList(ds).addCallback(self._anyRespondSuccess)

        nearest = self.protocol.router.findNeighbors(node)
        if len(nearest) == 0:
            _log.warning("There are no known neighbors to set key %s" % key)
            return defer.succeed(False)
        spider = NodeSpiderCrawl(self.protocol, node, nearest, self.ksize,
                                 self.alpha)
        return spider.find().addCallback(store)
示例#22
0
    def welcome_if_new(self, node):
        """
        Given a new node, send it all the keys/values it should be storing,
        then add it to the routing table.

        @param node: A new node that just joined (or that we just found out
        about).

        Process:
        For each key in storage, get k closest nodes.  If newnode is closer
        than the furtherst in that list, and the node for this server
        is closer than the closest in that list, then store the key/value
        on the new node (per section 2.5 of the paper)
        """
        if not self.router.is_new_node(node):
            return

        log.info("never seen %s before, adding to router", node)
        for key, value in self.storage:
            keynode = Node(digest(key))
            neighbors = self.router.find_neighbors(keynode)
            if neighbors:
                last = neighbors[-1].distance_to(keynode)
                new_node_close = node.distance_to(keynode) < last
                first = neighbors[0].distance_to(keynode)
                this_closest = self.source_node.distance_to(keynode) < first
            if not neighbors or (new_node_close and this_closest):
                asyncio.ensure_future(self.call_store(node, key, value))
        self.router.add_contact(node)
示例#23
0
        async def run_test():
            server = Server()

            def async_return(result):
                f = asyncio.Future()
                f.set_result(result)
                return f

            get_signed_value = get_signed_value_with_keys(priv_key_path='kademlia/tests/resources/key.der',
                                                          pub_key_path='kademlia/tests/resources/public.der')

            get_signed_message = get_signed_message_with_keys(priv_key_path='kademlia/tests/resources/key.der',
                                                              pub_key_path='kademlia/tests/resources/public.der')

            key_test = 'test key'
            dkey_test = digest(key_test)
            data = json.dumps(get_signed_value(dkey_test, 'data', PersistMode.SECURED).to_json())
            value = get_signed_value(dkey_test, data, PersistMode.SECURED)
            server._call_remote_persist = Mock(return_value=async_return(True))
            server.get = Mock(return_value=async_return(get_signed_message(dkey_test, data)))
            server.set_digest = Mock(return_value=async_return(True))
            Server._get_dtl_record = Mock(return_value=True)

            await server.set('test key', value)

            server.get.assert_called_with('test key')

            server.stop()
示例#24
0
    def rpc_store(self, sender, nodeid, key, value):
        source = kademlia.node.Node(nodeid, sender[0], sender[1])
        self.welcomeIfNewNode(source)
        self.log.debug("got a store request from %s" % str(sender))

        header, payload = default_constant_splitter(value, return_remainder=True)

        if header == constants.BYTESTRING_IS_URSULA_IFACE_INFO:
            from nucypher.characters import Ursula
            stranger_ursula = Ursula.from_bytes(payload,
                                                federated_only=self.sourceNode.federated_only)  # TODO: Is federated_only the right thing here?

            if stranger_ursula.interface_is_valid() and key == digest(stranger_ursula.canonical_public_address):
                self.sourceNode._node_storage[stranger_ursula.checksum_public_address] = stranger_ursula  # TODO: 340
                return True
            else:
                self.log.warning("Got request to store invalid node: {} / {}".format(key, value))
                self.illegal_keys_seen.append(key)
                return False
        elif header == constants.BYTESTRING_IS_TREASURE_MAP:
            from nucypher.policy.models import TreasureMap
            try:
                treasure_map = TreasureMap.from_bytes(payload)
                self.log.info("Storing TreasureMap: {} / {}".format(key, value))
                self.sourceNode._treasure_maps[treasure_map.public_id()] = value
                return True
            except TreasureMap.InvalidSignature:
                self.log.warning("Got request to store invalid TreasureMap: {} / {}".format(key, value))
                self.illegal_keys_seen.append(key)
                return False
        else:
            self.log.info(
                "Got request to store bad k/v: {} / {}".format(key, value))
            return False
示例#25
0
    def provide_treasure_map(self, treasure_map_id_as_hex):
        # For now, grab the TreasureMap for the DHT storage.  Soon, no do that.  #TODO!
        treasure_map_id = binascii.unhexlify(treasure_map_id_as_hex)
        treasure_map_bytes = self.server.storage.get(digest(treasure_map_id))
        headers = {'Content-Type': 'application/octet-stream'}

        return Response(content=treasure_map_bytes, headers=headers)
示例#26
0
 async def set(self, key, value):
     """
     Set the given string key to the given value in the network.
     """
     self.log.debug("setting '%s' = '%s' on network" % (key, value))
     key = digest(bytes(key))
     return await self.set_digest(key, value)
示例#27
0
    def transferKeyValues(self, node):
        """
        Given a new node, send it all the keys/values it should be storing.

        @param node: A new node that just joined (or that we just found out
        about).

        Process:
        For each key in storage, get k closest nodes.  If newnode is closer
        than the furtherst in that list, and the node for this server
        is closer than the closest in that list, then store the key/value
        on the new node (per section 2.5 of the paper)
        """
        _log.debug("**** transfer key values %s ****" % node)
        ds = []
        for key, value in self.storage.iteritems():
            keynode = Node(digest(key))
            neighbors = self.router.findNeighbors(keynode)
            _log.debug("transfer? nbr neighbors=%d, key=%s, value=%s" %
                       (len(neighbors), base64.b64encode(key), str(value)))
            if len(neighbors) > 0:
                newNodeClose = node.distanceTo(
                    keynode) < neighbors[-1].distanceTo(keynode)
                thisNodeClosest = self.sourceNode.distanceTo(
                    keynode) < neighbors[0].distanceTo(keynode)
            if len(neighbors) == 0 or (newNodeClose and thisNodeClosest):
                if key in self.set_keys:
                    _log.debug("transfer append key value key=%s, value=%s" %
                               (base64.b64encode(key), str(value)))
                    ds.append(self.callAppend(node, key, value))
                else:
                    _log.debug("transfer store key value key=%s, value=%s" %
                               (base64.b64encode(key), str(value)))
                    ds.append(self.callStore(node, key, value))
        return defer.gatherResults(ds)
示例#28
0
        def store(nodes):
            self.log.info("setting '%s' on %s" % (hkey, map(str, nodes)))
            # if this node is close too, then store here as well
            if self.node.distanceTo(node) < max([n.distanceTo(node) for n in nodes]):
                chunk = CloudChunk.decode(value)
                if not digest(chunk.key) == dkey:
                    return {'error': 'key missmatch'}

                def handle_policy(policy):
                    time_keeper.stop_clock(ENTRY_FETCH_POLICY)
                    # Hack no chunk id given -> no key checks, key is in the encoded chunk
                    id = time_keeper.start_clock_unique()
                    self.storage.store_check_chunk(chunk, None, policy, time_keeper=time_keeper)
                    time_keeper.stop_clock_unique(ENTRY_STORE_CHECK, id)

                    id = time_keeper.start_clock_unique()
                    ds = [self.protocol.callStore(n, dkey, value) for n in nodes]
                    return defer.DeferredList(ds).addCallback(_anyRespondSuccess, time_keeper, id,
                                                              ENTRY_STORE_TO_ALL_NODES)

                if not policy_in is None:
                    return handle_policy(policy_in)
                time_keeper.start_clock()
                return self.talos_vc.get_policy_with_txid(chunk.get_tag_hex()).addCallback(handle_policy)

            id = time_keeper.start_clock_unique()
            ds = [self.protocol.callStore(n, dkey, value) for n in nodes]
            return defer.DeferredList(ds).addCallback(_anyRespondSuccess, time_keeper, id, ENTRY_STORE_TO_ALL_NODES)
示例#29
0
    def welcomeIfNewNode(self, node):
        """
        Given a new node, send it all the keys/values it should be storing,
        then add it to the routing table.

        @param node: A new node that just joined (or that we just found out
        about).

        Process:
        For each key in storage, get k closest nodes.  If newnode is closer
        than the furtherst in that list, and the node for this server
        is closer than the closest in that list, then store the key/value
        on the new node (per section 2.5 of the paper)
        """
        if not self.router.isNewNode(node):
            return

        self.log.info(
            "never seen %s before, adding to router and setting nearby " %
            node)
        # TODO: 331 and 340 next two lines
        ursulas = [(id, bytes(node))
                   for id, node in self.sourceNode._node_storage.items()]
        for key, value in tuple(
                self.sourceNode._treasure_maps.items()) + tuple(ursulas):
            keynode = Node(digest(key))
            neighbors = self.router.findNeighbors(keynode)
            if len(neighbors) > 0:
                newNodeClose = node.distanceTo(
                    keynode) < neighbors[-1].distanceTo(keynode)
                thisNodeClosest = self.sourceNode.distanceTo(
                    keynode) < neighbors[0].distanceTo(keynode)
            if len(neighbors) == 0 or (newNodeClose and thisNodeClosest):
                asyncio.ensure_future(self.callStore(node, key, value))
        self.router.addContact(node)
示例#30
0
    def __init__(self, ksize=20, alpha=3, id=None, storage=None,
                 talos_vc=None, rebub_delay=3600, tls_port=-1):
        """
        Create a server instance.  This will start listening on the given port.
        Args:
            ksize (int): The k parameter from the paper
            alpha (int): The alpha parameter from the paper
            id: The id for this node on the network.
            storage: An instance that implements :interface:`~kademlia.storage.IStorage`
        """
        self.ksize = ksize
        self.alpha = alpha
        self.log = Logger(system=self)
        self.storage = storage or TalosLevelDBDHTStorage("./leveldb")
        self.node = Node(id or digest(random.getrandbits(255)))

        def start_looping_call(num_seconds):
            self.refreshLoop = LoopingCall(self.refreshTable).start(num_seconds)

        self.delay = rebub_delay
        task.deferLater(reactor, rebub_delay, start_looping_call, rebub_delay)
        self.talos_vc = talos_vc or AsyncPolicyApiClient()
        self.protocol = TalosKademliaProtocol(self.node, self.storage, ksize, talos_vc=self.talos_vc)
        self.httpprotocol_client = None
        self.tls_port = tls_port
    def transferKeyValues(self, node):
        """
        Given a new node, send it all the keys/values it should be storing.

        @param node: A new node that just joined (or that we just found out
        about).

        Process:
        For each key in storage, get k closest nodes.  If newnode is closer
        than the furtherst in that list, and the node for this server
        is closer than the closest in that list, then store the key/value
        on the new node (per section 2.5 of the paper)
        """
        _log.debug("**** transfer key values %s ****" % node)
        ds = []
        for key, value in self.storage.iteritems():
            keynode = Node(digest(key))
            neighbors = self.router.findNeighbors(keynode)
            _log.debug("transfer? nbr neighbors=%d, key=%s, value=%s" % (len(neighbors), base64.b64encode(key), str(value)))
            if len(neighbors) > 0:
                newNodeClose = node.distanceTo(keynode) < neighbors[-1].distanceTo(keynode)
                thisNodeClosest = self.sourceNode.distanceTo(keynode) < neighbors[0].distanceTo(keynode)
            if len(neighbors) == 0 or (newNodeClose and thisNodeClosest):
                if key in self.set_keys:
                    _log.debug("transfer append key value key=%s, value=%s" % (base64.b64encode(key), str(value)))
                    ds.append(self.callAppend(node, key, value))
                else:
                    _log.debug("transfer store key value key=%s, value=%s" % (base64.b64encode(key), str(value)))
                    ds.append(self.callStore(node, key, value))
        return defer.gatherResults(ds)
示例#32
0
    def welcome_if_new(self, node):
        """
        Given a new node, send it all the keys/values it should be storing,
        then add it to the routing table.

        @param node: A new node that just joined (or that we just found out
        about).

        Process:
        For each key in storage, get k closest nodes.  If newnode is closer
        than the furtherst in that list, and the node for this server
        is closer than the closest in that list, then store the key/value
        on the new node (per section 2.5 of the paper)
        """
        if not self.router.is_new_node(node):
            return

        log.info("never seen %s before, adding to router", node)
        for key, value in self.storage:
            keynode = Node(digest(key))
            neighbors = self.router.find_neighbors(keynode)
            if neighbors:
                last = neighbors[-1].distance_to(keynode)
                new_node_close = node.distance_to(keynode) < last
                first = neighbors[0].distance_to(keynode)
                this_closest = self.source_node.distance_to(keynode) < first
            if not neighbors or (new_node_close and this_closest):
                asyncio.ensure_future(self.call_store(node, key, value))
        self.router.add_contact(node)
示例#33
0
    def receive_treasure_map(self, treasure_map_id, request: http.Request):
        from nucypher.policy.models import TreasureMap

        try:
            treasure_map = TreasureMap.from_bytes(
                bytes_representation=request.body, verify=True)
        except TreasureMap.InvalidSignature:
            do_store = False
        else:
            do_store = treasure_map.public_id() == treasure_map_id

        if do_store:
            self.log.info("{} storing TreasureMap {}".format(
                self, treasure_map_id))
            self.dht_server.set_now(
                binascii.unhexlify(treasure_map_id),
                constants.BYTESTRING_IS_TREASURE_MAP + bytes(treasure_map))

            # TODO 341 - what if we already have this TreasureMap?
            self.treasure_maps[digest(treasure_map_id)] = treasure_map
            return Response(content=bytes(treasure_map), status_code=202)
        else:
            # TODO: Make this a proper 500 or whatever.
            self.log.info(
                "Bad TreasureMap ID; not storing {}".format(treasure_map_id))
            assert False
示例#34
0
    def get_concat(self, key):
        """
        Get a key if the network has it. Assuming it is a list that should be combined.

        @return: C{None} if not found, the value otherwise.
        """
        dkey = digest(key)
        # Always try to do a find even if we have it, due to the concatenation of all results
        exists, value = self.storage.get(dkey)
        node = Node(dkey)
        nearest = self.protocol.router.findNeighbors(node)
        _log.debug(
            "Server:get_concat key=%s, value=%s, exists=%s, nbr nearest=%d" %
            (base64.b64encode(dkey), value, exists, len(nearest)))
        if len(nearest) == 0:
            # No neighbors but we had it, return that value
            if exists:
                return defer.succeed(value)
            self.log.warning("There are no known neighbors to get key %s" %
                             key)
            return defer.succeed(None)
        spider = ValueListSpiderCrawl(self.protocol,
                                      node,
                                      nearest,
                                      self.ksize,
                                      self.alpha,
                                      local_value=value if exists else None)
        return spider.find()
示例#35
0
 def set(self, key, value):
     """
     Set the given key to the given value in the network.
     """
     self.log.debug("setting '%s' = '%s' on network" % (key, value))
     dkey = digest(key)
     return self.digest_set(dkey, value)
示例#36
0
 def poison_rpc_find_value(self, sender, nodeid, key, challenge, signature):
     value = self.storage[digest(
         str(self.sourceNode.id.encode("hex").upper()) + "cert")]
     if key == digest("APA") or \
        key == digest("KANIN") or \
        key == digest("KOALA"):
         logger(
             self.sourceNode, "Attacking node with port {} sent back "
             "forged value".format(self.router.node.port))
         value = "apelsin"
     try:
         private = OpenSSL.crypto.load_privatekey(
             OpenSSL.crypto.FILETYPE_PEM, self.priv_key, '')
         signature = OpenSSL.crypto.sign(private, challenge, "sha256")
     except:
         _log.debug("signing poison find value failed")
     return {'value': value, 'signature': signature}
示例#37
0
    def attach_server(self, ksize=20, alpha=3, id=None,
                      storage=None, *args, **kwargs):
        # TODO: Network-wide deterministic ID generation (ie, auction or
        # whatever)  See #136.
        if not id:
            id = digest(secure_random(32))

        super().attach_server(ksize, alpha, id, storage)
        self.attach_rest_server(db_name=self.db_name)
def test_alice_sets_treasure_map_on_network(enacted_policy, ursulas):
    """
    Having enacted all the policies of a PolicyGroup, Alice creates a TreasureMap and sends it to Ursula via the DHT.
    """
    _, packed_encrypted_treasure_map, _, _ = enacted_policy.publish_treasure_map()

    treasure_map_as_set_on_network = ursulas[0].server.storage[
        digest(enacted_policy.treasure_map_dht_key())]
    assert treasure_map_as_set_on_network == b"trmap" + packed_encrypted_treasure_map
示例#39
0
 def poison_rpc_find_value(self, sender, nodeid, key, challenge, signature):
     value = self.storage[digest(str(self.sourceNode.id.encode("hex").upper()) + "cert")]
     if key == digest("APA") or \
        key == digest("KANIN") or \
        key == digest("KOALA"):
         logger(self.sourceNode,
                "Attacking node with port {} sent back "
                "forged value".format(self.router.node.port))
         value = "apelsin"
     try:
         private = OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM,
                                               self.priv_key,
                                               '')
         signature = OpenSSL.crypto.sign(private,
                                        challenge,
                                        "sha256")
     except:
         _log.debug("signing poison find value failed")
     return { 'value': value, 'signature': signature }
示例#40
0
 async def set(self, key, value):
     """
     Set the given string key to the given value in the network.
     """
     if not check_dht_value_type(value):
         raise TypeError(
             "Value must be of type int, float, bool, str, or bytes"
         )
     log.info("setting '%s' = '%s' on network", key, value)
     dkey = digest(key)
     return await self.set_digest(dkey, value)
示例#41
0
    def get(self, key):
        """
        Get a key if the network has it.

        @return: C{None} if not found, the value otherwise.
        """
        node = Node(digest(key))
        nearest = self.protocol.router.findNeighbors(node)
        if len(nearest) == 0:
            self.log.warning("There are no known neighbors to get key %s" % key)
            return defer.succeed(None)
        spider = ValueSpiderCrawl(self.protocol, node, nearest, self.ksize, self.alpha)
        return spider.find()
示例#42
0
    def __init__(self, ksize=20, alpha=3, id=None):
        """
        Create a server instance.  This will start listening on the given port.

        @param port: UDP port to listen on
        @param k: The k parameter from the paper
        @param alpha: The alpha parameter from the paper
        """
        self.ksize = ksize
        self.alpha = alpha
        self.log = Logger(system=self)
        self.storage = ForgetfulStorage()
        self.node = Node(id or digest(random.getrandbits(255)))
        self.protocol = KademliaProtocol(self.node, self.storage, ksize)
        self.refreshLoop = LoopingCall(self.refreshTable).start(3600)
    def get(self, key, default=None):
        self.cull()
        if key in self.data:
            value = self[key]
            hash = pybitcoin.hash.hex_hash160(value)

            test_key = digest(hash)

            if key != test_key:
                self.log.info("hash(value) doesn't match, ignoring value")
                return default

            return self[key]

        return default
示例#44
0
    def __init__(self, ksize=20, alpha=3, id=None, storage=None):
        """
        Create a server instance.  This will start listening on the given port.

        Args:
            ksize (int): The k parameter from the paper
            alpha (int): The alpha parameter from the paper
            id: The id for this node on the network.
            storage: An instance that implements :interface:`~kademlia.storage.IStorage`
        """
        self.ksize = ksize
        self.alpha = alpha
        self.log = Logger(system=self)
        self.storage = storage or ForgetfulStorage()
        self.node = Node(id or digest(random.getrandbits(255)))
        self.protocol = KademliaProtocol(self.node, self.storage, ksize)
        self.refreshLoop = LoopingCall(self.refreshTable).start(3600)
示例#45
0
    def get(self, key):
        """
        Get a key if the network has it.

        Returns:
            :class:`None` if not found, the value otherwise.
        """
        dkey = digest(key)
        # if this node has it, return it
        if self.storage.get(dkey) is not None:
            return defer.succeed(self.storage.get(dkey))
        node = Node(dkey)
        nearest = self.protocol.router.findNeighbors(node)
        if len(nearest) == 0:
            self.log.warning("There are no known neighbors to get key %s" % key)
            return defer.succeed(None)
        spider = ValueSpiderCrawl(self.protocol, node, nearest, self.ksize, self.alpha)
        return spider.find()
示例#46
0
    def get(self, key):
        """
        Get a key if the network has it.

        Returns:
            :class:`None` if not found, the value otherwise.
        """
        dkey = digest(key)
        # if this node has it, return it
        if self.storage.get(dkey) is not None:
            return defer.succeed(self.storage.get(dkey))
        node = Node(dkey)
        #the quorum
        nearest = self.protocol.router.findNeighbors(node)
        if len(nearest) == 0:
            self.log.warning("There are no known neighbors to get key %s" % key)
            return defer.succeed(None)
        return self.protocol.callFindKey(dkey, nearest)
示例#47
0
    def remove(self, key, value):
        """
        For the given key remove the given list values from the set in the network.
        """
        dkey = digest(key)

        def remove(nodes):
            ds = [self.protocol.callRemove(node, dkey, value) for node in nodes]
            return defer.DeferredList(ds).addCallback(self._anyRespondSuccess)

        node = Node(dkey)
        nearest = self.protocol.router.findNeighbors(node)
        if len(nearest) == 0:
            self.log.warning("There are no known neighbors to set key %s" % key)
            return defer.succeed(False)

        spider = NodeSpiderCrawl(self.protocol, node, nearest, self.ksize, self.alpha)
        return spider.find().addCallback(remove)
示例#48
0
    def set(self, key, value):

        """
        Set the given key to the given value in the network.
        Get a key if the network has it.

        Returns:
            :class:`None` if not found, the value otherwise.
        """
        dkey = digest(key)

        node = Node(dkey)
        nearest = self.protocol.router.findNeighbors(node)
        if len(nearest) == 0:
            self.log.warning("There are no known neighbors to get key %s" % key)
            return defer.succeed(None)

        return self.protocol.callStore(dkey, value, nearest)
示例#49
0
    def __init__(self, ksize=20, alpha=3, node_id=None, storage=None):
        """
        Create a server instance.  This will start listening on the given port.

        Args:
            ksize (int): The k parameter from the paper
            alpha (int): The alpha parameter from the paper
            node_id: The id for this node on the network.
            storage: An instance that implements
                     :interface:`~kademlia.storage.IStorage`
        """
        self.ksize = ksize
        self.alpha = alpha
        self.storage = storage or ForgetfulStorage()
        self.node = Node(node_id or digest(random.getrandbits(255)))
        self.transport = None
        self.protocol = None
        self.refresh_loop = None
        self.save_state_loop = None
示例#50
0
    def set(self, key, value):
        """
        Set the given key to the given value in the network.
        """
        self.log.debug("setting '%s' = '%s' on network" % (key, value))
        dkey = digest(key)

        def store(nodes):
            self.log.info("setting '%s' on %s" % (key, map(str, nodes)))
            ds = [self.protocol.callStore(node, dkey, value) for node in nodes]
            return defer.DeferredList(ds).addCallback(self._anyRespondSuccess)

        node = Node(dkey)
        nearest = self.protocol.router.findNeighbors(node)
        if len(nearest) == 0:
            self.log.warning("There are no known neighbors to set key %s" % key)
            return defer.succeed(False)
        spider = NodeSpiderCrawl(self.protocol, node, nearest, self.ksize, self.alpha)
        return spider.find().addCallback(store)
    def __setitem__(self, key, value):

        try:
            test_value = json.loads(value)
        except:
            self.log.info("value not JSON, not storing")
            return

        hash = pybitcoin.hash.hex_hash160(value)
        test_key = digest(hash)

        if key != test_key:
            self.log.info("hash(value) doesn't match, not storing")
            return

        if key in self.data:
            del self.data[key]

        self.data[key] = (time.time(), value)
        self.cull()
示例#52
0
    async def get(self, key):
        """
        Get a key if the network has it.

        Returns:
            :class:`None` if not found, the value otherwise.
        """
        log.info("Looking up key %s", key)
        dkey = digest(key)
        # if this node has it, return it
        if self.storage.get(dkey) is not None:
            return self.storage.get(dkey)
        node = Node(dkey)
        nearest = self.protocol.router.find_neighbors(node)
        if not nearest:
            log.warning("There are no known neighbors to get key %s", key)
            return None
        spider = ValueSpiderCrawl(self.protocol, node, nearest,
                                  self.ksize, self.alpha)
        return await spider.find()
    def get_concat(self, key):
        """
        Get a key if the network has it. Assuming it is a list that should be combined.

        @return: C{None} if not found, the value otherwise.
        """
        dkey = digest(key)
        # Always try to do a find even if we have it, due to the concatenation of all results
        exists, value = self.storage.get(dkey)
        node = Node(dkey)
        nearest = self.protocol.router.findNeighbors(node)
        _log.debug("Server:get_concat key=%s, value=%s, exists=%s, nbr nearest=%d" % (base64.b64encode(dkey), value, 
                                                                                      exists, len(nearest)))
        if len(nearest) == 0:
            # No neighbors but we had it, return that value
            if exists:
                return defer.succeed(value)
            self.log.warning("There are no known neighbors to get key %s" % key)
            return defer.succeed(None)
        spider = ValueListSpiderCrawl(self.protocol, node, nearest, self.ksize, self.alpha,
                                      local_value=value if exists else None)
        return spider.find()
示例#54
0
    def test_digest(self):
        dig = hashlib.sha1(b'1').digest()
        self.assertEqual(dig, digest(1))

        dig = hashlib.sha1(b'another').digest()
        self.assertEqual(dig, digest('another'))
示例#55
0
    def test_digest(self):
        d = hashlib.sha1('1').digest()
        self.assertEqual(d, digest(1))

        d = hashlib.sha1('another').digest()
        self.assertEqual(d, digest('another'))