def reencrypt_via_rest(self, id_as_hex, request: http.Request): from nucypher.policy.models import WorkOrder # Avoid circular import id = binascii.unhexlify(id_as_hex) work_order = WorkOrder.from_rest_payload(id, request.body) self.log.info("Work Order from {}, signed {}".format( work_order.bob, work_order.receipt_signature)) with ThreadedSession(self.db_engine) as session: kfrag_bytes = self.datastore.get_policy_arrangement( id.hex().encode(), session=session).k_frag # Careful! :-) # TODO: Push this to a lower level. kfrag = KFrag.from_bytes(kfrag_bytes) cfrag_byte_stream = b"" for capsule in work_order.capsules: # TODO: Sign the result of this. See #141. cfrag = pre.reencrypt(kfrag, capsule) self.log.info( "Re-encrypting for Capsule {}, made CFrag {}.".format( capsule, cfrag)) cfrag_byte_stream += VariableLengthBytestring(cfrag) # TODO: Put this in Ursula's datastore self._work_orders.append(work_order) headers = {'Content-Type': 'application/octet-stream'} return Response(content=cfrag_byte_stream, headers=headers)
def generate_work_orders(self, map_id, *capsules, num_ursulas=None): from nucypher.policy.models import WorkOrder # Prevent circular import try: treasure_map_to_use = self.treasure_maps[map_id] except KeyError: raise KeyError( "Bob doesn't have the TreasureMap {}; can't generate work orders.".format(map_id)) generated_work_orders = OrderedDict() if not treasure_map_to_use: raise ValueError( "Bob doesn't have a TreasureMap to match any of these capsules: {}".format( capsules)) for node_id, arrangement_id in treasure_map_to_use: ursula = self.known_nodes[node_id] capsules_to_include = [] for capsule in capsules: if not capsule in self._saved_work_orders[node_id]: capsules_to_include.append(capsule) if capsules_to_include: work_order = WorkOrder.construct_by_bob( arrangement_id, capsules_to_include, ursula, self) generated_work_orders[node_id] = work_order self._saved_work_orders[node_id][capsule] = work_order if num_ursulas is not None: if num_ursulas == len(generated_work_orders): break return generated_work_orders
def reencrypt_via_rest(id_as_hex): from nucypher.policy.models import WorkOrder # Avoid circular import arrangement_id = binascii.unhexlify(id_as_hex) work_order = WorkOrder.from_rest_payload(arrangement_id, request.data) log.info("Work Order from {}, signed {}".format(work_order.bob, work_order.receipt_signature)) with ThreadedSession(db_engine) as session: policy_arrangement = datastore.get_policy_arrangement(arrangement_id=id_as_hex.encode(), session=session) kfrag_bytes = policy_arrangement.kfrag # Careful! :-) verifying_key_bytes = policy_arrangement.alice_pubkey_sig.key_data # TODO: Push this to a lower level. kfrag = KFrag.from_bytes(kfrag_bytes) alices_verifying_key = UmbralPublicKey.from_bytes(verifying_key_bytes) cfrag_byte_stream = b"" for capsule, capsule_signature in zip(work_order.capsules, work_order.capsule_signatures): # This is the capsule signed by Bob capsule_signature = bytes(capsule_signature) # Ursula signs on top of it. Now both are committed to the same capsule. capsule_signed_by_both = bytes(stamp(capsule_signature)) capsule.set_correctness_keys(verifying=alices_verifying_key) cfrag = pre.reencrypt(kfrag, capsule, metadata=capsule_signed_by_both) log.info("Re-encrypting for {}, made {}.".format(capsule, cfrag)) signature = stamp(bytes(cfrag) + bytes(capsule)) cfrag_byte_stream += VariableLengthBytestring(cfrag) + signature # TODO: Put this in Ursula's datastore work_order_tracker.append(work_order) headers = {'Content-Type': 'application/octet-stream'} return Response(response=cfrag_byte_stream, headers=headers)
def _mock_ursula_reencrypts(ursula, corrupt_cfrag: bool = False): delegating_privkey = UmbralPrivateKey.gen_key() _symmetric_key, capsule = pre._encapsulate(delegating_privkey.get_pubkey()) signing_privkey = UmbralPrivateKey.gen_key() signing_pubkey = signing_privkey.get_pubkey() signer = Signer(signing_privkey) priv_key_bob = UmbralPrivateKey.gen_key() pub_key_bob = priv_key_bob.get_pubkey() kfrags = pre.generate_kfrags(delegating_privkey=delegating_privkey, signer=signer, receiving_pubkey=pub_key_bob, threshold=2, N=4, sign_delegating_key=False, sign_receiving_key=False) capsule.set_correctness_keys(delegating_privkey.get_pubkey(), pub_key_bob, signing_pubkey) ursula_pubkey = ursula.stamp.as_umbral_pubkey() alice_address = canonical_address_from_umbral_key(signing_pubkey) blockhash = bytes(32) specification = b''.join((bytes(capsule), bytes(ursula_pubkey), bytes(ursula.decentralized_identity_evidence), alice_address, blockhash)) bobs_signer = Signer(priv_key_bob) task_signature = bytes(bobs_signer(specification)) metadata = bytes(ursula.stamp(task_signature)) cfrag = pre.reencrypt(kfrags[0], capsule, metadata=metadata) if corrupt_cfrag: cfrag.proof.bn_sig = CurveBN.gen_rand(capsule.params.curve) cfrag_signature = bytes(ursula.stamp(bytes(cfrag))) bob = Bob.from_public_keys(verifying_key=pub_key_bob) task = WorkOrder.Task(capsule, task_signature, cfrag, cfrag_signature) work_order = WorkOrder(bob, None, alice_address, [task], None, ursula, blockhash) evidence = IndisputableEvidence(task, work_order) return evidence
def reencrypt_via_rest(id_as_hex): from nucypher.policy.models import WorkOrder # Avoid circular import arrangement_id = binascii.unhexlify(id_as_hex) work_order = WorkOrder.from_rest_payload(arrangement_id, request.data) log.info("Work Order from {}, signed {}".format( work_order.bob, work_order.receipt_signature)) with ThreadedSession(db_engine) as session: policy_arrangement = datastore.get_policy_arrangement( arrangement_id=id_as_hex.encode(), session=session) kfrag_bytes = policy_arrangement.kfrag # Careful! :-) verifying_key_bytes = policy_arrangement.alice_pubkey_sig.key_data # TODO: Push this to a lower level. Perhaps to Ursula character? #619 kfrag = KFrag.from_bytes(kfrag_bytes) alices_verifying_key = UmbralPublicKey.from_bytes(verifying_key_bytes) cfrag_byte_stream = b"" alices_address = canonical_address_from_umbral_key( alices_verifying_key) if not alices_address == work_order.alice_address: message = f"This Bob ({work_order.bob}) sent an Alice's ETH address " \ f"({work_order.alice_address}) that doesn't match " \ f"the one I have ({alices_address})." raise SuspiciousActivity(message) bob_pubkey = work_order.bob.stamp.as_umbral_pubkey() if not work_order.alice_address_signature.verify( message=alices_address, verifying_key=bob_pubkey): message = f"This Bob ({work_order.bob}) sent an invalid signature of Alice's ETH address" raise InvalidSignature(message) # This is Bob's signature of Alice's verifying key as ETH address. alice_address_signature = bytes(work_order.alice_address_signature) for capsule, capsule_signature in zip(work_order.capsules, work_order.capsule_signatures): # This is the capsule signed by Bob capsule_signature = bytes(capsule_signature) # Ursula signs on top of it. Now both are committed to the same capsule. # She signs Alice's address too. ursula_signature = stamp(capsule_signature + alice_address_signature) capsule.set_correctness_keys(verifying=alices_verifying_key) cfrag = pre.reencrypt(kfrag, capsule, metadata=bytes(ursula_signature)) log.info(f"Re-encrypting for {capsule}, made {cfrag}.") signature = stamp(bytes(cfrag) + bytes(capsule)) cfrag_byte_stream += VariableLengthBytestring(cfrag) + signature # TODO: Put this in Ursula's datastore work_order_tracker.append(work_order) headers = {'Content-Type': 'application/octet-stream'} return Response(response=cfrag_byte_stream, headers=headers)
def reencrypt_via_rest(id_as_hex): # TODO: How to pass Ursula's identity evidence to Bob? #962 # 'Identity evidence' is a signature of her stamp with the checksum address from nucypher.policy.models import WorkOrder # Avoid circular import arrangement_id = binascii.unhexlify(id_as_hex) with ThreadedSession(db_engine) as session: policy_arrangement = datastore.get_policy_arrangement( arrangement_id=id_as_hex.encode(), session=session) kfrag_bytes = policy_arrangement.kfrag # Careful! :-) verifying_key_bytes = policy_arrangement.alice_pubkey_sig.key_data # TODO: Push this to a lower level. Perhaps to Ursula character? #619 kfrag = KFrag.from_bytes(kfrag_bytes) alices_verifying_key = UmbralPublicKey.from_bytes(verifying_key_bytes) alices_address = canonical_address_from_umbral_key( alices_verifying_key) work_order = WorkOrder.from_rest_payload(arrangement_id=arrangement_id, rest_payload=request.data, ursula_pubkey_bytes=bytes( this_node.stamp), alice_address=alices_address) log.info( f"Work Order from {work_order.bob}, signed {work_order.receipt_signature}" ) cfrag_byte_stream = b"" for task in work_order.tasks: # Ursula signs on top of Bob's signature of each task. # Now both are committed to the same task. See #259. reencryption_metadata = bytes( this_node.stamp(bytes(task.signature))) capsule = task.capsule capsule.set_correctness_keys(verifying=alices_verifying_key) cfrag = pre.reencrypt(kfrag, capsule, metadata=reencryption_metadata) log.info(f"Re-encrypting for {capsule}, made {cfrag}.") # Finally, Ursula commits to her result reencryption_signature = this_node.stamp(bytes(cfrag)) cfrag_byte_stream += VariableLengthBytestring( cfrag) + reencryption_signature # TODO: Put this in Ursula's datastore this_node._work_orders.append(work_order) headers = {'Content-Type': 'application/octet-stream'} return Response(response=cfrag_byte_stream, headers=headers)
def reencrypt_via_rest(self, hrac_as_hex, request: http.Request): from nucypher.policy.models import WorkOrder # Avoid circular import hrac = binascii.unhexlify(hrac_as_hex) work_order = WorkOrder.from_rest_payload(hrac, request.body) with ThreadedSession(self.db_engine) as session: kfrag_bytes = self.datastore.get_policy_arrangement( hrac.hex().encode(), session=session).k_frag # Careful! :-) # TODO: Push this to a lower level. kfrag = KFrag.from_bytes(kfrag_bytes) cfrag_byte_stream = b"" for capsule in work_order.capsules: # TODO: Sign the result of this. See #141. cfrag_byte_stream += VariableLengthBytestring( pre.reencrypt(kfrag, capsule)) # TODO: Put this in Ursula's datastore self._work_orders.append(work_order) headers = {'Content-Type': 'application/octet-stream'} return Response(content=cfrag_byte_stream, headers=headers)
def generate_work_orders(self, kfrag_hrac, *capsules, num_ursulas=None): from nucypher.policy.models import WorkOrder # Prevent circular import try: treasure_map_to_use = self.treasure_maps[kfrag_hrac] except KeyError: raise KeyError( "Bob doesn't have a TreasureMap matching the hrac {}".format( kfrag_hrac)) generated_work_orders = OrderedDict() if not treasure_map_to_use: raise ValueError( "Bob doesn't have a TreasureMap to match any of these capsules: {}" .format(capsules)) for ursula_dht_key in treasure_map_to_use: ursula = self.known_nodes[UmbralPublicKey.from_bytes( ursula_dht_key)] capsules_to_include = [] for capsule in capsules: if not capsule in self._saved_work_orders[ursula_dht_key]: capsules_to_include.append(capsule) if capsules_to_include: work_order = WorkOrder.construct_by_bob( kfrag_hrac, capsules_to_include, ursula, self) generated_work_orders[ursula_dht_key] = work_order self._saved_work_orders[ursula_dht_key][capsule] = work_order if num_ursulas is not None: if num_ursulas == len(generated_work_orders): break return generated_work_orders