def test_capsule_as_dict_key(alices_keys): priv_key_alice, pub_key_alice = alices_keys plain_data = b'peace at dawn' ciphertext, capsule = pre.encrypt(pub_key_alice, plain_data) # We can use the capsule as a key, and successfully lookup using it. some_dict = {capsule: "Thing that Bob wants to try per-Capsule"} assert some_dict[capsule] == "Thing that Bob wants to try per-Capsule" kfrags = pre.split_rekey(alices_keys.priv, alices_keys.pub, 1, 2) cfrag = pre.reencrypt(kfrags[0], capsule) capsule.attach_cfrag(cfrag) cfrag = pre.reencrypt(kfrags[1], capsule) capsule.attach_cfrag(cfrag) # Even if we activate the capsule, it still serves as the same key. cleartext = pre.decrypt(ciphertext, capsule, alices_keys.priv, alices_keys.pub) assert some_dict[capsule] == "Thing that Bob wants to try per-Capsule" assert cleartext == plain_data # And if we change the value for this key, all is still well. some_dict[capsule] = "Bob has changed his mind." assert some_dict[capsule] == "Bob has changed his mind." assert len(some_dict.keys()) == 1
def test_cheating_ursula_replays_old_reencryption(N, M): priv_key_alice = keys.UmbralPrivateKey.gen_key() pub_key_alice = priv_key_alice.get_pubkey() priv_key_bob = keys.UmbralPrivateKey.gen_key() pub_key_bob = priv_key_bob.get_pubkey() sym_key_alice1, capsule_alice1 = pre._encapsulate(pub_key_alice.point_key) sym_key_alice2, capsule_alice2 = pre._encapsulate(pub_key_alice.point_key) kfrags = pre.split_rekey(priv_key_alice, pub_key_bob, M, N) cfrags, metadata = [], [] for i, kfrag in enumerate(kfrags): # Example of potential metadata to describe the re-encryption request metadata_i = "This is an example of metadata for re-encryption request #{}" metadata_i = metadata_i.format(i).encode() if i == 0: # Let's put the re-encryption of a different Alice ciphertext cfrag = pre.reencrypt(kfrag, capsule_alice2, metadata=metadata_i) else: cfrag = pre.reencrypt(kfrag, capsule_alice1, metadata=metadata_i) capsule_alice1.attach_cfrag(cfrag) cfrags.append(cfrag) # Let's activate the capsule capsule_alice1._reconstruct_shamirs_secret(pub_key_alice, priv_key_bob) with pytest.raises(pre.GenericUmbralError): sym_key = pre._decapsulate_reencrypted(pub_key_bob.point_key, priv_key_bob.bn_key, pub_key_alice.point_key, capsule_alice1) assert not cfrags[0].verify_correctness( capsule_alice1, pub_key_alice, pub_key_bob, ) # The response of cheating Ursula is in cfrags[0], # so the rest of CFrags should be correct: for cfrag_i, metadata_i in zip(cfrags[1:], metadata[1:]): assert cfrag_i.verify_correctness( capsule_alice1, pub_key_alice, pub_key_bob, ) # Alternatively, we can try to open the capsule directly. # We should get an exception with an attached list of incorrect cfrags with pytest.raises(pre.UmbralCorrectnessError) as exception_info: _ = pre._open_capsule(capsule_alice1, priv_key_bob, pub_key_alice) correctness_error = exception_info.value assert cfrags[0] in correctness_error.offending_cfrags assert len(correctness_error.offending_cfrags) == 1
def test_cheating_ursula_replays_old_reencryption(N, M): priv_key_alice = keys.UmbralPrivateKey.gen_key() pub_key_alice = priv_key_alice.get_pubkey() priv_key_bob = keys.UmbralPrivateKey.gen_key() pub_key_bob = priv_key_bob.get_pubkey() sym_key_alice1, capsule_alice1 = pre._encapsulate(pub_key_alice.point_key) sym_key_alice2, capsule_alice2 = pre._encapsulate(pub_key_alice.point_key) kfrags = pre.split_rekey(priv_key_alice, pub_key_bob, M, N) cfrags, challenges = [], [] for index, kfrag in enumerate(kfrags): if index == 0: # Let's put the re-encryption of a different Alice ciphertext cfrag = pre.reencrypt(kfrag, capsule_alice2) else: cfrag = pre.reencrypt(kfrag, capsule_alice1) metadata = ("Challenge metadata: index {}".format(index)).encode() challenge = pre._challenge(kfrag, capsule_alice1, cfrag, metadata) capsule_alice1.attach_cfrag(cfrag) challenges.append(challenge) cfrags.append(cfrag) # Let's activate the capsule capsule_alice1._reconstruct_shamirs_secret(pub_key_alice, priv_key_bob) with pytest.raises(pre.GenericUmbralError): sym_key = pre._decapsulate_reencrypted(pub_key_bob.point_key, priv_key_bob.bn_key, pub_key_alice.point_key, capsule_alice1) metadata = b"Challenge metadata: index 0" assert not pre._check_challenge(capsule_alice1, cfrags[0], challenges[0], pub_key_alice.point_key, pub_key_bob.point_key, metadata ) # The response of cheating Ursula is in capsules[0], # so the rest of challenges chould be correct: for i, challenge in enumerate(challenges[1:], 1): cfrag = cfrags[i] metadata = ("Challenge metadata: index {}".format(i)).encode() assert pre._check_challenge(capsule_alice1, cfrag, challenge, pub_key_alice.point_key, pub_key_bob.point_key, metadata )
def test_cheating_ursula_replays_old_reencryption(N, M): priv_key_alice = keys.UmbralPrivateKey.gen_key() pub_key_alice = priv_key_alice.get_pubkey() priv_key_bob = keys.UmbralPrivateKey.gen_key() pub_key_bob = priv_key_bob.get_pubkey() sym_key_alice1, capsule_alice1 = pre._encapsulate(pub_key_alice.point_key) sym_key_alice2, capsule_alice2 = pre._encapsulate(pub_key_alice.point_key) kfrags = pre.split_rekey(priv_key_alice, pub_key_bob, M, N) cfrags, challenges, metadata = [], [], [] for i, kfrag in enumerate(kfrags): if i == 0: # Let's put the re-encryption of a different Alice ciphertext cfrag = pre.reencrypt(kfrag, capsule_alice2) else: cfrag = pre.reencrypt(kfrag, capsule_alice1) # Example of potential metadata to describe the challenge request metadata_i = { 'ursula_id': i, 'timestamp': time.time(), 'capsule': bytes(capsule_alice1), 'cfrag': bytes(cfrag) } metadata.append(str(metadata_i).encode()) challenge = pre._challenge(kfrag, capsule_alice1, cfrag, metadata[i]) capsule_alice1.attach_cfrag(cfrag) challenges.append(challenge) cfrags.append(cfrag) # Let's activate the capsule capsule_alice1._reconstruct_shamirs_secret(pub_key_alice, priv_key_bob) with pytest.raises(pre.GenericUmbralError): sym_key = pre._decapsulate_reencrypted(pub_key_bob.point_key, priv_key_bob.bn_key, pub_key_alice.point_key, capsule_alice1) assert not pre._check_challenge(capsule_alice1, cfrags[0], challenges[0], pub_key_alice.point_key, pub_key_bob.point_key, metadata[0]) # The response of cheating Ursula is in capsules[0], # so the rest of challenges should be correct: for i, challenge in enumerate(challenges[1:], 1): cfrag = cfrags[i] assert pre._check_challenge(capsule_alice1, cfrag, challenge, pub_key_alice.point_key, pub_key_bob.point_key, metadata[i])
def test_bad_capsule_fails_reencryption(kfrags): params = default_params() bollocks_capsule = Capsule(params, point_e=Point.gen_rand(), point_v=Point.gen_rand(), bn_sig=CurveBN.gen_rand()) for kfrag in kfrags: with pytest.raises(Capsule.NotValid): pre.reencrypt(kfrag, bollocks_capsule)
def test_bad_capsule_fails_reencryption(alices_keys): priv_key_alice, pub_key_alice = alices_keys kfrags = pre.split_rekey(priv_key_alice, pub_key_alice, 1, 2) bollocks_capsule = Capsule(point_e=Point.gen_rand(), point_v=Point.gen_rand(), bn_sig=CurveBN.gen_rand()) with pytest.raises(Capsule.NotValid): pre.reencrypt(kfrags[0], bollocks_capsule)
def test_cheating_ursula_replays_old_reencryption(N, M): priv_key_alice = keys.UmbralPrivateKey.gen_key() pub_key_alice = priv_key_alice.get_pubkey() priv_key_bob = keys.UmbralPrivateKey.gen_key() pub_key_bob = priv_key_bob.get_pubkey() sym_key_alice1, capsule_alice1 = pre._encapsulate(pub_key_alice.point_key) sym_key_alice2, capsule_alice2 = pre._encapsulate(pub_key_alice.point_key) k_frags = pre.split_rekey(priv_key_alice, pub_key_bob, M, N) c_frags, challenges = [], [] for index, k_frag in enumerate(k_frags): if index == 0: # Let's put the re-encryption of a different Alice ciphertext c_frag = pre.reencrypt(k_frag, capsule_alice2) else: c_frag = pre.reencrypt(k_frag, capsule_alice1) challenge = pre.challenge(k_frag, capsule_alice1, c_frag) capsule_alice1.attach_cfrag(c_frag) challenges.append(challenge) c_frags.append(c_frag) capsule_alice1._reconstruct_shamirs_secret() # activate capsule with pytest.raises(pre.GenericUmbralError): sym_key = pre.decapsulate_reencrypted(pub_key_bob.point_key, priv_key_bob.bn_key, pub_key_alice.point_key, capsule_alice1) assert not sym_key == sym_key_alice1 assert not pre.check_challenge( capsule_alice1, c_frags[0], challenges[0], pub_key_alice.point_key, pub_key_bob.point_key, ) # The response of cheating Ursula is in capsules[0], # so the rest of challenges chould be correct: for (c_frag, ch) in zip(c_frags[1:], challenges[1:]): assert pre.check_challenge( capsule_alice1, c_frag, ch, pub_key_alice.point_key, pub_key_bob.point_key, )
def test_cheating_ursula_replays_old_reencryption(alices_keys, bobs_keys, kfrags, prepared_capsule): delegating_privkey, signing_privkey = alices_keys delegating_pubkey = delegating_privkey.get_pubkey() receiving_privkey, receiving_pubkey = bobs_keys capsule_alice1 = prepared_capsule _unused_key2, capsule_alice2 = pre._encapsulate(delegating_pubkey) capsule_alice2.set_correctness_keys(delegating=delegating_pubkey, receiving=receiving_pubkey, verifying=signing_privkey.get_pubkey()) cfrags = [] for i, kfrag in enumerate(kfrags): # Example of potential metadata to describe the re-encryption request metadata_i = "This is an example of metadata for re-encryption request #{}" metadata_i = metadata_i.format(i).encode() if i == 0: # Let's put the re-encryption of a different Alice ciphertext cfrag = pre.reencrypt(kfrag, capsule_alice2, metadata=metadata_i) else: cfrag = pre.reencrypt(kfrag, capsule_alice1, metadata=metadata_i) cfrags.append(cfrag) # CFrag 0 is not valid ... assert not cfrags[0].verify_correctness(capsule_alice1) # ... and trying to attach it raises an error. with pytest.raises(pre.UmbralCorrectnessError) as exception_info: capsule_alice1.attach_cfrag(cfrags[0]) correctness_error = exception_info.value assert cfrags[0] in correctness_error.offending_cfrags assert len(correctness_error.offending_cfrags) == 1 # The rest of CFrags should be correct: correct_cases = 0 for cfrag_i in cfrags[1:]: assert cfrag_i.verify_correctness(capsule_alice1) capsule_alice1.attach_cfrag(cfrag_i) correct_cases += 1 assert correct_cases == len(cfrags[1:])
def test_bad_capsule_fails_reencryption(alices_keys, bobs_keys): delegating_privkey, _signing_privkey = alices_keys signer_alice = Signer(_signing_privkey) _receiving_privkey, receiving_pubkey = bobs_keys kfrags = pre.split_rekey(delegating_privkey, signer_alice, receiving_pubkey, 1, 2) bollocks_capsule = Capsule(point_e=Point.gen_rand(), point_v=Point.gen_rand(), bn_sig=CurveBN.gen_rand()) with pytest.raises(Capsule.NotValid): pre.reencrypt(kfrags[0], bollocks_capsule)
def test_m_of_n(N, M, alices_keys, bobs_keys): priv_key_alice, pub_key_alice = alices_keys priv_key_bob, pub_key_bob = bobs_keys sym_key, capsule = pre._encapsulate(pub_key_alice.point_key) kfrags = pre.split_rekey(priv_key_alice, pub_key_bob, M, N) for kfrag in kfrags: assert kfrag.verify(pub_key_alice.point_key, pub_key_bob.point_key) for i, kfrag in enumerate(kfrags[:M]): # Example of potential metadata to describe the re-encryption request metadata = "This is an example of metadata for re-encryption request #{}" metadata = metadata.format(i).encode() cfrag = pre.reencrypt(kfrag, capsule, metadata=metadata) capsule.attach_cfrag(cfrag) assert pre._verify_correctness( capsule, cfrag, pub_key_alice.point_key, pub_key_bob.point_key, ) # assert capsule.is_openable_by_bob() # TODO: Is it possible to check here if >= m cFrags have been attached? sym_key_from_capsule = pre._open_capsule(capsule, priv_key_bob, pub_key_alice) assert sym_key == sym_key_from_capsule
def test_cheating_ursula_sends_garbage(N, M): priv_key_alice = keys.UmbralPrivateKey.gen_key() pub_key_alice = priv_key_alice.get_pubkey() # Bob priv_key_bob = keys.UmbralPrivateKey.gen_key() pub_key_bob = priv_key_bob.get_pubkey() sym_key, capsule_alice = pre._encapsulate(pub_key_alice.point_key) kfrags = pre.split_rekey(priv_key_alice, pub_key_bob, M, N) cfrags, metadata = [], [] for i, kfrag in enumerate(kfrags[:M]): # Example of potential metadata to describe the re-encryption request metadata_i = "This is an example of metadata for re-encryption request #{}" metadata_i = metadata_i.format(i).encode() cfrag = pre.reencrypt(kfrag, capsule_alice, metadata=metadata_i) capsule_alice.attach_cfrag(cfrag) cfrags.append(cfrag) # Let's put random garbage in one of the cfrags cfrags[0]._point_e1 = Point.gen_rand() cfrags[0]._point_v1 = Point.gen_rand() capsule_alice._reconstruct_shamirs_secret(pub_key_alice, priv_key_bob) # activate capsule with pytest.raises(pre.GenericUmbralError): _unused_key = pre._decapsulate_reencrypted(pub_key_bob.point_key, priv_key_bob.bn_key, pub_key_alice.point_key, capsule_alice) assert not pre._verify_correctness( capsule_alice, cfrags[0], pub_key_alice.point_key, pub_key_bob.point_key, ) # The response of cheating Ursula is in cfrags[0], # so the rest of CFrags chould be correct: for cfrag_i, metadata_i in zip(cfrags[1:], metadata[1:]): assert pre._verify_correctness( capsule_alice, cfrag_i, pub_key_alice.point_key, pub_key_bob.point_key, ) # Alternatively, we can try to open the capsule directly. # We should get an exception with an attached list of incorrect cfrags with pytest.raises(pre.UmbralCorrectnessError) as exception_info: _ = pre._open_capsule(capsule_alice, priv_key_bob, pub_key_alice) correctness_error = exception_info.value assert cfrags[0] in correctness_error.offending_cfrags assert len(correctness_error.offending_cfrags) == 1
def test_correctness_proof_serialization(): priv_key_alice = keys.UmbralPrivateKey.gen_key() pub_key_alice = priv_key_alice.get_pubkey() priv_key_bob = keys.UmbralPrivateKey.gen_key() pub_key_bob = priv_key_bob.get_pubkey() _unused_key, capsule = pre._encapsulate(pub_key_alice.point_key) kfrags = pre.split_rekey(priv_key_alice, pub_key_bob, 1, 2) # Example of potential metadata to describe the re-encryption request metadata = b"This is an example of metadata for re-encryption request" cfrag = pre.reencrypt(kfrags[0], capsule, metadata=metadata) capsule.attach_cfrag(cfrag) proof = cfrag.proof proof_bytes = proof.to_bytes() # A CorrectnessProof can be represented as # the 228 total bytes of four Points (33 each) and three BigNums (32 each). # TODO: Figure out final size for CorrectnessProofs # assert len(proof_bytes) == (33 * 4) + (32 * 3) == 228 new_proof = CorrectnessProof.from_bytes(proof_bytes) assert new_proof._point_e2 == proof._point_e2 assert new_proof._point_v2 == proof._point_v2 assert new_proof._point_kfrag_commitment == proof._point_kfrag_commitment assert new_proof._point_kfrag_pok == proof._point_kfrag_pok assert new_proof._bn_kfrag_sig1 == proof._bn_kfrag_sig1 assert new_proof._bn_kfrag_sig2 == proof._bn_kfrag_sig2 assert new_proof._bn_sig == proof._bn_sig assert new_proof.metadata == proof.metadata
def test_cheating_ursula_sends_garbage(kfrags, prepared_capsule): capsule_alice = prepared_capsule cfrags = [] for i, kfrag in enumerate(kfrags): # Example of potential metadata to describe the re-encryption request metadata_i = "This is an example of metadata for re-encryption request #{}" metadata_i = metadata_i.format(i).encode() cfrag = pre.reencrypt(kfrag, capsule_alice, metadata=metadata_i) cfrags.append(cfrag) # Let's put random garbage in one of the cfrags cfrags[0]._point_e1 = Point.gen_rand() cfrags[0]._point_v1 = Point.gen_rand() # Of course, this CFrag is not valid ... assert not cfrags[0].verify_correctness(capsule_alice) # ... and trying to attach it raises an error. with pytest.raises(pre.UmbralCorrectnessError) as exception_info: capsule_alice.attach_cfrag(cfrags[0]) correctness_error = exception_info.value assert cfrags[0] in correctness_error.offending_cfrags assert len(correctness_error.offending_cfrags) == 1 # The response of cheating Ursula is in cfrags[0], # so the rest of CFrags should be correct: for cfrag_i in cfrags[1:]: assert cfrag_i.verify_correctness(capsule_alice) capsule_alice.attach_cfrag(cfrag_i)
def test_simple_api(N, M, curve=default_curve()): """Manually injects umbralparameters for multi-curve testing.""" params = UmbralParameters(curve=curve) priv_key_alice = keys.UmbralPrivateKey.gen_key(params=params) pub_key_alice = priv_key_alice.get_pubkey() priv_key_bob = keys.UmbralPrivateKey.gen_key(params=params) pub_key_bob = priv_key_bob.get_pubkey() plain_data = b'peace at dawn' ciphertext, capsule = pre.encrypt(pub_key_alice, plain_data, params=params) cleartext = pre.decrypt(ciphertext, capsule, priv_key_alice, params=params) assert cleartext == plain_data kfrags = pre.split_rekey(priv_key_alice, pub_key_bob, M, N, params=params) for kfrag in kfrags: cfrag = pre.reencrypt(kfrag, capsule, params=params) capsule.attach_cfrag(cfrag) reenc_cleartext = pre.decrypt(ciphertext, capsule, priv_key_bob, pub_key_alice, params=params) assert reenc_cleartext == plain_data
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 test_m_of_n(N, M, alices_keys, bobs_keys): delegating_privkey, signing_privkey = alices_keys delegating_pubkey = delegating_privkey.get_pubkey() signer = Signer(signing_privkey) priv_key_bob, pub_key_bob = bobs_keys params = delegating_privkey.params sym_key, capsule = pre._encapsulate(delegating_pubkey) capsule.set_correctness_keys(delegating=delegating_privkey.get_pubkey(), receiving=pub_key_bob, verifying=signing_privkey.get_pubkey()) kfrags = pre.split_rekey(delegating_privkey, signer, pub_key_bob, M, N) for kfrag in kfrags: assert kfrag.verify(signing_privkey.get_pubkey(), delegating_privkey.get_pubkey(), pub_key_bob) for i, kfrag in enumerate(kfrags[:M]): # Example of potential metadata to describe the re-encryption request metadata = "This is an example of metadata for re-encryption request #{}" metadata = metadata.format(i).encode() cfrag = pre.reencrypt(kfrag, capsule, metadata=metadata) capsule.attach_cfrag(cfrag) assert cfrag.verify_correctness(capsule) sym_key_from_capsule = pre._open_capsule(capsule, priv_key_bob) assert sym_key == sym_key_from_capsule
def test_cfrag_serialization_with_proof_but_no_metadata( prepared_capsule, kfrags): for kfrag in kfrags: cfrag = pre.reencrypt(kfrag, prepared_capsule, provide_proof=True) cfrag_bytes = cfrag.to_bytes() proof = cfrag.proof assert proof is not None assert proof.metadata is None # A CFrag can be represented as the 131 total bytes of three Points (33 each) and a CurveBN (32). # TODO: Figure out final size for CFrags with proofs # assert len(cfrag_bytes) == 33 + 33 + 33 + 32 == 131 new_cfrag = CapsuleFrag.from_bytes(cfrag_bytes) assert new_cfrag.point_e1 == cfrag.point_e1 assert new_cfrag.point_v1 == cfrag.point_v1 assert new_cfrag.kfrag_id == cfrag.kfrag_id assert new_cfrag.point_precursor == cfrag.point_precursor new_proof = new_cfrag.proof assert new_proof is not None assert new_proof.point_e2 == proof.point_e2 assert new_proof.point_v2 == proof.point_v2 assert new_proof.point_kfrag_commitment == proof.point_kfrag_commitment assert new_proof.point_kfrag_pok == proof.point_kfrag_pok assert new_proof.bn_sig == proof.bn_sig assert new_proof.metadata is None
def test_m_of_n(N, M, alices_keys, bobs_keys): priv_key_alice, pub_key_alice = alices_keys priv_key_bob, pub_key_bob = bobs_keys sym_key, capsule = pre._encapsulate(pub_key_alice.point_key) kfrags = pre.split_rekey(priv_key_alice, pub_key_bob, M, N) for kfrag in kfrags: assert kfrag.verify(pub_key_alice.point_key, pub_key_bob.point_key) for kfrag in kfrags[:M]: cfrag = pre.reencrypt(kfrag, capsule) capsule.attach_cfrag(cfrag) ch = pre.challenge(kfrag, capsule, cfrag) assert pre.check_challenge(capsule, cfrag, ch, pub_key_alice.point_key, pub_key_bob.point_key) # assert capsule.is_openable_by_bob() # TODO: Is it possible to check here if >= m cFrags have been attached? # capsule.open(pub_bob, priv_bob, pub_alice) capsule._reconstruct_shamirs_secret() sym_key_from_capsule = pre.decapsulate_reencrypted(pub_key_bob.point_key, priv_key_bob.bn_key, pub_key_alice.point_key, capsule) assert sym_key == sym_key_from_capsule
def test_simple_api(N, M, curve=default_curve()): """Manually injects umbralparameters for multi-curve testing.""" params = UmbralParameters(curve=curve) delegating_privkey = UmbralPrivateKey.gen_key(params=params) delegating_pubkey = delegating_privkey.get_pubkey() signing_privkey = UmbralPrivateKey.gen_key(params=params) signing_pubkey = signing_privkey.get_pubkey() signer = Signer(signing_privkey) receiving_privkey = UmbralPrivateKey.gen_key(params=params) receiving_pubkey = receiving_privkey.get_pubkey() plain_data = b'peace at dawn' ciphertext, capsule = pre.encrypt(delegating_pubkey, plain_data) cleartext = pre.decrypt(ciphertext, capsule, delegating_privkey) assert cleartext == plain_data capsule.set_correctness_keys(delegating=delegating_pubkey, receiving=receiving_pubkey, verifying=signing_pubkey) kfrags = pre.split_rekey(delegating_privkey, signer, receiving_pubkey, M, N) for kfrag in kfrags: cfrag = pre.reencrypt(kfrag, capsule) capsule.attach_cfrag(cfrag) reenc_cleartext = pre.decrypt(ciphertext, capsule, receiving_privkey) assert reenc_cleartext == plain_data
def test_activated_capsule_serialization(): priv_key = pre.gen_priv() pub_key = pre.priv2pub(priv_key) _unused_key, capsule = pre._encapsulate(pub_key) kfrags = pre.split_rekey(priv_key, pub_key, 1, 2) cfrag = pre.reencrypt(kfrags[0], capsule) capsule.attach_cfrag(cfrag) capsule._reconstruct_shamirs_secret() rec_capsule_bytes = capsule.to_bytes() # An activated Capsule is: # three points, representable as 33 bytes each (the original), and # two points and a bignum (32 bytes) (the activated components), for 197 total. assert len(rec_capsule_bytes) == (33 * 3) + (33 + 33 + 32) new_rec_capsule = pre.Capsule.from_bytes(rec_capsule_bytes) # Again, the same three perspectives on equality. assert new_rec_capsule == capsule assert new_rec_capsule.activated_components( ) == capsule.activated_components() assert new_rec_capsule._point_eph_e_prime == capsule._point_eph_e_prime assert new_rec_capsule._point_eph_v_prime == capsule._point_eph_v_prime assert new_rec_capsule._point_noninteractive == capsule._point_noninteractive
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 test_correctness_proof_serialization(prepared_capsule, kfrags): # Example of potential metadata to describe the re-encryption request metadata = b"This is an example of metadata for re-encryption request" for kfrag in kfrags: cfrag = pre.reencrypt(kfrag, prepared_capsule, metadata=metadata) proof = cfrag.proof proof_bytes = proof.to_bytes() # A CorrectnessProof can be represented as # the 228 total bytes of four Points (33 each) and three BigNums (32 each). # TODO: Figure out final size for CorrectnessProofs # assert len(proof_bytes) == (33 * 4) + (32 * 3) == 228 new_proof = CorrectnessProof.from_bytes(proof_bytes) assert new_proof.point_e2 == proof.point_e2 assert new_proof.point_v2 == proof.point_v2 assert new_proof.point_kfrag_commitment == proof.point_kfrag_commitment assert new_proof.point_kfrag_pok == proof.point_kfrag_pok assert new_proof.bn_sig == proof.bn_sig assert new_proof.kfrag_signature == proof.kfrag_signature assert new_proof.metadata == proof.metadata
def test_capsule_length(prepared_capsule, kfrags): capsule = prepared_capsule for counter, kfrag in enumerate(kfrags): assert len(capsule) == counter cfrag = pre.reencrypt(kfrag, capsule) capsule.attach_cfrag(cfrag)
def reencrypt(self, policy_id: str, capsule: pre.Capsule, M: int) -> List[fragments.CapsuleFrag]: """ Re-encrypts the given capsule 'M' number of times and returns a list of CapsuleFrags (CFrags) to be attached to the original Capsule. :param policy_id: Policy ID to access re-encryption. :param capsule: The Umbral capsule to re-encrypt. :param M: The number of times to re-encrypt the capsule for the minimum number of CFrags needed. :return: List of CFrags (CapsuleFrags). """ try: kfrags = self.db[policy_id] except KeyError: raise ValueError("No Policy found for {}".format(policy_id)) if M > len(kfrags): raise ValueError( "Not enough KFrags to re-encrypt {} times!".format(M)) cfrags = [] # TODO: using web3py check if is dead? data = requests.get("http://172.16.21.223:3000/api/platform/isAlive/") res = json.loads(data.text) if bool(res["result"]) == True: m_kfrags = random.sample(kfrags, M) for kfrag in m_kfrags: cfrags.append(pre.reencrypt(kfrag, capsule)) return cfrags
def test_cfrag_serialization_with_proof_and_metadata(prepared_capsule, kfrags): # Example of potential metadata to describe the re-encryption request metadata = b'This is an example of metadata for re-encryption request' for kfrag in kfrags: cfrag = pre.reencrypt(kfrag, prepared_capsule, provide_proof=True, metadata=metadata) cfrag_bytes = cfrag.to_bytes() proof = cfrag.proof assert proof is not None assert proof.metadata is not None new_cfrag = CapsuleFrag.from_bytes(cfrag_bytes) assert new_cfrag.point_e1 == cfrag.point_e1 assert new_cfrag.point_v1 == cfrag.point_v1 assert new_cfrag.kfrag_id == cfrag.kfrag_id assert new_cfrag.point_precursor == cfrag.point_precursor new_proof = new_cfrag.proof assert new_proof is not None assert new_proof.point_e2 == proof.point_e2 assert new_proof.point_v2 == proof.point_v2 assert new_proof.point_kfrag_commitment == proof.point_kfrag_commitment assert new_proof.point_kfrag_pok == proof.point_kfrag_pok assert new_proof.bn_sig == proof.bn_sig assert new_proof.metadata == metadata assert new_proof.metadata == proof.metadata
def reencrypt(self, policy_id: str, capsule: pre.Capsule, M: int) -> List[fragments.CapsuleFrag]: """ Re-encrypts the given capsule 'M' number of times and returns a list of CapsuleFrags (CFrags) to be attached to the original Capsule. :param policy_id: Policy ID to access re-encryption. :param capsule: The Umbral capsule to re-encrypt. :param M: The number of times to re-encrypt the capsule for the minimum number of CFrags needed. :return: List of CFrags (CapsuleFrags). """ try: kfrags = self.db[policy_id] except KeyError: raise ValueError("No Policy found for {}".format(policy_id)) if M > len(kfrags): raise ValueError( "Not enough KFrags to re-encrypt {} times!".format(M)) cfrags = [] m_kfrags = random.sample(kfrags, M) for kfrag in m_kfrags: cfrags.append(pre.reencrypt(kfrag, capsule)) return cfrags
def test_decryption_fails_when_it_expects_a_proof_and_there_isnt(N, M, alices_keys, bobs_keys): """Manually injects umbralparameters for multi-curve testing.""" delegating_privkey, signing_privkey = alices_keys delegating_pubkey = delegating_privkey.get_pubkey() signer = Signer(signing_privkey) priv_key_bob, pub_key_bob = bobs_keys plain_data = b'peace at dawn' ciphertext, capsule = pre.encrypt(delegating_privkey.get_pubkey(), plain_data) kfrags = pre.split_rekey(delegating_privkey, signer, pub_key_bob, M, N) capsule.set_correctness_keys(delegating=delegating_privkey.get_pubkey(), receiving=pub_key_bob, verifying=signing_privkey.get_pubkey()) for kfrag in kfrags[:M]: cfrag = pre.reencrypt(kfrag, capsule) capsule.attach_cfrag(cfrag) # Even thought we can successfully attach a CFrag, if the proof is lost # (for example, it is chopped off a serialized CFrag or similar), then decrypt # will still fail. cfrag.proof = None with pytest.raises(cfrag.NoProofProvided): _cleartext = pre.decrypt(ciphertext, capsule, priv_key_bob)
def test_challenge_response_serialization(): priv_key = pre.gen_priv() pub_key = pre.priv2pub(priv_key) _unused_key, capsule = pre._encapsulate(pub_key) kfrags = pre.split_rekey(priv_key, pub_key, 1, 2) cfrag = pre.reencrypt(kfrags[0], capsule) capsule.attach_cfrag(cfrag) ch_resp = pre.challenge(kfrags[0], capsule, cfrag) ch_resp_bytes = ch_resp.to_bytes() # A ChallengeResponse can be represented as # the 228 total bytes of four Points (33 each) and three BigNums (32 each). assert len(ch_resp_bytes) == (33 * 4) + (32 * 3) == 228 new_ch_resp = pre.ChallengeResponse.from_bytes(ch_resp_bytes) assert new_ch_resp.point_eph_e2 == ch_resp.point_eph_e2 assert new_ch_resp.point_eph_v2 == ch_resp.point_eph_v2 assert new_ch_resp.point_kfrag_commitment == ch_resp.point_kfrag_commitment assert new_ch_resp.point_kfrag_pok == ch_resp.point_kfrag_pok assert new_ch_resp.bn_kfrag_sig1 == ch_resp.bn_kfrag_sig1 assert new_ch_resp.bn_kfrag_sig2 == ch_resp.bn_kfrag_sig2 assert new_ch_resp.bn_sig == ch_resp.bn_sig
def test_correctness_proof_serialization(alices_keys): delegating_privkey, signing_privkey = alices_keys delegating_pubkey = delegating_privkey.get_pubkey() signer = Signer(signing_privkey) priv_key_bob = keys.UmbralPrivateKey.gen_key() pub_key_bob = priv_key_bob.get_pubkey() params = delegating_privkey.params _unused_key, capsule = pre._encapsulate(delegating_pubkey) kfrags = pre.split_rekey(delegating_privkey, signer, pub_key_bob, 1, 2) # Example of potential metadata to describe the re-encryption request metadata = b"This is an example of metadata for re-encryption request" cfrag = pre.reencrypt(kfrags[0], capsule, metadata=metadata) proof = cfrag.proof proof_bytes = proof.to_bytes() # A CorrectnessProof can be represented as # the 228 total bytes of four Points (33 each) and three BigNums (32 each). # TODO: Figure out final size for CorrectnessProofs # assert len(proof_bytes) == (33 * 4) + (32 * 3) == 228 new_proof = CorrectnessProof.from_bytes(proof_bytes) assert new_proof._point_e2 == proof._point_e2 assert new_proof._point_v2 == proof._point_v2 assert new_proof._point_kfrag_commitment == proof._point_kfrag_commitment assert new_proof._point_kfrag_pok == proof._point_kfrag_pok assert new_proof.bn_sig == proof.bn_sig assert new_proof.kfrag_signature == proof.kfrag_signature assert new_proof.metadata == proof.metadata
def test_cfrag_serialization_no_proof_no_metadata(alices_keys, bobs_keys): delegating_privkey, signing_privkey = alices_keys delegating_pubkey = delegating_privkey.get_pubkey() _receiving_privkey, receiving_pubkey = bobs_keys signer_alice = Signer(signing_privkey) _unused_key, capsule = pre._encapsulate(delegating_pubkey.point_key) kfrags = pre.split_rekey(delegating_privkey, signer_alice, receiving_pubkey, 1, 2) cfrag = pre.reencrypt(kfrags[0], capsule, provide_proof=False) cfrag_bytes = cfrag.to_bytes() proof = cfrag.proof assert proof is None curve = default_curve() assert len(cfrag_bytes) == CapsuleFrag.expected_bytes_length(curve) new_cfrag = pre.CapsuleFrag.from_bytes(cfrag_bytes) assert new_cfrag._point_e1 == cfrag._point_e1 assert new_cfrag._point_v1 == cfrag._point_v1 assert new_cfrag._kfrag_id == cfrag._kfrag_id assert new_cfrag._point_noninteractive == cfrag._point_noninteractive new_proof = new_cfrag.proof assert new_proof is None