Example #1
0
    def test_serialize_from_objects(self):
        """
        Tests that serialize/deserialize are inverse operations with from_objects factory function
        """
        sk, vk = W.new()
        message = self._default_msg()

        env = Envelope.create_from_message(message=message, signing_key=sk, verifying_key=vk)

        self.assertEqual(env, Envelope.from_bytes(env.serialize()))
Example #2
0
    def _validate_envelope(self, envelope_binary: bytes, header: str) -> Union[None, Envelope]:
        # TODO return/raise custom exceptions in this instead of just logging stuff and returning none

        # Deserialize envelope
        env = None
        try:
            env = Envelope.from_bytes(envelope_binary)
        except Exception as e:
            self.log.error("\n\n\nError deserializing envelope: {}\n\n\n".format(e))
            return None

        # Check seal
        if not env.verify_seal():
            self.log.error("\n\n\nSeal could not be verified for envelope {}\n\n\n".format(env))
            return None

        # If header is not none (meaning this is a ROUTE msg with an ID frame), then verify that the ID frame is
        # the same as the vk on the seal
        if header and (header != env.seal.verifying_key):
            self.log.error("\n\n\nHeader frame {} does not match seal's vk {}\nfor envelope {}\n\n\n"
                           .format(header, env.seal.verifying_key, env))
            return None

        # Make sure we haven't seen this message before
        if env.meta.uuid in Executor._recently_seen:
            self.log.warning("Duplicate envelope detect with UUID {}. Ignoring.".format(env.meta.uuid))
            return None

        # TODO -- checks timestamp to ensure this envelope is recv'd in a somewhat reasonable time (within N seconds)

        # If none of the above checks above return None, this envelope should be good
        return env
Example #3
0
    def create(cls,
               envelope: Envelope = None,
               envelope_binary: bytes = None,
               **kwargs):
        assert not (
            envelope and envelope_binary
        ), "Either envelope or envelope_binary should be passed in (not both)"

        cmd = reactor_capnp.ReactorCommand.new_message()

        if envelope:
            assert isinstance(
                envelope,
                Envelope), "'envelope' kwarg must be an Envelope instance"
            cmd.envelope.data = envelope.serialize()
        if envelope_binary:
            assert isinstance(envelope_binary,
                              bytes), "'envelope_binary' must be bytes"
            cmd.envelope.data = envelope_binary

        cmd.init('kwargs', len(kwargs))
        for i, key in enumerate(kwargs):
            cmd.kwargs[i].key, cmd.kwargs[i].value = str(key), str(kwargs[key])

        return cls.from_data(cmd)
Example #4
0
 def run(self):
     count = 0
     while count < NUM_SENDS:
         time.sleep(SEND_RATE)
         self.log.critical("Stu sending stab")
         stab = Stab.from_data("stab #{}".format(count))
         self.parent.reactor.pub(url=URL2, data=Envelope.create(stab))
         count += 1
Example #5
0
    def send_pub(self, filter: str, envelope: bytes):
        assert isinstance(filter, str), "'id' arg must be a string"
        assert isinstance(envelope, bytes), "'envelope' arg must be bytes"
        assert len(self.pubs) > 0, "Attempted to publish data but publisher socket(s) is not configured"

        for url in self.pubs:
            self.log.debug("Publishing to URL {} with envelope: {}".format(url, Envelope.from_bytes(envelope)))
            # self.log.info("Publishing to... {}".format(url))
            self.pubs[url].send_multipart([filter.encode(), envelope])
Example #6
0
    def _package_msg(self, msg: MessageBase) -> Envelope:
        """
        Convenience method to package a message into an envelope
        :param msg: The MessageBase instance to package
        :return: An Envelope instance
        """
        assert type(msg) is not Envelope, "Attempted to package a 'message' that is already an envelope"
        assert issubclass(type(msg), MessageBase), "Attempted to package a message that is not a MessageBase subclass"

        return Envelope.create_from_message(message=msg, signing_key=self.signing_key, verifying_key=self.verifying_key)
Example #7
0
    def recv_poke_req(self, poke: PokeRequest, id):
        self.log.critical("Stu got poke {}, but waiting {} seconds...".format(REPLY_WAIT))
        time.sleep(REPLY_WAIT)
        self.log.critical("Stu replying to poke <{}> with id {}".format(poke, id))
        reply = PokeReply.from_data("yoyo this is my reply to {}".format(poke))

        stab = Stab.from_data("stab!")
        self.parent.reactor.pub(url=URL2, data=Envelope.create(stab))

        return reply
Example #8
0
    def _recv_reply_env(self, header: str, envelope: Envelope):
        self.log.debug("Recv REPLY envelope with header {} and envelope {}".format(header, envelope))

        reply_uuid = envelope.meta.uuid
        if reply_uuid in self.expected_replies:
            self.log.debug("Removing reply with uuid {} from expected replies".format(reply_uuid))
            self.expected_replies[reply_uuid].cancel()
            del(self.expected_replies[reply_uuid])

        self.call_on_mp(callback=StateInput.INPUT, header=header, envelope_binary=envelope.serialize())
Example #9
0
    def test_create_with_envelope(self):
        """
        Tests creating a message with an envelope produces an object with the expected properties
        """
        sk, vk = ED25519Wallet.new()
        tx = StandardTransactionBuilder.random_tx()
        sender = 'me'
        env = Envelope.create_from_message(message=tx, signing_key=sk)

        cmd = ReactorCommand.create_cmd('some_cls', 'some_func', envelope=env)

        self.assertTrue(ReactorCommand.envelope, env)
Example #10
0
    def test_create_from_message(self):
        """
        Tests create_from_message with valid args (no vk passed) creates an envelope valid signature and expected fields
        """
        sk, vk = W.new()
        msg = self._default_msg()

        env = Envelope.create_from_message(message=msg, signing_key=sk)

        self.assertTrue(env.verify_seal())
        self.assertEqual(env.message, msg)
        self.assertEqual(env.seal.verifying_key, vk)
Example #11
0
    def test_lazy_serialize(self):
        """
        Tests that creating an envelope from_bytes does not try to repack the underlying struct when serialize is called.
        This is b/c the serialize() func should be 'cached' with the binary data passed into from_bytes
        """
        sk, vk = W.new()
        message = self._default_msg()

        env = Envelope.create_from_message(message=message, signing_key=sk, verifying_key=vk)
        env_binary = env.serialize()

        clone = Envelope.from_bytes(env_binary)

        clone._data = MagicMock()

        clone_binary = clone.serialize()  # this should not pack the capnp struct (_data) again

        # The Envelope Kitchen Sink lol -- make sure no serialization related API is called
        clone._data.as_builder.assert_not_called()
        clone._data.to_bytes_packed.assert_not_called()
        clone._data.to_bytes.assert_not_called()
Example #12
0
    def test_create_from_objects(self):
        """
        Test that create returns an object with expected properties
        """
        seal = self._default_seal()
        meta = self._default_meta()
        message = self._default_msg()

        env = Envelope.create_from_objects(seal=seal, meta=meta, message=message.serialize())

        self.assertEqual(env.seal, seal)
        self.assertEqual(env.meta, meta)
        self.assertEqual(env.message, message)
Example #13
0
    def test_validate_bad_seal(self):
        meta = self._default_meta()
        message = self._default_msg()
        sk, vk = W.new()
        sk2, vk2 = W.new()

        signature = EnvelopeAuth.seal(signing_key=sk, meta=meta, message=message)

        seal = Seal.create(signature=signature, verifying_key=vk2)

        env = Envelope.create_from_objects(seal=seal, meta=meta, message=message.serialize())

        self.assertFalse(env.verify_seal())
Example #14
0
    def route(self, msg_binary: bytes):
        msg = None
        try:
            envelope = Envelope.from_bytes(msg_binary)
            msg = envelope.open()
        except Exception as e:
            self.log.error("Error opening envelope: {}".format(e))

        if type(msg) in self._receivers:
            self.log.debug("Routing msg: {}".format(msg))
            self._receivers[type(msg)](self, msg)
        else:
            self.log.error("Message {} has no implemented receiver in {}".format(msg, self._receivers))
Example #15
0
    def test_verify_seal(self):
        """
        Tests verify seal with a valid signature
        """
        meta = self._default_meta()
        message = self._default_msg()
        sk, vk = W.new()

        signature = EnvelopeAuth.seal(signing_key=sk, meta=meta, message=message)
        seal = Seal.create(signature=signature, verifying_key=vk)

        env = Envelope.create_from_message(message=message, signing_key=sk, verifying_key=vk)

        self.assertTrue(env.verify_seal())
Example #16
0
    def _package_reply(self, reply: MessageBase, req_env: Envelope) -> Envelope:
        """
        Convenience method to create a reply envelope. The difference between this func and _package_msg, is that
        in the reply envelope the UUID must be the hash of the original request's uuid (not some randomly generated int)
        :param reply: The reply message (an instance of MessageBase)
        :param req_env: The original request envelope (an instance of Envelope)
        :return: An Envelope instance
        """
        self.log.debug("Creating REPLY envelope with msg type {} for request envelope {}".format(type(reply), req_env))
        request_uuid = req_env.meta.uuid
        reply_uuid = EnvelopeAuth.reply_uuid(request_uuid)

        return Envelope.create_from_message(message=reply, signing_key=self.signing_key,
                                            verifying_key=self.verifying_key, uuid=reply_uuid)
Example #17
0
    def test_validate_envelope(self):
        """
        Tests validate envelope function
        """
        meta = self._default_meta()
        message = self._default_msg()
        sk, vk = W.new()

        signature = EnvelopeAuth.seal(signing_key=sk, meta=meta, message=message)
        seal = Seal.create(signature=signature, verifying_key=vk)

        env = Envelope.create_from_objects(seal=seal, meta=meta, message=message.serialize())

        env.validate()
Example #18
0
    def test_verify_seal_invalid(self):
        """
        Tests verifying a seal with an invalid signature
        """
        meta = self._default_meta()
        message = self._default_msg()
        sk, vk = W.new()
        sk_prime = 'A' * 64

        signature = EnvelopeAuth.seal(signing_key=sk_prime, meta=meta, message=message)
        seal = Seal.create(signature=signature, verifying_key=vk)

        env = Envelope.create_from_objects(seal=seal, meta=meta, message=message.serialize())

        env.verify_seal()
Example #19
0
    def test_create_from_message_bad_keypair(self):
        """
        test create_from_message passing in sk does and incorrect vk
        """
        sk, vk = W.new()
        sk1, vk1 = W.new()
        msg = self._default_msg()
        sender = 'dat boi'

        env = Envelope.create_from_message(message=msg, signing_key=sk, verifying_key=vk)  # no error

        self.assertEqual(env.seal.verifying_key, vk)

        self.assertRaises(Exception, Envelope.create_from_message, msg, sk, sender, vk1)

        self.assertNotEqual(env.seal.verifying_key, vk1)
Example #20
0
 def envelope(self):
     if self._data.envelope.which() == 'unset':
         return None
     else:
         return Envelope.from_bytes(self._data.envelope.data)
Example #21
0
 def send_poke(self, poke_msg):
     poke = Poke.from_data(poke_msg)
     evl = Envelope.create(poke)
     self.reactor.pub(url=self.url, data=evl.serialize())
Example #22
0
 def _recv_request_env(self, header: str, envelope: Envelope):
     self.log.debug("Recv REQUEST envelope with header {} and envelope {}".format(header, envelope))
     self.call_on_mp(callback=StateInput.REQUEST, header=header, envelope_binary=envelope.serialize())
Example #23
0
 def _recv_pub_env(self, header: str, envelope: Envelope):
     self.log.debug("Recv'd pub envelope with header {} and env {}".format(header, envelope))
     self.call_on_mp(callback=StateInput.INPUT, envelope_binary=envelope.serialize())