def get(self): "User should send Bob password to decrypt files" try: user = request.args.get("user") pw = request.args.get("password") label = request.args.get("label") frmt = request.args.get("frmt") except: response = {'message': "Insufficient Query Params"} return make_response(jsonify(response)), 404 keyringBob = NucypherKeyring(account=user) keyringBob.unlock(password=pw) bob = Bob(keyring=keyringBob, known_nodes=[ursula], federated_only=True, learn_on_same_thread=True, domain=TEMPORARY_DOMAIN) bob.join_policy(label.encode(), alice_sig_pubkey) from nucypher.characters.lawful import Enrico global globalStorage enrico1 = Enrico.from_public_keys( verifying_key=globalStorage[label]["data_source_public_key"], policy_encrypting_key=globalStorage[label]["policy_pubkey"]) imgUrl = base_uri + label + "." + frmt response = requests.get(imgUrl) ciphertext = UmbralMessageKit.from_bytes(response.content) decrypted_plaintext = bob.retrieve( ciphertext, label=label.encode(), enrico=enrico1, alice_verifying_key=alice_sig_pubkey) return send_file(io.BytesIO(decrypted_plaintext[0]), mimetype="image/" + frmt, as_attachment=False, attachment_filename='{}.'.format(label) + frmt), 200
def generate_charlie(): shutil.rmtree(TEMP_CHARLIE_DIR, ignore_errors=True) ursula = Ursula.from_seed_and_stake_info(seed_uri=SEEDNODE_URL, federated_only=True, minimum_stake=0) # To create a Bob, we need the charlie's private keys previously generated. from charlie_keys import get_charlie_privkeys charlie_keys = get_charlie_privkeys() bob_enc_keypair = DecryptingKeypair(private_key=charlie_keys["enc"]) bob_sig_keypair = SigningKeypair(private_key=charlie_keys["sig"]) enc_power = DecryptingPower(keypair=bob_enc_keypair) sig_power = SigningPower(keypair=bob_sig_keypair) power_ups = [enc_power, sig_power] print("Creating the Charlie ...") charlie = Bob( is_me=True, federated_only=True, crypto_power_ups=power_ups, start_learning_now=True, abort_on_learning_error=True, known_nodes=[ursula], save_metadata=False, network_middleware=RestMiddleware(), ) print("Charlie = ", charlie) # Join policy generated by alice with open("policy-metadata.json", 'r') as f: policy_data = json.load(f) policy_pubkey = UmbralPublicKey.from_bytes( bytes.fromhex(policy_data["policy_pubkey"])) alices_sig_pubkey = UmbralPublicKey.from_bytes( bytes.fromhex(policy_data["alice_sig_pubkey"])) label = policy_data["label"].encode() print("The Charlie joins policy for label '{}'".format( label.decode("utf-8"))) charlie.join_policy(label, alices_sig_pubkey) return charlie, policy_pubkey, alices_sig_pubkey, label
def post(self): keys = request.json['keys'] password = request.json['password'] address = request.json['address'] alice_pubkey = request.json['alice_pubkey'] label = request.json['label'] path = self.writeKeys(keys) passwd = PBKDF2(password, address.encode(), 20, count=30000, hmac_hash_module=SHA256).hex() keyring = NucypherKeyring(account=address, keyring_root="./keys") keyring.unlock(password=passwd) bob = Bob(known_nodes=[self.URSULA], checksum_address=address, domain='lynx', keyring=keyring) alice_pubkey_umbral = UmbralPublicKey.from_bytes( bytes.fromhex(alice_pubkey)) bob.join_policy(label.encode(), alice_verifying_key=alice_pubkey_umbral, block=True) self.readAndDeleteKeys(address, keyring) # delete keys
def test_bob_joins_policy_and_retrieves(federated_alice, federated_ursulas, certificates_tempdir, ): # Let's partition Ursulas in two parts a_couple_of_ursulas = list(federated_ursulas)[:2] rest_of_ursulas = list(federated_ursulas)[2:] # Bob becomes bob = Bob(federated_only=True, domain=TEMPORARY_DOMAIN, start_learning_now=True, network_middleware=MockRestMiddleware(), abort_on_learning_error=True, known_nodes=a_couple_of_ursulas, ) # Bob has only connected to - at most - 2 nodes. assert sum(node.verified_node for node in bob.known_nodes) <= 2 # Alice creates a policy granting access to Bob # Just for fun, let's assume she distributes KFrags among Ursulas unknown to Bob n = NUMBER_OF_URSULAS_IN_DEVELOPMENT_NETWORK - 2 label = b'label://' + os.urandom(32) contract_end_datetime = maya.now() + datetime.timedelta(days=5) policy = federated_alice.grant(bob=bob, label=label, m=3, n=n, expiration=contract_end_datetime, handpicked_ursulas=set(rest_of_ursulas), ) assert bob == policy.bob assert label == policy.label try: # Now, Bob joins the policy bob.join_policy(label=label, alice_verifying_key=federated_alice.stamp, block=True) except policy.treasure_map.NowhereToBeFound: maps = [] for ursula in federated_ursulas: for map in ursula.treasure_maps.values(): maps.append(map) if policy.treasure_map in maps: # This is a nice place to put a breakpoint to examine Bob's failure to join a policy. bob.join_policy(label=label, alice_verifying_key=federated_alice.stamp, block=True) pytest.fail(f"Bob didn't find map {policy.treasure_map} even though it was available. Come on, Bob.") else: pytest.fail(f"It seems that Alice didn't publish {policy.treasure_map}. Come on, Alice.") # In the end, Bob should know all the Ursulas assert len(bob.known_nodes) == len(federated_ursulas) # Enrico becomes enrico = Enrico(policy_encrypting_key=policy.public_key) plaintext = b"What's your approach? Mississippis or what?" message_kit, _signature = enrico.encrypt_message(plaintext) alices_verifying_key = federated_alice.stamp.as_umbral_pubkey() # Bob takes the message_kit and retrieves the message within delivered_cleartexts = bob.retrieve(message_kit, enrico=enrico, alice_verifying_key=alices_verifying_key, label=policy.label, retain_cfrags=True) assert plaintext == delivered_cleartexts[0] # Bob tries to retrieve again, but without using the cached CFrags, it fails. with pytest.raises(TypeError): delivered_cleartexts = bob.retrieve(message_kit, enrico=enrico, alice_verifying_key=alices_verifying_key, label=policy.label) cleartexts_delivered_a_second_time = bob.retrieve(message_kit, enrico=enrico, alice_verifying_key=alices_verifying_key, label=policy.label, use_attached_cfrags=True) # Indeed, they're the same cleartexts. assert delivered_cleartexts == cleartexts_delivered_a_second_time # Let's try retrieve again, but Alice revoked the policy. failed_revocations = federated_alice.revoke(policy) assert len(failed_revocations) == 0 # One thing to note here is that Bob *can* still retrieve with the cached CFrags, even though this Policy has been revoked. #892 _cleartexts = bob.retrieve(message_kit, enrico=enrico, alice_verifying_key=alices_verifying_key, label=policy.label, use_precedent_work_orders=True, ) assert _cleartexts == delivered_cleartexts # TODO: 892 # OK, but we imagine that the message_kit is fresh here. message_kit.capsule.clear_cfrags() with pytest.raises(Ursula.NotEnoughUrsulas): _cleartexts = bob.retrieve(message_kit, enrico=enrico, alice_verifying_key=alices_verifying_key, label=policy.label, ) bob.disenchant()
# (this is optional of course - she may wish to remain in order to create # new policies in the future. The point is - she is no longer obligated. ##################### # some time passes. # # ... # # # # ... # # And now for Bob. # ##################### # Bob wants to join the policy so that he can receive any future # data shared on it. # He needs a few pieces of knowledge to do that. BOB.join_policy( label, # The label - he needs to know what data he's after. alices_pubkey_bytes_saved_for_posterity, # To verify the signature, he'll need Alice's public key. ) # Now that Bob has joined the Policy, let's show how DataSources # can share data with the members of this Policy and then how Bob retrieves it. finnegans_wake = open(sys.argv[1], 'rb') # We'll also keep track of some metadata to gauge performance. # You can safely ignore from here until... ################################################################################ start_time = datetime.datetime.now() for counter, plaintext in enumerate(finnegans_wake): if counter % 20 == 0: now_time = datetime.datetime.now()
# ...and then disappears from the internet. del ALICE ##################### # some time passes. # # ... # # # # ... # # And now for Bob. # ##################### ##################### # Bob the BUIDLer ## ##################### BOB.join_policy(label, alices_pubkey_bytes_saved_for_posterity) # Now that Bob has joined the Policy, let's show how Enrico the Encryptor # can share data with the members of this Policy and then how Bob retrieves it. # In order to avoid re-encrypting the entire book in this demo, we only read some lines. with open(BOOK_PATH, 'rb') as file: finnegans_wake = file.readlines()[:NUMBER_OF_LINES_TO_REENCRYPT] print() print("**************James Joyce's Finnegan's Wake**************") print() print("---------------------------------------------------------") for counter, plaintext in enumerate(finnegans_wake): #########################
def createBobToResolveData(sub_uuid, sender, event_uuid, sub_private_key, sub_signer_key, policy_pub_key, policy_sign_key, label): SEEDNODE_URI = "127.0.0.1:10151" # TODO: path joins? TEMP_DOCTOR_DIR = "{}/doctor-files".format( os.path.dirname(os.path.abspath(__file__))) # Remove previous demo files and create new ones shutil.rmtree(TEMP_DOCTOR_DIR, ignore_errors=True) ursula = Ursula.from_seed_and_stake_info(seed_uri=SEEDNODE_URI, federated_only=True, minimum_stake=0) # doctor private key encdoctor = UmbralPrivateKey.from_bytes(bytes.fromhex(sub_private_key)) signdoctor = UmbralPrivateKey.from_bytes(bytes.fromhex(sub_signer_key)) bob_enc_keypair = DecryptingKeypair(private_key=encdoctor) bob_sig_keypair = SigningKeypair(private_key=signdoctor) enc_power = DecryptingPower(keypair=bob_enc_keypair) sig_power = SigningPower(keypair=bob_sig_keypair) power_ups = [enc_power, sig_power] print("Creating the Doctor ...") doctor = Bob( domains={TEMPORARY_DOMAIN}, federated_only=True, crypto_power_ups=power_ups, start_learning_now=True, abort_on_learning_error=True, known_nodes=[ursula], save_metadata=False, network_middleware=RestMiddleware(), ) print("Doctor = ", doctor) policy_pub_keys = UmbralPublicKey.from_bytes(bytes.fromhex(policy_pub_key)) policy_sign_keys = UmbralPublicKey.from_bytes( bytes.fromhex(policy_sign_key)) label = label.encode() print("The Doctor joins policy for label '{}'".format( label.decode("utf-8"))) doctor.join_policy(label, policy_sign_keys) data = msgpack.load(open(event_uuid + ".msgpack", "rb"), raw=False) message_kits = UmbralMessageKit.from_bytes(data['data']) data_source = Enrico.from_public_keys( verifying_key=data['data_source'], policy_encrypting_key=policy_pub_keys) try: retrieved_plaintexts = doctor.retrieve( message_kits, label=label, enrico=data_source, alice_verifying_key=policy_sign_keys) 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. location_decrypted = plaintext['data_enc'] print(location_decrypted) except Exception as e: # We just want to know what went wrong and continue the demo traceback.print_exc() return location_decrypted
class service(object): def __init__(self, network_provider): self.provider_uri = network_provider self.user_path = "users/" self.public_key_path = "/recipent.public.json" self.private_key_path = "/recipent.private.json" def connect(self, networkURL, second_provider, third_provider, ipfs_provider): BlockchainInterfaceFactory.initialize_interface(provider_uri=self.provider_uri) self.ipfs_gateway_api = ipfshttpclient.connect(ipfs_provider) self.ursula = Ursula.from_seed_and_stake_info( seed_uri=networkURL, federated_only=True, minimum_stake=0 ) self.ursula2 = Ursula.from_teacher_uri( teacher_uri=networkURL, federated_only=True, min_stake=0 ) self.ursula3 = Ursula.from_teacher_uri( teacher_uri=networkURL, federated_only=True, min_stake=0 ) return True def generate_keys(self): enc_privkey = UmbralPrivateKey.gen_key() sig_privkey = UmbralPrivateKey.gen_key() recipient_privkeys = { 'enc': enc_privkey.to_bytes().hex(), 'sig': sig_privkey.to_bytes().hex(), } enc_pubkey = enc_privkey.get_pubkey() sig_pubkey = sig_privkey.get_pubkey() recipient_pubkeys = { 'enc': enc_pubkey.to_bytes().hex(), 'sig': sig_pubkey.to_bytes().hex() } return recipient_privkeys, recipient_pubkeys def configure_alice(self, path): return AliceConfiguration( config_root=os.path.join(path), known_nodes=[self.ursula, self.ursula2, self.ursula3], start_learning_now=False, federated_only=True, learn_on_same_thread=True, network_middleware=RestMiddleware(), ) def create_alice(self, username, password): path = self.user_path + username alice_config = self.configure_alice(path) alice_config.initialize(password=password) alice_config.keyring.unlock(password=password) self.Alice = alice_config.produce() alice_config_file = alice_config.to_configuration_file() self.Alice.start_learning_loop(now=True) private_keys, public_keys = self.generate_keys() with open(path + self.private_key_path, 'w') as file: json.dump(private_keys, file) with open(path + self.public_key_path, 'w') as f: json.dump(public_keys, f) config_path = path + '/alice.json' with open(config_path) as config_file: data = json.load(config_file) address = data["checksum_address"] return address def generate_policy(self, username, label): policy_end_datetime = maya.now() + datetime.timedelta(365) path = self.user_path + username self.configure_alice(path) policy_pubkey = self.Alice.get_policy_pubkey_from_label(label) return policy_pubkey def reveal_public_keys(self, username, serialized=False): public_keys = self.user_path + username + self.public_key_path with open(public_keys) as data_file: data = json.load(data_file) enc_pubkey = UmbralPublicKey.from_bytes(bytes.fromhex(data["enc"])) sig_pubkey = UmbralPublicKey.from_bytes(bytes.fromhex(data["sig"])) print(sig_pubkey.to_bytes()) if serialized: return ( base58.b58encode(bytes.fromhex(data["enc"])).decode("utf-8"), base58.b58encode(bytes.fromhex(data["sig"])).decode("utf-8") ) return (enc_pubkey, sig_pubkey) def calculate_powers(self, username): enc_pubkey, sig_pubkey = self.reveal_public_keys(username) powers_and_material = { DecryptingPower: enc_pubkey, SigningPower: sig_pubkey } return powers_and_material def reveal_private_keys(self, username): private_keys = self.user_path + username + self.private_key_path with open(private_keys) as data_file: data = json.load(data_file) enc_privkey = UmbralPrivateKey.from_bytes(bytes.fromhex(data["enc"])) sig_privkey = UmbralPrivateKey.from_bytes(bytes.fromhex(data["sig"])) return enc_privkey, sig_privkey def uploadData(self, label, file): policy_pubkey = self.Alice.get_policy_encrypting_key_from_label(label.encode("utf-8")) data_source = Enrico(policy_encrypting_key=policy_pubkey) data_source_public_key = bytes(data_source.stamp) now = time.time() kits = list() now += 5 data_representation = { 'data': file, 'timestamp': now, } plaintext = msgpack.dumps(data_representation, use_bin_type=True) message_kit, _signature = data_source.encrypt_message(plaintext) kit_bytes = message_kit.to_bytes() kits.append(kit_bytes) data = { 'data_source': data_source_public_key, 'kits': kits, } d = msgpack.dumps(data, use_bin_type=True) ipfs_hash = self.ipfs_gateway_api.add_bytes(d) receipt = { "data_source_public_key" : data_source_public_key.hex(), "hash_key" : ipfs_hash } return receipt def alice_from_configutation(self, username, password, account): path = self.user_path + username + '/' keyring_path = path + "keyring" full_path = path + 'alice.json' alice_config = self.configure_alice(path) configuration = alice_config.from_configuration_file( config_root=os.path.join(path), filepath=full_path, keyring=NucypherKeyring( account=account, keyring_root=os.path.join(keyring_path), ), ) configuration.keyring.unlock(password) self.Alice = configuration.produce() return self.Alice def grant(self, username, password, account, bob_username, label): self.Alice = self.alice_from_configutation(username, password, account) powers_and_material = self.calculate_powers(bob_username) bob = Bob.from_public_keys(powers_and_material=powers_and_material, federated_only=True) policy_end_datetime = maya.now() + datetime.timedelta(days=365) encoded_label = label.encode("utf-8") self.Alice.start_learning_loop(now=True) policy = self.Alice.grant(bob, encoded_label, m=1, n=1, expiration=policy_end_datetime) alices_pubkey = bytes(self.Alice.stamp) policy_info = { "policy_pubkey" : policy.public_key.to_bytes().hex(), "alice_sig_pubkey": base58.b58encode(alices_pubkey).decode("utf-8"), "label" : encoded_label.decode("utf-8") } return policy_info def add_data_and_grant_self_access(self, username, password, account, label, file): policy_info = self.grant(username, password, account, username, label) receipt = self.uploadData(label, file) return policy_info, receipt def downloadFile(self, username, receipt, policy_info): hash = receipt['hash_key'] input = self.ipfs_gateway_api.cat(hash) enc_privkey, sig_privkey = self.reveal_private_keys(username) bob_enc_key = DecryptingKeypair(private_key=enc_privkey) bob_sig_keyp = SigningKeypair(private_key=sig_privkey) enc_power = DecryptingPower(keypair=bob_enc_key) sig_power = SigningPower(keypair=bob_sig_keyp) power_ups = [enc_power, sig_power] self.Bob = Bob( federated_only=True, crypto_power_ups=power_ups, start_learning_now=True, abort_on_learning_error=True, known_nodes=[self.ursula], save_metadata=False, network_middleware=RestMiddleware(), ) policy_pubkey = UmbralPublicKey.from_bytes(bytes.fromhex(policy_info["policy_pubkey"])) enrico = Enrico.from_public_keys( {SigningPower: UmbralPublicKey.from_bytes(bytes.fromhex(receipt['data_source_public_key']))}, policy_encrypting_key=policy_pubkey ) alice_pubkey_restored = UmbralPublicKey.from_bytes(base58.b58decode(policy_info['alice_sig_pubkey'])) self.Bob.join_policy(policy_info['label'].encode(), alice_pubkey_restored) data = msgpack.loads(input, raw=False) message_kits = (UmbralMessageKit.from_bytes(k) for k in data['kits']) message_kit = next(message_kits) retrieved_plaintexts = self.Bob.retrieve( message_kit, enrico=enrico, alice_verifying_key=alice_pubkey_restored, label=policy_info['label'].encode(), ) plaintext = msgpack.loads(retrieved_plaintexts[0], raw=False) print(plaintext) decrypted_data = plaintext['data'] return decrypted_data
) print("Doctor = ", doctor) # Let's join the policy generated by Alicia. We just need some info about it. with open("policy-metadata.json", 'r') as f: 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() print("The Doctor joins policy for label '{}'".format(label.decode("utf-8"))) doctor.join_policy(label, alices_sig_pubkey) # Now that the Doctor joined the policy in the NuCypher network, # he 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 = (UmbralMessageKit.from_bytes(k) for k in data['kits']) # The doctor also needs to create a view of the Data Source from its public keys data_source = Enrico.from_public_keys(verifying_key=data['data_source'], policy_encrypting_key=policy_pubkey) # Now he can ask the NuCypher network to get a re-encrypted version of each MessageKit. for message_kit in message_kits:
def test_bob_joins_policy_and_retrieves(federated_alice, federated_ursulas, certificates_tempdir, ): # Let's partition Ursulas in two parts a_couple_of_ursulas = list(federated_ursulas)[:2] rest_of_ursulas = list(federated_ursulas)[2:] # Bob becomes bob = Bob(federated_only=True, domains={TEMPORARY_DOMAIN}, start_learning_now=True, network_middleware=MockRestMiddleware(), abort_on_learning_error=True, known_nodes=a_couple_of_ursulas, ) # Bob only knows a couple of Ursulas initially assert len(bob.known_nodes) == 2 # Alice creates a policy granting access to Bob # Just for fun, let's assume she distributes KFrags among Ursulas unknown to Bob n = NUMBER_OF_URSULAS_IN_DEVELOPMENT_NETWORK - 2 label = b'label://' + os.urandom(32) contract_end_datetime = maya.now() + datetime.timedelta(days=5) policy = federated_alice.grant(bob=bob, label=label, m=3, n=n, expiration=contract_end_datetime, handpicked_ursulas=set(rest_of_ursulas), ) assert bob == policy.bob assert label == policy.label # Now, Bob joins the policy bob.join_policy(label=label, alice_verifying_key=federated_alice.stamp, block=True) # In the end, Bob should know all the Ursulas assert len(bob.known_nodes) == len(federated_ursulas) # Enrico becomes enrico = Enrico(policy_encrypting_key=policy.public_key) plaintext = b"What's your approach? Mississippis or what?" message_kit, _signature = enrico.encrypt_message(plaintext) alices_verifying_key = federated_alice.stamp.as_umbral_pubkey() # Bob takes the message_kit and retrieves the message within delivered_cleartexts = bob.retrieve(message_kit, enrico=enrico, alice_verifying_key=alices_verifying_key, label=policy.label, retain_cfrags=True) assert plaintext == delivered_cleartexts[0] # Bob tries to retrieve again, but without using the cached CFrags, it fails. with pytest.raises(TypeError): delivered_cleartexts = bob.retrieve(message_kit, enrico=enrico, alice_verifying_key=alices_verifying_key, label=policy.label) cleartexts_delivered_a_second_time = bob.retrieve(message_kit, enrico=enrico, alice_verifying_key=alices_verifying_key, label=policy.label, use_attached_cfrags=True) # Indeed, they're the same cleartexts. assert delivered_cleartexts == cleartexts_delivered_a_second_time # Let's try retrieve again, but Alice revoked the policy. failed_revocations = federated_alice.revoke(policy) assert len(failed_revocations) == 0 # One thing to note here is that Bob *can* still retrieve with the cached CFrags, even though this Policy has been revoked. #892 _cleartexts = bob.retrieve(message_kit, enrico=enrico, alice_verifying_key=alices_verifying_key, label=policy.label, use_precedent_work_orders=True, ) assert _cleartexts == delivered_cleartexts # TODO: 892 # OK, but we imagine that the message_kit is fresh here. message_kit.capsule.clear_cfrags() with pytest.raises(Ursula.NotEnoughUrsulas): _cleartexts = bob.retrieve(message_kit, enrico=enrico, alice_verifying_key=alices_verifying_key, label=policy.label, )
# new policies in the future. The point is - she is no longer obligated. ##################### # some time passes. # # ... # # # # ... # # And now for Bob. # ##################### # Bob wants to join the policy so that he can receive any future # data shared on it. # He needs a few pieces of knowledge to do that. BOB.join_policy(label, # The label - he needs to know what data he's after. alices_pubkey_bytes_saved_for_posterity, # To verify the signature, he'll need Alice's public key. # He can also bootstrap himself onto the network more quickly # by providing a list of known nodes at this time. node_list=[("localhost", 3601)] ) # Now that Bob has joined the Policy, let's show how DataSources # can share data with the members of this Policy and then how Bob retrieves it. finnegans_wake = open(sys.argv[1], 'rb') # We'll also keep track of some metadata to gauge performance. # You can safely ignore from here until... ################################################################################ start_time = datetime.datetime.now() for counter, plaintext in enumerate(finnegans_wake): if counter % 20 == 0:
class KMS: def __init__(self, ursula_url, dir_name, passphrase, ipfs_addr='', arweave_wallet_file_path='', federated_only=True, signer_uri='', checksum_address=None, client_password=None, provider_uri='', domain=TEMPORARY_DOMAIN): """ Args: ursula_url (str): ursula url e.g. localhost:11500 dir_name (str): dir_name where account files will be stored in tmp directory passphrase (str): passphrase for account ipfs_addr (str): ipfs addr (required only if you want to store data in ipfs) arweave_wallet_file_path (str): arweave wallet file path (required only if you want to store data in arweave) federated_only (bool): Whether federated mode should be used signer_uri (str): signer uri for ethereum transaction https://docs.nucypher.com/en/latest/guides/ethereum_node.html#external-transaction-signing checksum_address (str): Ethereum address client_password (str): Password for ethereum keystore. Required only if signer_uri is keystore://{path} provider_uri (str): geth or infura https uri domain (str): nucypher network name e.g. lynx for nucypher testnet and mainnet for nucypher mainnet """ self.__client_password = client_password self.federated_only = federated_only self.ursula_url = ursula_url self.ursula = Ursula.from_seed_and_stake_info( seed_uri=self.ursula_url, federated_only=self.federated_only, minimum_stake=0) self.arweave_wallet = None if arweave_wallet_file_path: self.arweave_wallet = arweave.Wallet(arweave_wallet_file_path) self.ipfs = None if ipfs_addr: self.ipfs = ipfshttpclient.connect(ipfs_addr) self.temp_dir = os.path.join('/', 'tmp', dir_name) self.alice_config = AliceConfiguration( provider_uri=provider_uri, checksum_address=checksum_address, signer_uri=signer_uri, config_root=os.path.join(self.temp_dir), domain=domain, known_nodes={self.ursula}, start_learning_now=False, federated_only=self.federated_only, learn_on_same_thread=True) try: if os.path.exists(os.path.join(self.temp_dir, "alice.json")): raise ExistingKeyringError() self.alice_config.initialize(password=passphrase) except ExistingKeyringError: self.alice_config = AliceConfiguration.from_configuration_file( filepath=os.path.join(self.temp_dir, "alice.json"), known_nodes={self.ursula}, start_learning_now=False) self.alice_config.attach_keyring() self.alice_config.keyring.unlock(password=passphrase) signer = Signer.from_signer_uri(signer_uri) if signer_uri else None if signer: signer.unlock_account(account=checksum_address, password=client_password) self.alice = self.alice_config.produce(signer=signer) try: self.alice_config_file = self.alice_config.to_configuration_file() except FileExistsError: pass self.alice.start_learning_loop(now=True) self.privkeys, self.pubkeys = fetch_keys(path=self.temp_dir) bob_enc_keypair = DecryptingKeypair(private_key=self.privkeys["enc"]) bob_sig_keypair = SigningKeypair(private_key=self.privkeys["sig"]) enc_power = DecryptingPower(keypair=bob_enc_keypair) sig_power = SigningPower(keypair=bob_sig_keypair) power_ups = [enc_power, sig_power] self.bob = Bob(domain=domain, federated_only=self.federated_only, crypto_power_ups=power_ups, start_learning_now=True, abort_on_learning_error=True, known_nodes=[self.ursula], save_metadata=False, network_middleware=RestMiddleware(), provider_uri=provider_uri) def encrypt_data(self, plaintext): """ Encrypt data Args: plaintext (str): plaintext that should be encrypted Returns: label, data_source_public_key, data (bytes, bytes, byes): tuple containing label for the policy, data source public_key & encrypted data """ label = ("policy️-" + os.urandom(8).hex()).encode() policy_pubkey = self.alice.get_policy_encrypting_key_from_label(label) data_source = Enrico(policy_encrypting_key=policy_pubkey) data_source_public_key = bytes(data_source.stamp) message, _signature = data_source.encrypt_message( plaintext.encode("utf-8")) data = message.to_bytes() return label, data_source_public_key, data def decrypt_data(self, data_source_public_key, data, policy_info): """ Decrypt data Args: data_source_public_key (bytes): data_source_public_key data (bytes): encrypted data policy_info (dict): dict containing policy_pubkey, alice_sig_pubkey and label keys Returns: retrieved_plaintexts (list): list of str """ policy_pubkey = UmbralPublicKey.from_bytes( bytes.fromhex(policy_info["policy_pubkey"])) alice_sig_pubkey = UmbralPublicKey.from_bytes( bytes.fromhex(policy_info["alice_sig_pubkey"])) label = policy_info["label"].encode() self.bob.join_policy(label, alice_sig_pubkey) message_kit = UmbralMessageKit.from_bytes(data) data_source = Enrico.from_public_keys( verifying_key=data_source_public_key, policy_encrypting_key=policy_pubkey) retrieved_plaintexts = self.bob.retrieve( message_kit, label=label, enrico=data_source, alice_verifying_key=alice_sig_pubkey) retrieved_plaintexts = [ x.decode('utf-8') for x in retrieved_plaintexts ] return retrieved_plaintexts def share_data_access(self, pubkeys, label, days=5, m=1, n=1, rate=Web3.toWei(50, 'gwei')): """ Share data access based on public keys Args: pubkeys (dict): public keys dict containing sig and enc keys label (bytes): label for the policy days (int): days for which the access should be granted m (int): Minimum number of kfrags needed to activate a Capsule n (int): Total number of kfrags to generate rate (int): rate in wei Returns: policy_info (dict): dict containing policy_pubkey, alice_sig_pubkey and label keys """ bob = Bob.from_public_keys(verifying_key=pubkeys['sig'], encrypting_key=pubkeys['enc'], federated_only=self.federated_only) # Policy expiration date policy_end_datetime = maya.now() + datetime.timedelta(days=days) power_ups = self.alice._crypto_power._CryptoPower__power_ups for key, power_up in power_ups.items(): self.alice._crypto_power.consume_power_up( power_up, password=self.__client_password) policy = self.alice.grant(bob=bob, label=label, m=m, n=n, expiration=policy_end_datetime, rate=rate) policy_info = { "policy_pubkey": policy.public_key.to_bytes().hex(), "alice_sig_pubkey": bytes(self.alice.stamp).hex(), "label": label.decode("utf-8"), } return policy_info def upload_data(self, plaintext, storage): """ Upload data to the selected storage Args: plaintext (str): plaintext storage (str): storage layer e.g. ipfs, arweave, skynet, etc. Returns: label, data_source_public_key, hash_key (bytes, bytes, str): tuple containing policy label, data source public key and hash_key """ label, data_source_public_key, data = self.encrypt_data( plaintext=plaintext) if storage == "ipfs": hash_key = self.ipfs.add_bytes(data) elif storage == "arweave": transaction = arweave.Transaction(self.arweave_wallet, data=data) transaction.sign() transaction.send() hash_key = transaction.id elif storage == "skynet": file_name = '/tmp/{}.txt'.format( random.randint(100000000000, 999999999999)) file = open(file_name, 'wb') file.write(data) file.close() skynet_client = skynet.SkynetClient() hash_key = skynet_client.upload_file(file_name) else: raise ValueError("invalid storage layer") return label, data_source_public_key, hash_key @staticmethod def get_shareable_code(hash_key, data_source_public_key, policy_info, storage): """ Get shareable code to fetch the secret which can be shared easily Args: hash_key (str): storage layer hash key data_source_public_key (bytes): data source public key policy_info (dict): dict containing policy_pubkey, alice_sig_pubkey and label keys storage (str): storage layer e.g. ipfs, arweave, skynet, etc. Returns: shareable_code (str): shareable code """ data = { "hash": hash_key, "data_source_public_key": data_source_public_key.hex(), "policy_info": policy_info, "storage": storage } return base64.b64encode( json.dumps(data, separators=(',', ':')).encode("utf-8")).decode('utf-8') def fetch_data(self, shareable_code, storage): """ Fetch data from the selected storage and decrypt it Args: shareable_code (str): shareable code storage (str): storage layer e.g. ipfs, arweave, skynet, etc. Returns: retrieved_plaintexts (list): list of str """ meta_data = json.loads( base64.b64decode(shareable_code.encode('utf-8')).decode('utf-8')) data_source_public_key = meta_data['data_source_public_key'] hash_key = meta_data['hash'] if storage == "ipfs": data = self.ipfs.cat(hash_key) elif storage == "arweave": transaction = arweave.Transaction(self.arweave_wallet, id=hash_key) transaction.get_data() data = transaction.data if data == b'': raise ValueError( "Transaction not found. Wait for some more time") elif storage == "skynet": file_name = '/tmp/{}.txt'.format( random.randint(100000000000, 999999999999)) skynet_client = skynet.SkynetClient() skynet_client.download_file(file_name, hash_key) file = open(file_name, 'rb') data = file.read() file.close() else: raise ValueError("invalid storage layer") data_source_public_key = bytes.fromhex(data_source_public_key) policy_info = meta_data["policy_info"] return self.decrypt_data(data_source_public_key=data_source_public_key, data=data, policy_info=policy_info)
def test_bob_joins_policy_and_retrieves( federated_alice, federated_ursulas, certificates_tempdir, ): # Let's partition Ursulas in two parts a_couple_of_ursulas = list(federated_ursulas)[:2] rest_of_ursulas = list(federated_ursulas)[2:] # Bob becomes bob = Bob( federated_only=True, start_learning_now=True, network_middleware=MockRestMiddleware(), known_certificates_dir=certificates_tempdir, abort_on_learning_error=True, known_nodes=a_couple_of_ursulas, ) # Bob only knows a couple of Ursulas initially assert len(bob.known_nodes) == 2 # Alice creates a policy granting access to Bob # Just for fun, let's assume she distributes KFrags among Ursulas unknown to Bob n = DEFAULT_NUMBER_OF_URSULAS_IN_DEVELOPMENT_NETWORK - 2 label = b'label://' + os.urandom(32) contract_end_datetime = maya.now() + datetime.timedelta(days=5) policy = federated_alice.grant( bob=bob, label=label, m=3, n=n, expiration=contract_end_datetime, handpicked_ursulas=set(rest_of_ursulas), ) assert bob == policy.bob assert label == policy.label # Now, Bob joins the policy bob.join_policy( label=label, alice_pubkey_sig=federated_alice.stamp, ) # In the end, Bob should know all the Ursulas assert len(bob.known_nodes) == len(federated_ursulas) # DataSource becomes data_source = DataSource(policy_pubkey_enc=policy.public_key, signing_keypair=SigningKeypair(), label=label) plaintext = b"What's your approach? Mississippis or what?" message_kit, _signature = data_source.encapsulate_single_message(plaintext) alices_verifying_key = federated_alice.stamp.as_umbral_pubkey() # Bob takes the message_kit and retrieves the message within delivered_cleartexts = bob.retrieve( message_kit=message_kit, data_source=data_source, alice_verifying_key=alices_verifying_key) assert plaintext == delivered_cleartexts[0]
alice.disenchant() del alice ##################### # some time passes. # # ... # # # # ... # # And now for Bob. # ##################### ##################### # Bob the BUIDLer ## ##################### bob.join_policy(label, alice_verifying_key) # Now that Bob has joined the Policy, let's show how Enrico the Encryptor # can share data with the members of this Policy and then how Bob retrieves it. # In order to avoid re-encrypting the entire book in this demo, we only read some lines. with open(BOOK_PATH, 'rb') as file: finnegans_wake = file.readlines() print() print("**************James Joyce's Finnegan's Wake (Excerpt)**************") print() print("---------------------------------------------------------") for counter, plaintext in enumerate(finnegans_wake): #########################
}) # Alice grants access to Bob policy = alice.grant(bob_as_seen_by_alice, health_label, m=m, n=n, expiration=policy_end_datetime) assert policy.public_key == policy_pubkey # Alice can disappear from the Internet. del alice # Bob joins the Policy alice_nucypher_signing_pub_key_as_seen_by_bob = alice_proxy_account.functions.getData( nucypher_signing_key).call() bob.join_policy(health_label, alice_nucypher_signing_pub_key_as_seen_by_bob) # Threaded function simulating Bob's behaviour, watching for on-chain claims def decrypt_first_message(): ############### # Back to Bob # ############### # Bob watches for the first claim to be made on alice about her health claim_added_filter = alice_claim_holder.events.ClaimAdded.createFilter( fromBlock=0x0, argument_filters={'topic': health_label_key}) while True: events = claim_added_filter.get_all_entries() if events: break
def doctor_decrypt(hash_key): globalLogPublisher.addObserver(SimpleObserver()) SEEDNODE_URL = 'localhost:11501' TEMP_DOCTOR_DIR = "{}/doctor-files".format( os.path.dirname(os.path.abspath(__file__))) shutil.rmtree(TEMP_DOCTOR_DIR, ignore_errors=True) ursula = Ursula.from_seed_and_stake_info(seed_uri=SEEDNODE_URL, federated_only=True, minimum_stake=0) from doctor_keys import get_doctor_privkeys doctor_keys = get_doctor_privkeys() bob_enc_keypair = DecryptingKeypair(private_key=doctor_keys["enc"]) bob_sig_keypair = SigningKeypair(private_key=doctor_keys["sig"]) enc_power = DecryptingPower(keypair=bob_enc_keypair) sig_power = SigningPower(keypair=bob_sig_keypair) power_ups = [enc_power, sig_power] print("Creating the Doctor ...") doctor = Bob( is_me=True, federated_only=True, crypto_power_ups=power_ups, start_learning_now=True, abort_on_learning_error=True, known_nodes=[ursula], save_metadata=False, network_middleware=RestMiddleware(), ) print("Doctor = ", doctor) with open("policy-metadata.json", 'r') as f: policy_data = json.load(f) policy_pubkey = UmbralPublicKey.from_bytes( bytes.fromhex(policy_data["policy_pubkey"])) alices_sig_pubkey = UmbralPublicKey.from_bytes( bytes.fromhex(policy_data["alice_sig_pubkey"])) label = policy_data["label"].encode() print("The Doctor joins policy for label '{}'".format( label.decode("utf-8"))) doctor.join_policy(label, alices_sig_pubkey) ipfs_api = ipfsapi.connect() file = ipfs_api.get(hash_key) print(file) os.rename(hash_key, 'patient_details.msgpack') data = msgpack.load(open("patient_details.msgpack", "rb"), raw=False) message_kits = (UmbralMessageKit.from_bytes(k) for k in data['kits']) data_source = DataSource.from_public_keys( policy_public_key=policy_pubkey, datasource_public_key=data['data_source'], label=label) complete_message = [] for message_kit in message_kits: print(message_kit) try: start = timer() retrieved_plaintexts = doctor.retrieve( message_kit=message_kit, data_source=data_source, alice_verifying_key=alices_sig_pubkey) end = timer() plaintext = msgpack.loads(retrieved_plaintexts[0], raw=False) complete_message.append(plaintext) print(plaintext) #with open("details.json", "w") as write_file: # json.dump(plaintext, write_file) except Exception as e: traceback.print_exc() with open("details.json", "w") as write_file: json.dump(complete_message, write_file) return complete_message
############################################# # Alice puts her public key down and leaves # ############################################# alices_pubkey_bytes_saved_for_posterity = bytes(ALICE.stamp) print("Saying bye to Alice, who is off to receive treatment and is offline.") del ALICE ############################################## # Bobs join policies and prepare to get data # ############################################## print("Honest researcher joins the fray") BOB_A.join_policy(label_A, alices_pubkey_bytes_saved_for_posterity) BOB_D.join_policy(label_D, alices_pubkey_bytes_saved_for_posterity) ##################### # Summoning Enricos # ##################### enrico_A = Enrico(policy_encrypting_key=policy_pubkey_A) enrico_D = Enrico(policy_encrypting_key=policy_pubkey_D) print("Summoned encrypters") print("") print("") print("") ################################# # Retrieving Alice's public key #
def run_doc(): globalLogPublisher.addObserver(SimpleObserver()) ###################### # Boring setup stuff # ###################### SEEDNODE_URL = 'localhost:11501' # TODO: path joins? TEMP_DOCTOR_DIR = "{}/doctor-files".format( os.path.dirname(os.path.abspath(__file__))) # Remove previous demo files and create new ones shutil.rmtree(TEMP_DOCTOR_DIR, ignore_errors=True) ursula = Ursula.from_seed_and_stake_info(seed_uri=SEEDNODE_URL, federated_only=True, minimum_stake=0) # To create a Bob, we need the doctor's private keys previously generated. doctor_keys = get_doctor_privkeys() bob_enc_keypair = DecryptingKeypair(private_key=doctor_keys["enc"]) bob_sig_keypair = SigningKeypair(private_key=doctor_keys["sig"]) enc_power = DecryptingPower(keypair=bob_enc_keypair) sig_power = SigningPower(keypair=bob_sig_keypair) power_ups = [enc_power, sig_power] print("Creating the Doctor ...") doctor = Bob( is_me=True, federated_only=True, crypto_power_ups=power_ups, start_learning_now=True, abort_on_learning_error=True, known_nodes=[ursula], save_metadata=False, network_middleware=RestMiddleware(), ) print("Doctor = ", doctor) # Let's join the policy generated by Alicia. We just need some info about it. with open("policy-metadata.json", 'r') as f: policy_data = json.load(f) policy_pubkey = UmbralPublicKey.from_bytes( bytes.fromhex(policy_data["policy_pubkey"])) alices_sig_pubkey = UmbralPublicKey.from_bytes( bytes.fromhex(policy_data["alice_sig_pubkey"])) label = policy_data["label"].encode() print("The Doctor joins policy for label '{}'".format( label.decode("utf-8"))) doctor.join_policy(label, alices_sig_pubkey) # Now that the Doctor joined the policy in the NuCypher network, # he 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 = (UmbralMessageKit.from_bytes(k) for k in data['kits']) # The doctor also needs to create a view of the Data Source from its public keys data_source = Enrico.from_public_keys({SigningPower: data['data_source']}, policy_encrypting_key=policy_pubkey) # Now he can ask the NuCypher network to get a re-encrypted version of each MessageKit. for message_kit in message_kits: try: start = timer() retrieved_plaintexts = doctor.retrieve( label=label, message_kit=message_kit, data_source=data_source, alice_verifying_key=alices_sig_pubkey) 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'] timestamp = maya.MayaDT(plaintext['timestamp']) # This code block simply pretty prints the heart rate info terminal_size = shutil.get_terminal_size().columns max_width = min(terminal_size, 120) columns = max_width - 12 - 27 scale = columns / 40 scaled_heart_rate = int(scale * (heart_rate - 60)) retrieval_time = "Retrieval time: {:8.2f} ms".format(1000 * (end - start)) line = ("-" * scaled_heart_rate) + "❤︎ ({} BPM)".format(heart_rate) line = line.ljust(max_width - 27, " ") + retrieval_time print(line) except Exception as e: # We just want to know what went wrong and continue the demo traceback.print_exc()
def decryptDelegated(): # Fetch Request Data # { # "bobKeys": "{\"enc\": \"40f05590a27491caf37049366fefd43e46034e4308f4f1fd233c166bc3980ab4\", \"sig\": \"3bcf21d3cb160118b499a883023569c60476f8731bd9eade11016c5030c1ca5d\"}", # "policy_public_key": "02aef01b40c0a62a9a1f650dd9a8381695e21a7b3826c748a5b64831aa0dd9862c", # "alice_sig_pubkey": "036c5d361000e6fbf3c4a84c98f924a3206e8a72c758a67e8300b5bee111b5fa97", # "label": "1stlabel", # "message": "messagekit", # "data_source": "03a38eef9fd09c9841585dea93791e139a3003d540539673c8c719af55e46c0c1b", # } json_data = json.loads(request.data.decode('utf-8')) bob_private_keys = json.loads(json_data['bobKeys']) policy_public_key = json_data['policy_public_key'] alice_signing_key = json_data['alice_sig_pubkey'] label = json_data['label'] # username = json_data['username'] message = json_data['message'] data_source = json_data['data_source'] data_source = bytes.fromhex(data_source) print (bob_private_keys['enc']) enc = UmbralPrivateKey.from_bytes(bytes.fromhex(bob_private_keys["enc"])) sig = UmbralPrivateKey.from_bytes(bytes.fromhex(bob_private_keys["sig"])) # signingPublic = sig.get_pubkey() # bobFilePath = os.path.join(os.getcwd(), 'bob/' + username + '.json') # doctor_pubkeys = _get_keys(bobFilePath, UmbralPublicKey) # print (signingPublic == doctor_pubkeys['sig']) # print (signingPublic) # print (doctor_pubkeys['sig']) print ('\n\n\n') bob_enc_keypair = DecryptingKeypair(private_key=enc) bob_sig_keypair = SigningKeypair(private_key=sig) enc_power = DecryptingPower(keypair=bob_enc_keypair) sig_power = SigningPower(keypair=bob_sig_keypair) power_ups = [enc_power, sig_power] doctor = Bob( domains={'TEMPORARY_DOMAIN'}, is_me=True, federated_only=True, crypto_power_ups=power_ups, start_learning_now=True, abort_on_learning_error=True, known_nodes={ursula}, save_metadata=False, network_middleware=RestMiddleware() ) policy_pubkey = UmbralPublicKey.from_bytes(bytes.fromhex(policy_public_key)) alices_sig_pubkey = UmbralPublicKey.from_bytes(bytes.fromhex(alice_signing_key)) label = label.encode() doctor.join_policy(label, alices_sig_pubkey) message_kit = UmbralMessageKit.from_bytes(bytes.fromhex(message)) print (message_kit == MessageKit) print (message_kit) print (MessageKit) print ('\n\n\n') data_source = Enrico.from_public_keys( {SigningPower: data_source}, policy_encrypting_key=policy_pubkey ) retrieved_plaintexts = doctor.retrieve( label=label, message_kit=message_kit, data_source=data_source, alice_verifying_key=alices_sig_pubkey ) # the object to be sent back to front end # { # "fileFieldCount": 2, # "textFieldCount": 2, # "files (stringified)": { # "fileKey1": "fileUrl1", # "fileKey2": "fileUrl2" # }, # "textFields (stringified)": { # "age": "18", # "name": "arvind" # } # } plaintext = msgpack.loads(retrieved_plaintexts[0], raw=False) # the object from plaintext data_obj = createDataObject(plaintext, json_data['label']) return jsonify(data_obj)
def decryptDelegated(): json_data = json.loads(request.data.decode('utf-8')) bob_private_keys = json.loads(json_data['bobKeys']) policy_public_key = json_data['policy_public_key'] alice_signing_key = json_data['alice_sig_pubkey'] label = json_data['label'] # username = json_data['username'] message = json_data['message'] data_source = json_data['data_source'] data_source = bytes.fromhex(data_source) print (bob_private_keys['enc']) enc = UmbralPrivateKey.from_bytes(bytes.fromhex(bob_private_keys["enc"])) sig = UmbralPrivateKey.from_bytes(bytes.fromhex(bob_private_keys["sig"])) # signingPublic = sig.get_pubkey() # bobFilePath = os.path.join(os.getcwd(), 'bob/' + username + '.json') # doctor_pubkeys = _get_keys(bobFilePath, UmbralPublicKey) # print (signingPublic == doctor_pubkeys['sig']) # print (signingPublic) # print (doctor_pubkeys['sig']) print ('\n\n\n') bob_enc_keypair = DecryptingKeypair(private_key=enc) bob_sig_keypair = SigningKeypair(private_key=sig) enc_power = DecryptingPower(keypair=bob_enc_keypair) sig_power = SigningPower(keypair=bob_sig_keypair) power_ups = [enc_power, sig_power] doctor = Bob( domains={'TEMPORARY_DOMAIN'}, is_me=True, federated_only=True, crypto_power_ups=power_ups, start_learning_now=True, abort_on_learning_error=True, known_nodes={ursula}, save_metadata=False, network_middleware=RestMiddleware() ) policy_pubkey = UmbralPublicKey.from_bytes(bytes.fromhex(policy_public_key)) alices_sig_pubkey = UmbralPublicKey.from_bytes(bytes.fromhex(alice_signing_key)) label = label.encode() doctor.join_policy(label, alices_sig_pubkey) message_kit = UmbralMessageKit.from_bytes(bytes.fromhex(message)) print (message_kit == MessageKit) print (message_kit) print (MessageKit) print ('\n\n\n') data_source = Enrico.from_public_keys( {SigningPower: data_source}, policy_encrypting_key=policy_pubkey ) retrieved_plaintexts = doctor.retrieve( label=label, message_kit=message_kit, data_source=data_source, alice_verifying_key=alices_sig_pubkey ) # the object to be sent back to front end # { # "fileFieldCount": 2, # "textFieldCount": 2, # "files (stringified)": { # "fileKey1": "fileUrl1", # "fileKey2": "fileUrl2" # }, # "textFields (stringified)": { # "age": "18", # "name": "arvind" # } # } plaintext = msgpack.loads(retrieved_plaintexts[0], raw=False) # the object from plaintext # data_obj = createDataObject(plaintext, json_data['label']) return jsonify(plaintext)
def test_bob_joins_policy_and_retrieves(federated_alice, federated_ursulas, certificates_tempdir, ): # Let's partition Ursulas in two parts a_couple_of_ursulas = list(federated_ursulas)[:2] rest_of_ursulas = list(federated_ursulas)[2:] # Bob becomes bob = Bob(federated_only=True, start_learning_now=True, network_middleware=MockRestMiddleware(), abort_on_learning_error=True, known_nodes=a_couple_of_ursulas, ) # Bob only knows a couple of Ursulas initially assert len(bob.known_nodes) == 2 # Alice creates a policy granting access to Bob # Just for fun, let's assume she distributes KFrags among Ursulas unknown to Bob n = NUMBER_OF_URSULAS_IN_DEVELOPMENT_NETWORK - 2 label = b'label://' + os.urandom(32) contract_end_datetime = maya.now() + datetime.timedelta(days=5) policy = federated_alice.grant(bob=bob, label=label, m=3, n=n, expiration=contract_end_datetime, handpicked_ursulas=set(rest_of_ursulas), ) assert bob == policy.bob assert label == policy.label # Now, Bob joins the policy bob.join_policy(label=label, alice_pubkey_sig=federated_alice.stamp, block=True) # In the end, Bob should know all the Ursulas assert len(bob.known_nodes) == len(federated_ursulas) # Enrico becomes enrico = Enrico(policy_encrypting_key=policy.public_key) plaintext = b"What's your approach? Mississippis or what?" message_kit, _signature = enrico.encrypt_message(plaintext) alices_verifying_key = federated_alice.stamp.as_umbral_pubkey() # Bob takes the message_kit and retrieves the message within delivered_cleartexts = bob.retrieve(message_kit=message_kit, data_source=enrico, alice_verifying_key=alices_verifying_key, label=policy.label) assert plaintext == delivered_cleartexts[0] # FIXME: Bob tries to retrieve again # delivered_cleartexts = bob.retrieve(message_kit=message_kit, # data_source=enrico, # alice_verifying_key=alices_verifying_key, # label=policy.label) # # assert plaintext == delivered_cleartexts[0] # # Let's try retrieve again, but Alice revoked the policy. failed_revocations = federated_alice.revoke(policy) assert len(failed_revocations) == 0 with pytest.raises(Ursula.NotEnoughUrsulas): _cleartexts = bob.retrieve(message_kit=message_kit, data_source=enrico, alice_verifying_key=alices_verifying_key, label=policy.label)
def downloadFile(self, downloadFilename, recipient_privkeys, receipt, policy_info): hash = receipt['hash_key'] input = self.ipfs.cat(hash) ursula = Ursula.from_seed_and_stake_info( seed_uri=self.URSULA_SEEDNODE_URI, federated_only=True, minimum_stake=0) bob_enc_keypair = DecryptingKeypair( private_key=UmbralPrivateKey.from_bytes( bytes.fromhex(recipient_privkeys["enc"]))) bob_sig_keypair = SigningKeypair( private_key=UmbralPrivateKey.from_bytes( bytes.fromhex(recipient_privkeys["sig"]))) enc_power = DecryptingPower(keypair=bob_enc_keypair) sig_power = SigningPower(keypair=bob_sig_keypair) power_ups = [enc_power, sig_power] authorizedRecipient = Bob( is_me=True, federated_only=True, crypto_power_ups=power_ups, start_learning_now=True, abort_on_learning_error=True, known_nodes=[ursula], save_metadata=False, network_middleware=RestMiddleware(), ) policy_pubkey = UmbralPublicKey.from_bytes( bytes.fromhex(policy_info["policy_pubkey"])) enrico_as_understood = Enrico.from_public_keys( { SigningPower: UmbralPublicKey.from_bytes( bytes.fromhex(receipt['data_source_public_key'])) }, #{SigningPower: data_source_public_key}, policy_encrypting_key=policy_pubkey) alice_pubkey_restored = UmbralPublicKey.from_bytes( (policy_info['alice_sig_pubkey'])) authorizedRecipient.join_policy(policy_info['label'].encode(), alice_pubkey_restored) kit = UmbralMessageKit.from_bytes(input) delivered_cleartexts = authorizedRecipient.retrieve( message_kit=kit, data_source=enrico_as_understood, alice_verifying_key=alice_pubkey_restored, label=(policy_info['label'].encode())) #delivered_cleartexts = authorizedRecipient.retrieve(message_kit=kit,data_source=data_source,alice_verifying_key=alice_pubkey_restored, label=(policy_info['label'].encode()) ) data = base64.b64decode(delivered_cleartexts[0]) output = open('./' + downloadFilename, 'wb') output.write(data) output.close()