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
def verify_from( self, stranger: 'Character', message_kit: Union[UmbralMessageKit, bytes], signature: Signature = None, decrypt=False, delegator_signing_key: UmbralPublicKey = None, ) -> 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 message_kit: the message to be (perhaps decrypted and) verified. :param signature: The signature to check. :param decrypt: Whether or not to decrypt the messages. :param delegator_signing_key: A signing key from the original delegator. This is used only when decrypting a MessageKit with an activated Capsule to check that the KFrag used to create each attached CFrag is the authentic KFrag initially created by the delegator. :return: Whether or not the signature is valid, the decrypted plaintext or NO_DECRYPTION_PERFORMED """ sender_pubkey_sig = stranger.stamp.as_umbral_pubkey() with suppress(AttributeError): if message_kit.sender_pubkey_sig: if not message_kit.sender_pubkey_sig == sender_pubkey_sig: raise ValueError( "This MessageKit doesn't appear to have come from {}". format(stranger)) signature_from_kit = None if decrypt: # We are decrypting the message; let's do that first and see what the sig header says. cleartext_with_sig_header = self.decrypt( message_kit, verifying_key=delegator_signing_key) sig_header, cleartext = default_constant_splitter( cleartext_with_sig_header, return_remainder=True) if sig_header == constants.SIGNATURE_IS_ON_CIPHERTEXT: # THe ciphertext is what is signed - note that for later. message = message_kit.ciphertext if not signature: raise ValueError( "Can't check a signature on the ciphertext if don't provide one." ) elif sig_header == constants.SIGNATURE_TO_FOLLOW: # The signature follows in this cleartext - split it off. signature_from_kit, cleartext = signature_splitter( cleartext, return_remainder=True) message = cleartext else: # Not decrypting - the message is the object passed in as a message kit. Cast it. message = bytes(message_kit) cleartext = constants.NO_DECRYPTION_PERFORMED if signature and signature_from_kit: if signature != signature_from_kit: raise ValueError( "The MessageKit has a Signature, but it's not the same one you provided. Something's up." ) signature_to_use = signature or signature_from_kit if signature_to_use: is_valid = signature_to_use.verify(message, sender_pubkey_sig) if not is_valid: raise stranger.InvalidSignature( "Signature for message isn't valid: {}".format( signature_to_use)) else: raise self.InvalidSignature( "No signature provided -- signature presumed invalid.") # # Next we have decrypt() and sign() - these use the private # keys of their respective powers; any character who has these powers can use these functions. # # If they don't have the correct Power, the appropriate PowerUpError is raised. # return cleartext
def verify_from( self, stranger: 'Character', message_kit: Union[UmbralMessageKit, bytes], signature: Signature = None, decrypt=False, label=None, ) -> bytes: """ Inverse of encrypt_for. :param stranger: 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 message_kit: the message to be (perhaps decrypted and) verified. :param signature: The signature to check. :param decrypt: Whether or not to decrypt the messages. :return: Whether or not the signature is valid, the decrypted plaintext or NO_DECRYPTION_PERFORMED """ sender_pubkey_sig = stranger.stamp.as_umbral_pubkey() with suppress(AttributeError): if message_kit.sender_pubkey_sig: if not message_kit.sender_pubkey_sig == sender_pubkey_sig: raise ValueError( "This MessageKit doesn't appear to have come from {}". format(stranger)) signature_from_kit = None if decrypt: # We are decrypting the message; let's do that first and see what the sig header says. cleartext_with_sig_header = self.decrypt(message_kit=message_kit, label=label) sig_header, cleartext = default_constant_splitter( cleartext_with_sig_header, return_remainder=True) if sig_header == SIGNATURE_IS_ON_CIPHERTEXT: # THe ciphertext is what is signed - note that for later. message = message_kit.ciphertext if not signature: raise ValueError( "Can't check a signature on the ciphertext if don't provide one." ) elif sig_header == SIGNATURE_TO_FOLLOW: # The signature follows in this cleartext - split it off. signature_from_kit, cleartext = signature_splitter( cleartext, return_remainder=True) message = cleartext else: # Not decrypting - the message is the object passed in as a message kit. Cast it. message = bytes(message_kit) cleartext = NO_DECRYPTION_PERFORMED if signature and signature_from_kit: if signature != signature_from_kit: raise ValueError( "The MessageKit has a Signature, but it's not the same one you provided. Something's up." ) signature_to_use = signature or signature_from_kit if signature_to_use: is_valid = signature_to_use.verify(message, sender_pubkey_sig) if not is_valid: raise stranger.InvalidSignature( "Signature for message isn't valid: {}".format( signature_to_use)) else: raise self.InvalidSignature( "No signature provided -- signature presumed invalid.") return cleartext
def verify_from( self, stranger: 'Character', message_kit: Union[UmbralMessageKit, bytes], signature: Signature = None, decrypt=False, label=None, ) -> bytes: """ Inverse of encrypt_for. :param stranger: 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 message_kit: the message to be (perhaps decrypted and) verified. :param signature: The signature to check. :param decrypt: Whether or not to decrypt the messages. :param label: A label used for decrypting messages encrypted under its associated policy encrypting key :return: Whether or not the signature is valid, the decrypted plaintext or NO_DECRYPTION_PERFORMED """ # # Optional Sanity Check # # In the spirit of duck-typing, we want to accept a message kit object, or bytes # If the higher-order object MessageKit is passed, we can perform an additional # eager sanity check before performing decryption. with contextlib.suppress(AttributeError): sender_verifying_key = stranger.stamp.as_umbral_pubkey() if message_kit.sender_verifying_key: if not message_kit.sender_verifying_key == sender_verifying_key: raise ValueError( "This MessageKit doesn't appear to have come from {}". format(stranger)) # # Decrypt # signature_from_kit = None if decrypt: # We are decrypting the message; let's do that first and see what the sig header says. cleartext_with_sig_header = self.decrypt(message_kit=message_kit, label=label) sig_header, cleartext = default_constant_splitter( cleartext_with_sig_header, return_remainder=True) if sig_header == SIGNATURE_IS_ON_CIPHERTEXT: # The ciphertext is what is signed - note that for later. message = message_kit.ciphertext if not signature: raise ValueError( "Can't check a signature on the ciphertext if don't provide one." ) elif sig_header == SIGNATURE_TO_FOLLOW: # The signature follows in this cleartext - split it off. signature_from_kit, cleartext = signature_splitter( cleartext, return_remainder=True) message = cleartext else: # Not decrypting - the message is the object passed in as a message kit. Cast it. message = bytes(message_kit) cleartext = NO_DECRYPTION_PERFORMED # # Verify Signature # if signature and signature_from_kit: if signature != signature_from_kit: raise ValueError( "The MessageKit has a Signature, but it's not the same one you provided. Something's up." ) signature_to_use = signature or signature_from_kit if signature_to_use: is_valid = signature_to_use.verify( message, sender_verifying_key) # FIXME: Message is undefined here if not is_valid: raise InvalidSignature( "Signature for message isn't valid: {}".format( signature_to_use)) else: raise InvalidSignature( "No signature provided -- signature presumed invalid.") return cleartext
def verify_from( self, actor_whom_sender_claims_to_be: "Character", message_kit: Union[UmbralMessageKit, bytes], signature: Signature = None, decrypt=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 """ sender_pubkey_sig = actor_whom_sender_claims_to_be.stamp.as_umbral_pubkey( ) with suppress(AttributeError): if message_kit.sender_pubkey_sig: if not message_kit.sender_pubkey_sig == sender_pubkey_sig: raise ValueError( "This MessageKit doesn't appear to have come from {}". format(actor_whom_sender_claims_to_be)) signature_from_kit = None if decrypt: # We are decrypting the message; let's do that first and see what the sig header says. cleartext_with_sig_header = self.decrypt(message_kit) sig_header, cleartext = default_constant_splitter( cleartext_with_sig_header, return_remainder=True) if sig_header == constants.SIGNATURE_IS_ON_CIPHERTEXT: # THe ciphertext is what is signed - note that for later. message = message_kit.ciphertext if not signature: raise ValueError( "Can't check a signature on the ciphertext if don't provide one." ) elif sig_header == constants.SIGNATURE_TO_FOLLOW: # The signature follows in this cleartext - split it off. signature_from_kit, cleartext = signature_splitter( cleartext, return_remainder=True) message = cleartext else: # Not decrypting - the message is the object passed in as a message kit. Cast it. message = bytes(message_kit) cleartext = constants.NO_DECRYPTION_PERFORMED if signature and signature_from_kit: if signature != signature_from_kit: raise ValueError( "The MessageKit has a Signature, but it's not the same one you provided. Something's up." ) signature_to_use = signature or signature_from_kit if signature_to_use: is_valid = signature_to_use.verify(message, sender_pubkey_sig) else: # Meh, we didn't even get a signature. Not much we can do. is_valid = False return is_valid, cleartext