def test_enrico_web_character_control_encrypt_message( enrico_web_controller_test_client, encrypt_control_request): method_name, params = encrypt_control_request endpoint = f'/{method_name}' response = enrico_web_controller_test_client.post(endpoint, data=json.dumps(params)) assert response.status_code == 200 response_data = json.loads(response.data) assert 'message_kit' in response_data['result'] # Check that it serializes correctly. MessageKit.from_bytes(b64decode(response_data['result']['message_kit'])) # Send bad data to assert error return response = enrico_web_controller_test_client.post('/encrypt_message', data=json.dumps( {'bad': 'input'})) assert response.status_code == 400 bad_params = dict(params) del (bad_params['message']) response = enrico_web_controller_test_client.post('/encrypt_message', data=bad_params) assert response.status_code == 400
def _deserialize(self, value, attr, data, **kwargs): try: message_kit_bytes = super()._deserialize(value, attr, data, **kwargs) return MessageKitClass.from_bytes(message_kit_bytes) except Exception as e: raise InvalidInputData( f"Could not parse {self.name} as MessageKit: {e}")
def decrypt_message_kit(self, message_kit: MessageKit) -> bytes: """ Decrypt data encrypted with Umbral. :return: bytes """ try: return message_kit.decrypt(self._privkey) except ValueError as e: raise self.DecryptionFailed() from e
def test_retrieval_kit_field(get_random_checksum_address): field = RetrievalKit() def run_tests_on_kit(kit: RetrievalKitClass): serialized = field._serialize(value=kit, attr=None, obj=None) assert serialized == b64encode(bytes(kit)).decode() deserialized = field._deserialize(value=serialized, attr=None, data=None) assert isinstance(deserialized, RetrievalKitClass) assert deserialized.capsule == kit.capsule assert deserialized.queried_addresses == kit.queried_addresses # kit with list of ursulas encrypting_key = SecretKey.random().public_key() capsule = MessageKit(encrypting_key, b'testing retrieval kit with 2 ursulas').capsule ursulas = [get_random_checksum_address(), get_random_checksum_address()] run_tests_on_kit(kit=RetrievalKitClass( capsule, {to_canonical_address(ursula) for ursula in ursulas})) # kit with no ursulas encrypting_key = SecretKey.random().public_key() capsule = MessageKit(encrypting_key, b'testing retrieval kit with no ursulas').capsule run_tests_on_kit(kit=RetrievalKitClass(capsule, set())) with pytest.raises(InvalidInputData): field._deserialize(value=b"non_base_64_data", attr=None, data=None) with pytest.raises(InvalidInputData): field._deserialize( value=b64encode(b"invalid_retrieval_kit_bytes").decode(), attr=None, data=None)
def fragments(): delegating_privkey = SecretKey.random() delegating_pubkey = delegating_privkey.public_key() signing_privkey = SecretKey.random() signer = Signer(signing_privkey) priv_key_bob = SecretKey.random() pub_key_bob = priv_key_bob.public_key() kfrags = generate_kfrags(delegating_sk=delegating_privkey, signer=signer, receiving_pk=pub_key_bob, threshold=2, shares=4, sign_delegating_key=False, sign_receiving_key=False) capsule = MessageKit(delegating_pubkey, b'unused').capsule cfrag = reencrypt(capsule, kfrags[0]) return capsule, cfrag
def test_message_kit(enacted_federated_policy, federated_alice): # Setup enrico = Enrico.from_alice(federated_alice, label=enacted_federated_policy.label) message = 'this is a message' plaintext_bytes = bytes(message, encoding='utf-8') message_kit = enrico.encrypt_message(plaintext=plaintext_bytes) message_kit_bytes = bytes(message_kit) message_kit = MessageKitClass.from_bytes(message_kit_bytes) # Test field = MessageKit() serialized = field._serialize(value=message_kit, attr=None, obj=None) assert serialized == b64encode(bytes(message_kit)).decode() deserialized = field._deserialize(value=serialized, attr=None, data=None) deserialized_plaintext = federated_alice.decrypt_message_kit(enacted_federated_policy.label, deserialized)[0] assert deserialized_plaintext == plaintext_bytes with pytest.raises(InvalidInputData): field._deserialize(value=b"MessageKit", attr=None, data=None)
def test_message_kit_serialization_via_enrico(federated_alice): mock_label = b'this is a label' # Enrico enrico = Enrico.from_alice(federated_alice, label=mock_label) # Plaintext message = 'this is a message' plaintext_bytes = bytes(message, encoding='utf-8') # Create message_kit = enrico.encrypt_message(plaintext=plaintext_bytes) # Serialize message_kit_bytes = bytes(message_kit) # Deserialize the_same_message_kit = MessageKit.from_bytes(message_kit_bytes) # Confirm assert message_kit_bytes == bytes(the_same_message_kit)
def encrypt_for( self, recipient: 'Character', plaintext: bytes, ) -> MessageKit: """ Encrypts plaintext for recipient actor. Optionally signs the message as well. :param recipient: The character whose public key will be used to encrypt cleartext. :param plaintext: The secret to be encrypted. :param sign_plaintext: the cleartext is signed if this is True, Otherwise, the resulting ciphertext is signed. :return: the message kit. """ # TODO: who even uses this method except for tests? message_kit = MessageKit( policy_encrypting_key=recipient.public_keys(DecryptingPower), plaintext=plaintext) return message_kit
policy_data = json.load(f) policy_pubkey = PublicKey.from_bytes( bytes.fromhex(policy_data["policy_pubkey"])) alices_sig_pubkey = PublicKey.from_bytes( bytes.fromhex(policy_data["alice_sig_pubkey"])) label = policy_data["label"].encode() treasure_map = EncryptedTreasureMap.from_bytes( base64.b64decode(policy_data["treasure_map"].encode())) # The Doctor can retrieve encrypted data which he can decrypt with his private key. # But first we need some encrypted data! # Let's read the file produced by the heart monitor and unpack the MessageKits, # which are the individual ciphertexts. data = msgpack.load(open("heart_data.msgpack", "rb"), raw=False) message_kits = (MessageKit.from_bytes(k) for k in data['kits']) # Now he can ask the NuCypher network to get a re-encrypted version of each MessageKit. for message_kit in message_kits: start = timer() retrieved_plaintexts = doctor.retrieve_and_decrypt( [message_kit], alice_verifying_key=alices_sig_pubkey, encrypted_treasure_map=treasure_map) end = timer() plaintext = msgpack.loads(retrieved_plaintexts[0], raw=False) # Now we can get the heart rate and the associated timestamp, # generated by the heart rate monitor. heart_rate = plaintext['heart_rate']
def test_web_character_control_lifecycle(alice_web_controller_test_client, bob_web_controller_test_client, enrico_web_controller_from_alice, blockchain_alice, blockchain_bob, blockchain_ursulas, random_policy_label): random_label = random_policy_label.decode() # Unicode string bob_keys_response = bob_web_controller_test_client.get('/public_keys') assert bob_keys_response.status_code == 200 response_data = json.loads(bob_keys_response.data) assert str(nucypher.__version__) == response_data['version'] bob_keys = response_data['result'] assert 'bob_encrypting_key' in bob_keys assert 'bob_verifying_key' in bob_keys bob_encrypting_key_hex = bob_keys['bob_encrypting_key'] bob_verifying_key_hex = bob_keys['bob_verifying_key'] # Create a policy via Alice control alice_request_data = { 'bob_encrypting_key': bob_encrypting_key_hex, 'bob_verifying_key': bob_verifying_key_hex, 'threshold': 1, 'shares': 1, 'label': random_label, 'expiration': (maya.now() + datetime.timedelta(days=35)).iso8601(), 'value': 3 * 10**10 } response = alice_web_controller_test_client.put( '/grant', data=json.dumps(alice_request_data)) assert response.status_code == 200 # Check Response Keys alice_response_data = json.loads(response.data) assert 'treasure_map' in alice_response_data['result'] assert 'policy_encrypting_key' in alice_response_data['result'] assert 'alice_verifying_key' in alice_response_data['result'] assert 'version' in alice_response_data assert str(nucypher.__version__) == alice_response_data['version'] # This is sidechannel policy metadata. It should be given to Bob by the # application developer at some point. alice_verifying_key_hex = alice_response_data['result'][ 'alice_verifying_key'] # Encrypt some data via Enrico control # Alice will also be Enrico via Enrico.from_alice # (see enrico_control_from_alice fixture) plaintext = "I'm bereaved, not a sap!" # type: str enrico_request_data = { 'message': b64encode(bytes(plaintext, encoding='utf-8')).decode(), } response = enrico_web_controller_from_alice.post( '/encrypt_message', data=json.dumps(enrico_request_data)) assert response.status_code == 200 enrico_response_data = json.loads(response.data) assert 'message_kit' in enrico_response_data['result'] kit_bytes = b64decode( enrico_response_data['result']['message_kit'].encode()) bob_message_kit = MessageKit.from_bytes(kit_bytes) # Retrieve data via Bob control encoded_message_kit = b64encode(bytes(bob_message_kit)).decode() bob_request_data = { 'alice_verifying_key': alice_verifying_key_hex, 'message_kits': [encoded_message_kit], 'encrypted_treasure_map': alice_response_data['result']['treasure_map'] } # Give bob a node to remember teacher = list(blockchain_ursulas)[1] blockchain_bob.remember_node(teacher) response = bob_web_controller_test_client.post( '/retrieve_and_decrypt', data=json.dumps(bob_request_data)) assert response.status_code == 200 bob_response_data = json.loads(response.data) assert 'cleartexts' in bob_response_data['result'] for cleartext in bob_response_data['result']['cleartexts']: assert b64decode(cleartext.encode()).decode() == plaintext