mirror of https://github.com/nucypher/nucypher.git
183 lines
6.0 KiB
Python
183 lines
6.0 KiB
Python
import os
|
|
|
|
import pytest_twisted as pt
|
|
from twisted.internet import threads
|
|
|
|
from nucypher.cli.main import nucypher_cli
|
|
from nucypher.config.characters import AliceConfiguration
|
|
from nucypher.config.storages import NodeStorage
|
|
from nucypher.crypto.kits import UmbralMessageKit
|
|
from nucypher.crypto.powers import DecryptingPower, SigningPower
|
|
from nucypher.policy.models import TreasureMap
|
|
from nucypher.utilities.sandbox.constants import INSECURE_DEVELOPMENT_PASSWORD, TEMPORARY_DOMAIN
|
|
from nucypher.utilities.sandbox.ursula import start_pytest_ursula_services
|
|
|
|
|
|
class MockSideChannel:
|
|
|
|
class NoMessageKits(Exception):
|
|
pass
|
|
|
|
class NoTreasureMaps(Exception):
|
|
pass
|
|
|
|
class NoPolicies(Exception):
|
|
pass
|
|
|
|
class NoEnricos(Exception):
|
|
pass
|
|
|
|
def __init__(self):
|
|
self.__message_kits = []
|
|
self.__treasure_maps = []
|
|
self.__policies = []
|
|
self.__enricos = []
|
|
|
|
def save_message_kit(self, message_kit: UmbralMessageKit) -> None:
|
|
self.__message_kits.append(message_kit)
|
|
|
|
def fetch_message_kit(self) -> UmbralMessageKit:
|
|
if self.__message_kits:
|
|
message_kit = self.__message_kits.pop()
|
|
return message_kit
|
|
raise self.NoMessageKits
|
|
|
|
def save_treasure_map(self, treasure_map: TreasureMap) -> None:
|
|
self.__treasure_maps.append(treasure_map)
|
|
|
|
def fetch_treasure_map(self):
|
|
if self.__treasure_maps:
|
|
treasure_map = self.__treasure_maps.pop()
|
|
return treasure_map
|
|
raise self.NoTreasureMaps
|
|
|
|
def save_policy(self, policy):
|
|
self.__policies.append(policy)
|
|
|
|
def fetch_policy(self):
|
|
if self.__policies:
|
|
policy = self.__policies.pop()
|
|
return policy
|
|
raise self.NoPolicies
|
|
|
|
def save_enrico(self, enrico):
|
|
self.__enricos.append(enrico)
|
|
|
|
def load_enrico(self):
|
|
if self.__enricos:
|
|
enrico = self.__enricos.pop()
|
|
return enrico
|
|
raise self.NoEnricos
|
|
|
|
|
|
@pt.inlineCallbacks
|
|
def test_cli_lifecycle(click_runner,
|
|
random_policy_label,
|
|
federated_bob,
|
|
federated_alice,
|
|
federated_ursulas,
|
|
custom_filepath):
|
|
|
|
envvars = {'NUCYPHER_KEYRING_PASSWORD': INSECURE_DEVELOPMENT_PASSWORD}
|
|
|
|
#
|
|
# Scene 1: Alice installs nucypher, creates a policy, and saves the policy metadata to a sidechannel.
|
|
#
|
|
init_args = ('alice', 'init',
|
|
'--federated-only',
|
|
'--network', TEMPORARY_DOMAIN,
|
|
'--config-root', custom_filepath)
|
|
|
|
result = click_runner.invoke(nucypher_cli, init_args, catch_exceptions=False, env=envvars)
|
|
assert result.exit_code == 0
|
|
|
|
# Alice Derives a Policy
|
|
custom_config_file = os.path.join(custom_filepath, AliceConfiguration.CONFIG_FILENAME)
|
|
random_label = random_policy_label.decode() # Unicode string
|
|
derive_args = ('alice', 'derive-policy',
|
|
'--config-file', custom_config_file,
|
|
'--label', random_label)
|
|
|
|
result = click_runner.invoke(nucypher_cli, derive_args, catch_exceptions=False, env=envvars)
|
|
|
|
assert random_label in result.output
|
|
|
|
side_channel = MockSideChannel()
|
|
# side_channel.save_policy(policy=alice_response_data['result']['policy_encrypting_key'])
|
|
|
|
#
|
|
# Scene 2: We catch up with Alice later on, after she has learned about existing Ursulas
|
|
#
|
|
|
|
# Some Ursula is running somewhere
|
|
teacher = list(federated_ursulas)[1]
|
|
start_pytest_ursula_services(ursula=teacher)
|
|
|
|
# Alice has pre-existing stored node metadata
|
|
alice_known_nodes_dir = os.path.join(custom_filepath, 'known_nodes', 'metadata')
|
|
filename = f'{teacher.checksum_public_address}.node'
|
|
with open(os.path.join(alice_known_nodes_dir, filename), 'wb') as f:
|
|
f.write(NodeStorage.NODE_SERIALIZER(bytes(teacher)))
|
|
|
|
def _grant():
|
|
bob_encrypting_key_hex = bytes(federated_bob.public_keys(DecryptingPower)).hex()
|
|
bob_signing_key_hex = bytes(federated_bob.public_keys(SigningPower)).hex()
|
|
|
|
grant_args = ('alice', 'grant',
|
|
# '--teacher-uri', teacher.rest_interface,
|
|
'--config-file', custom_config_file,
|
|
'--m', 1,
|
|
'--n', 1,
|
|
'--label', random_label,
|
|
'--bob-encrypting-key', bob_encrypting_key_hex,
|
|
'--bob-verifying-key', bob_signing_key_hex)
|
|
|
|
grant_result = click_runner.invoke(nucypher_cli, grant_args, catch_exceptions=False, env=envvars)
|
|
|
|
assert False
|
|
|
|
d = threads.deferToThread(_grant)
|
|
yield d
|
|
|
|
|
|
#
|
|
# Scene 3: Enrico encrpyts some data for the policy and saves it to a side channel
|
|
#
|
|
|
|
# policy_pubkey_enc_hex = alice_response_data['result']['policy_encrypting_key']
|
|
# alice_pubkey_sig_hex = alice_response_data['result']['alice_signing_key']
|
|
# label = alice_response_data['result']['label']
|
|
#
|
|
# enrico_encoded_message = "I'm bereaved, not a sap!" # type: str
|
|
# enrico_request_data = {
|
|
# 'message': enrico_encoded_message,
|
|
# }
|
|
#
|
|
# response = enrico_control_from_alice.post('/encrypt_message', data=json.dumps(enrico_request_data))
|
|
#
|
|
# enrico_response_data = json.loads(response.data)
|
|
|
|
|
|
#
|
|
# Scene 4: Bob retrieves encrypted data from the side channel and uses nucypher to re-encrypt it
|
|
#
|
|
|
|
# kit_bytes = b64decode(enrico_response_data['result']['message_kit'].encode())
|
|
# bob_message_kit = UmbralMessageKit.from_bytes(kit_bytes)
|
|
#
|
|
# # Retrieve data via Bob control
|
|
# encoded_message_kit = b64encode(bob_message_kit.to_bytes()).decode()
|
|
#
|
|
# # Give bob a node to remember
|
|
# teacher = list(federated_ursulas)[1]
|
|
# federated_bob.remember_node(teacher)
|
|
#
|
|
# response = bob_control_test_client.post('/retrieve', data=json.dumps(bob_request_data))
|
|
#
|
|
# bob_response_data = json.loads(response.data)
|
|
#
|
|
# for plaintext in bob_response_data['result']['plaintext']:
|
|
# plaintext_bytes = b64decode(plaintext)
|
|
|
|
assert False
|