def create_from_message(cls, message: MessageBase, signing_key: str, verifying_key: str=None, uuid: int=-1): """ Creates an Envelope to package a MessageBase instance :param message: The MessageBase instance to create an envelope for :param signing_key: The sender's signing key, which is used to create the Seal. :param verifying_key: The sender's verifying key. This should be passed in for computational efficiency, but can be computed from the signing key if it is ommited :param uuid: The UUID to use for the Envelope's MessageMeta. If -1, a random UUID will be generated. :return: An Envelope instance """ assert issubclass(type(message), MessageBase), "message arg must be a MessageBase subclass" assert type(message) in MessageBase.registry, "Message type {} not found in registry {}"\ .format(type(message), MessageBase.registry) # TODO -- verify sk (valid hex, 128 char) # Create MessageMeta t = MessageBase.registry[type(message)] timestamp = str(time.time()) meta = MessageMeta.create(type=t, timestamp=timestamp, uuid=uuid) # Create Seal if not verifying_key: verifying_key = Constants.Protocol.Wallets.get_vk(signing_key) seal_sig = EnvelopeAuth.seal(signing_key=signing_key, meta=meta, message=message) seal = Seal.create(signature=seal_sig, verifying_key=verifying_key) # Create Envelope obj = cls._create_from_objects(seal=seal, meta=meta, message=message.serialize()) set_lazy_property(obj, 'message', message) return obj
def create_from_message(cls, message: MessageBase, signing_key: str, verifying_key: str = None, uuid: int = -1): assert issubclass( type(message), MessageBase), "message arg must be a MessageBase subclass" assert type(message) in MessageBase.registry, "Message type {} not found in registry {}"\ .format(type(message), MessageBase.registry) # TODO -- verify sk (valid hex, 128 char) # Create MessageMeta t = MessageBase.registry[type(message)] timestamp = str(time.time()) meta = MessageMeta.create(type=t, timestamp=timestamp, uuid=uuid) # Create Seal if not verifying_key: verifying_key = Constants.Protocol.Wallets.get_vk(signing_key) seal_sig = EnvelopeAuth.seal(signing_key=signing_key, meta=meta, message=message) seal = Seal.create(signature=seal_sig, verifying_key=verifying_key) # Create Envelope obj = cls.create_from_objects(seal=seal, meta=meta, message=message.serialize()) set_lazy_property(obj, 'message', message) return obj
def send_request_env(self, envelope: Envelope, timeout=0, ip: str='', vk: str=''): url = "tcp://{}:{}".format(ip or vk, router_dealer) reply_uuid = EnvelopeAuth.reply_uuid(envelope.meta.uuid) cmd = ReactorCommand.create_cmd(DealerRouterExecutor.__name__, DealerRouterExecutor.request.__name__, url=url, envelope=envelope, timeout=timeout, reply_uuid=reply_uuid) self.interface.send_cmd(cmd)
def verify_seal(self) -> bool: """ Validates the cryptographic signature on the envelope's seal. The signature should be the MessageMeta binary concatenated with the MessageBase binary signed by the sender. :return: A bool, True is the Seal's signature is valid, and False otherwise """ return EnvelopeAuth.verify_seal(seal=self.seal, meta=self.meta_binary, message=self.message_binary)
def test_validate_bad_metadata(self): meta = b'lol' 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) self.assertRaises(Exception, Envelope.create_from_objects, seal, meta, message.serialize())
def send_request_env(self, envelope: Envelope, timeout=0, protocol: str = 'tcp', port: int = ROUTER_PORT, vk: str = '', ip: str = ''): url = self._build_url(protocol=protocol, port=port, ip=ip, vk=vk) reply_uuid = EnvelopeAuth.reply_uuid(envelope.meta.uuid) self.manager.executors['DealerRouterExecutor'].request( url=url, envelope=envelope, timeout=timeout, reply_uuid=reply_uuid)
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())
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)
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())
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()
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()
def verify_seal(self): return EnvelopeAuth.verify_seal(seal=self.seal, meta=self.meta_binary, message=self.message_binary)