Example #1
0
    def verify_from(self,
                    actor_whom_sender_claims_to_be: "Character",
                    signature: bytes,
                    message: bytes,
                    decrypt=False,
                    signature_is_on_cleartext=False) -> tuple:
        """
        Inverse of encrypt_for.

        :param actor_that_sender_claims_to_be: A Character instance representing the actor whom the sender claims to be.  We check the public key owned by this Character instance to verify.
        :param messages: The messages to be verified.
        :param decrypt: Whether or not to decrypt the messages.
        :param signature_is_on_cleartext: True if we expect the signature to be on the cleartext.  Otherwise, we presume that the ciphertext is what is signed.
        :return: (Whether or not the signature is valid, the decrypted plaintext or NO_DECRYPTION_PERFORMED)
        """
        cleartext = NO_DECRYPTION_PERFORMED
        if signature_is_on_cleartext:
            if decrypt:
                cleartext = self._crypto_power.decrypt(message)
                msg_digest = API.keccak_digest(cleartext)
            else:
                raise ValueError(
                    "Can't look for a signature on the cleartext if we're not decrypting."
                )
        else:
            msg_digest = API.keccak_digest(message)

        actor = self._lookup_actor(actor_whom_sender_claims_to_be)
        signature_pub_key = actor.seal

        sig = API.ecdsa_load_sig(signature)
        return API.ecdsa_verify(*sig, msg_digest, signature_pub_key), cleartext
Example #2
0
    def test_keccak_digest(self):
        data = b'this is a test'

        digest1 = sha3.keccak_256(data).digest()
        digest2 = api.keccak_digest(data)

        self.assertEqual(digest1, digest2)

        # Test iterables
        data = data.split()

        digest1 = sha3.keccak_256(b''.join(data)).digest()
        digest2 = api.keccak_digest(*data)

        self.assertEqual(digest1, digest2)
Example #3
0
    def fingerprint(self):
        """
        Hashes the key using keccak-256 and returns the hexdigest in bytes.

        :return: Hexdigest fingerprint of key (keccak-256) in bytes
        """
        return keccak_digest(bytes(self)).hex().encode()
def test_grant(alice, bob, ursulas):
    networky_stuff = MockNetworkyStuff(ursulas)
    policy_end_datetime = datetime.datetime.now() + datetime.timedelta(days=5)
    n = 5
    uri = b"this_is_the_path_to_which_access_is_being_granted"
    policy = alice.grant(bob,
                         uri,
                         networky_stuff,
                         m=3,
                         n=n,
                         expiration=policy_end_datetime)

    # The number of policies is equal to the number of Ursulas we're using (n)
    assert len(policy._accepted_contracts) == n

    # Let's look at the first Ursula.
    ursula = list(policy._accepted_contracts.values())[0].ursula

    # Get the Policy from Ursula's datastore, looking up by hrac.
    proper_hrac = keccak_digest(bytes(alice.stamp) + bytes(bob.stamp) + uri)
    retrieved_policy = ursula.keystore.get_policy_contract(
        proper_hrac.hex().encode())

    # TODO: Make this a legit KFrag, not bytes.
    retrieved_k_frag = KFrag.from_bytes(retrieved_policy.k_frag)

    # TODO: Implement KFrag.__eq__
    found = False
    for k_frag in policy.kfrags:
        if bytes(k_frag) == bytes(retrieved_k_frag):
            found = True
    assert found
Example #5
0
    def retrieve(self, message_kit, data_source, alice_pubkey_sig):
        hrac = keccak_digest(
            bytes(alice_pubkey_sig) + self.stamp + data_source.label)
        treasure_map = self.treasure_maps[hrac]

        # First, a quick sanity check to make sure we know about at least m nodes.
        known_nodes_as_bytes = set([bytes(n) for n in self.known_nodes.keys()])
        intersection = treasure_map.ids.intersection(known_nodes_as_bytes)

        if len(intersection) < treasure_map.m:
            raise RuntimeError(
                "Not enough known nodes.  Try following the TreasureMap again."
            )

        work_orders = self.generate_work_orders(hrac, message_kit.capsule)
        for node_id in self.treasure_maps[hrac]:
            node = self.known_nodes[UmbralPublicKey.from_bytes(node_id)]
            cfrags = self.get_reencrypted_c_frags(work_orders[bytes(
                node.stamp)])
            message_kit.capsule.attach_cfrag(cfrags[0])
        verified, delivered_cleartext = self.verify_from(data_source,
                                                         message_kit,
                                                         decrypt=True)

        if verified:
            return delivered_cleartext
        else:
            raise RuntimeError(
                "Not verified - replace this with real message.")
Example #6
0
    def rpc_store(self, sender, nodeid, key, value):
        source = NuCypherNode(nodeid, sender[0], sender[1])
        self.welcomeIfNewNode(source)
        self.log.debug("got a store request from %s" % str(sender))

        # TODO: Why is this logic here?  This is madness.  See #172.
        if value.startswith(bytes(constants.BYTESTRING_IS_URSULA_IFACE_INFO)):
            header, signature, sender_pubkey_sig, message = dht_value_splitter(
                value, return_remainder=True)

            # TODO: TTL?
            hrac = keccak_digest(message)
            do_store = self.determine_legality_of_dht_key(signature, sender_pubkey_sig, message,
                                                          hrac, key, value)
        elif value.startswith(bytes(constants.BYTESTRING_IS_TREASURE_MAP)):
            header, signature, sender_pubkey_sig, hrac, message = dht_with_hrac_splitter(
                value, return_remainder=True)

            # TODO: TTL?
            do_store = self.determine_legality_of_dht_key(signature, sender_pubkey_sig, message,
                                                          hrac, key, value)
        else:
            self.log.info(
                "Got request to store bad k/v: {} / {}".format(key, value))
            do_store = False

        if do_store:
            self.log.info("Storing k/v: {} / {}".format(key, value))
            self.storage[key] = value
            if value.startswith(bytes(constants.BYTESTRING_IS_URSULA_IFACE_INFO)):
                self.ursulas[key] = value
            if value.startswith(bytes(constants.BYTESTRING_IS_TREASURE_MAP)):
                self.treasure_maps[key] = value

        return do_store
Example #7
0
 def learn_about_nodes(self, address, port):
     """
     Sends a request to node_url to find out about known nodes.
     """
     response = self.network_middleware.get_nodes_via_rest(address, port)
     signature, nodes = signature_splitter(response.content,
                                           return_remainder=True)
     # TODO: Although not treasure map-related, this has a whiff of #172.
     ursula_interface_splitter = dht_value_splitter + BytestringSplitter(
         (bytes, 17))
     split_nodes = ursula_interface_splitter.repeat(nodes)
     new_nodes = {}
     for node_meta in split_nodes:
         header, sig, pubkey, interface_info = node_meta
         if not pubkey in self.known_nodes:
             if sig.verify(keccak_digest(interface_info), pubkey):
                 address, dht_port, rest_port = msgpack.loads(
                     interface_info)
                 new_nodes[pubkey] = \
                     Ursula.as_discovered_on_network(
                         rest_port=rest_port,
                         dht_port=dht_port,
                         ip_address=address.decode("utf-8"),
                         powers_and_keys=({SigningPower: pubkey})
                     )
             else:
                 message = "Suspicious Activity: Discovered node with bad signature: {}.  Propagated by: {}:{}".format(
                     node_meta, address, port)
                 self.log.warn(message)
     return new_nodes
Example #8
0
    def test_signing(self):
        msghash = API.keccak_digest(b'hello world!')

        sig = self.power.sign(msghash)
        self.assertEqual(bytes, type(sig))
        self.assertEqual(65, len(sig))

        is_valid = self.keypair.verify(msghash, sig)
        self.assertTrue(is_valid)
    def test_ecdsa_keypair_verification(self):
        msghash = API.keccak_digest(b'hello world!')

        sig = self.ecdsa_keypair.sign(msghash)
        self.assertEqual(bytes, type(sig))
        self.assertEqual(65, len(sig))

        is_valid = self.ecdsa_keypair.verify(msghash, sig)
        self.assertTrue(is_valid)
Example #10
0
def test_alice_creates_policy_group_with_correct_hrac(idle_policy):
    """
    Alice creates a PolicyGroup.  It has the proper HRAC, unique per her, Bob, and the uri (resource_id).
    """
    alice = idle_policy.alice
    bob = idle_policy.bob

    assert idle_policy.hrac() == keccak_digest(
        bytes(alice.stamp) + bytes(bob.stamp) + alice.__resource_id)
Example #11
0
    def treasure_map_dht_key(self):
        """
        We need a key that Bob can glean from knowledge he already has *and* which Ursula can verify came from us.
        Ursula will refuse to propagate this key if it she can't prove that our public key, which is included in it,
        was used to sign the payload.

        Our public key (which everybody knows) and the hrac above.
        """
        return keccak_digest(bytes(self.alice.stamp) + self.hrac())
Example #12
0
    def hrac_for(alice, bob, uri):
        """
        The "hashed resource authentication code".

        A hash of:
        * Alice's public key
        * Bob's public key
        * the uri

        Alice and Bob have all the information they need to construct this.
        Ursula does not, so we share it with her.
        """
        return keccak_digest(bytes(alice.stamp) + bytes(bob.stamp) + uri)
Example #13
0
    def _derive_path_key(
        self,
        path: bytes,
    ) -> bytes:
        """
        Derives a key for the specific path.

        :param path: Path to derive key for

        :return: Derived key
        """
        priv_key = API.keccak_digest(self.priv_key, path)
        pub_key = API.ecies_priv2pub(priv_key)
        return (priv_key, pub_key)
Example #14
0
    def sign(self, *messages):
        """
        Signs a message and returns a signature with the keccak hash.
        :param Iterable messages: Messages to sign in an iterable of bytes
        :rtype: bytestring
        :return: Signature of message
        """
        try:
            sig_keypair = self._power_ups[SigningPower]
        except KeyError as e:
            raise NoSigningPower(e)
        msg_digest = b"".join(API.keccak_digest(m) for m in messages)

        return sig_keypair.sign(msg_digest)
Example #15
0
    def determine_legality_of_dht_key(self, signature, sender_pubkey_sig,
                                      message, hrac, dht_key, dht_value):
        proper_key = digest(
            keccak_digest(bytes(sender_pubkey_sig) + bytes(hrac)))

        verified = signature.verify(hrac, sender_pubkey_sig)

        if not verified or not proper_key == dht_key:
            self.log.warning(
                "Got request to store illegal k/v: {} / {}".format(
                    dht_key, dht_value))
            self.illegal_keys_seen.append(dht_key)
            return False
        else:
            return True
Example #16
0
 def join_policy(self,
                 label,
                 alice_pubkey_sig,
                 using_dht=False,
                 node_list=None,
                 verify_sig=True):
     hrac = keccak_digest(
         bytes(alice_pubkey_sig) + bytes(self.stamp) + label)
     if node_list:
         self.network_bootstrap(node_list)
     self.get_treasure_map(alice_pubkey_sig,
                           hrac,
                           using_dht=using_dht,
                           verify_sig=verify_sig)
     self.follow_treasure_map(hrac, using_dht=using_dht)
    def verify(self, message: bytes, pubkey: PublicKey) -> bool:
        """
        Verifies that a message's signature was valid.

        :param message: The message to verify
        :param pubkey: Pubkey of the signer

        :return: True if valid, False if invalid
        """
        if not len(pubkey) == PublicKey._EXPECTED_LENGTH:
            raise TypeError(
                "Need a PublicKey of {} bytes to verify - got {}.".format(
                    PublicKey._EXPECTED_LENGTH, len(pubkey)))
        msg_digest = API.keccak_digest(message)
        return API.ecdsa_verify(self._v, self._r, self._s, msg_digest,
                                pubkey.without_metabytes())
Example #18
0
def test_actor_with_signing_power_can_sign():
    """
    However, simply giving that character a PowerUp bestows the power to sign.

    Instead of having a Character verify the signature, we'll use the lower level API.
    """
    message = b"Llamas."

    signer = Character(crypto_power_ups=[SigningPower])
    seal_of_the_signer = signer.seal

    # We can use the signer's seal to sign a message...
    signature = seal_of_the_signer(message)

    # ...or to get the signer's public key for verification purposes.
    sig = api.ecdsa_load_sig(signature)
    verification = api.ecdsa_verify(*sig, api.keccak_digest(message), seal_of_the_signer)

    assert verification is True
Example #19
0
def test_grant(alice, bob, ursulas):
    networky_stuff = MockNetworkyStuff(ursulas)
    policy_end_datetime = datetime.datetime.now() + datetime.timedelta(days=5)
    n = 5
    uri = b"this_is_the_path_to_which_access_is_being_granted"
    policy = alice.grant(bob,
                         uri,
                         networky_stuff,
                         m=3,
                         n=n,
                         expiration=policy_end_datetime)

    # The number of policies is equal to the number of Ursulas we're using (n)
    assert len(policy._accepted_contracts) == n

    # Let's look at the first Ursula.
    ursula = list(policy._accepted_contracts.values())[0].ursula

    # Get the kfrag, based in the hrac.
    proper_hrac = keccak_digest(bytes(alice.seal) + bytes(bob.seal) + uri)
    kfrag_that_was_set = ursula.keystore.get_kfrag(proper_hrac)
    assert kfrag_that_was_set
Example #20
0
    def determine_legality_of_dht_key(self, signature, sender_pubkey_sig,
                                      message, hrac, dht_key, dht_value):

        # TODO: This function can use a once-over.
        # TODO: Push the logic of this if branch down.
        if dht_value[:8] == constants.BYTESTRING_IS_URSULA_IFACE_INFO:
            proper_key = digest(bytes(sender_pubkey_sig))
        else:
            proper_key = digest(
                keccak_digest(bytes(sender_pubkey_sig) + bytes(hrac)))

        verified = signature.verify(hrac, sender_pubkey_sig)

        if not verified or not proper_key == dht_key:
            # Hachidan Kiritsu, it's illegal!
            self.log.warning(
                "Got request to store illegal k/v: {} / {}".format(dht_key,
                                                                   dht_value))
            self.illegal_keys_seen.append(dht_key)
            return False
        else:
            return True
Example #21
0
    def get_treasure_map(self,
                         alice_pubkey_sig,
                         hrac,
                         using_dht=False,
                         verify_sig=True):
        map_id = keccak_digest(alice_pubkey_sig + hrac)

        if using_dht:
            ursula_coro = self.server.get(map_id)
            event_loop = asyncio.get_event_loop()
            packed_encrypted_treasure_map = event_loop.run_until_complete(
                ursula_coro)
        else:
            if not self.known_nodes:
                # TODO: Try to find more Ursulas on the blockchain.
                raise self.NotEnoughUrsulas
            tmap_message_kit = self.get_treasure_map_from_known_ursulas(
                self.network_middleware, map_id)

        if verify_sig:
            alice = Alice.from_public_keys({SigningPower: alice_pubkey_sig})
            verified, packed_node_list = self.verify_from(alice,
                                                          tmap_message_kit,
                                                          decrypt=True)
        else:
            assert False

        if not verified:
            return constants.NOT_FROM_ALICE
        else:
            from nkms.policy.models import TreasureMap
            node_list = msgpack.loads(packed_node_list)
            m = node_list.pop()
            treasure_map = TreasureMap(m=m, ursula_interface_ids=node_list)
            self.treasure_maps[hrac] = treasure_map
            return treasure_map
Example #22
0
 def __bytes__(self):
     return keccak_digest(self.pubkey_sig_bytes + self.interface_hrac)
Example #23
0
def fingerprint_from_key(public_key: Any):
    """
    Hashes a key using keccak-256 and returns the hexdigest in bytes.
    :return: Hexdigest fingerprint of key (keccak-256) in bytes
    """
    return keccak_digest(bytes(public_key)).hex().encode()
Example #24
0
 def set_id(self):
     if self.deterministic_id_portion:
         self._id = "{}-{}".format(api.keccak_digest(*[str(d).encode() for d in self.deterministic_id_portion], self.random_id_portion),
                                   api.keccak_digest(self.random_id_portion))
     else:
         self._id = api.keccak_digest(self.random_id_portion)
Example #25
0
 def interface_hrac(self):
     return keccak_digest(msgpack.dumps(self.dht_interface_info()))
Example #26
0
 def hash(message):
     return keccak_digest(message)
Example #27
0
    def hash(self, pubkey_sig_alice, hash_input):

        self.hashed_part = api.keccak_digest(hash_input)
        hash_input_for_id = str(pubkey_sig_alice).encode() + str(self.hashed_part).encode()
        self._id = api.keccak_digest(hash_input_for_id)
        return self._id
Example #28
0
 def id(self):
     if not self._id:
         self._id = api.keccak_digest(self.uri, bytes(self.bob.seal))
     return self._id
Example #29
0
 def interface_info_with_metadata(self):
     interface_info = self.interface_information()
     signature = self.stamp(keccak_digest(interface_info))
     return constants.BYTESTRING_IS_URSULA_IFACE_INFO + signature + self.stamp + interface_info
    def test_ecdsa_keypair_signing(self):
        msghash = API.keccak_digest(b'hello world!')

        sig = self.ecdsa_keypair.sign(msghash)
        self.assertEqual(bytes, type(sig))
        self.assertEqual(65, len(sig))