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_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_cfrag_serialization_with_proof_but_no_metadata(alices_keys): priv_key_alice, pub_key_alice = alices_keys _unused_key, capsule = pre._encapsulate(pub_key_alice.point_key) kfrags = pre.split_rekey(priv_key_alice, pub_key_alice, 1, 2) cfrag = pre.reencrypt(kfrags[0], 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 = 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._bn_kfrag_id == cfrag._bn_kfrag_id assert new_cfrag._point_noninteractive == cfrag._point_noninteractive 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_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 is None
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_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_capsule_serialization(alices_keys): priv_key_alice, pub_key_alice = alices_keys _symmetric_key, capsule = pre._encapsulate(pub_key_alice.point_key) capsule_bytes = capsule.to_bytes() capsule_bytes_casted = bytes(capsule) assert capsule_bytes == capsule_bytes_casted # A Capsule can be represented as the 98 total bytes of two Points (33 each) and a BigNum (32). assert len(capsule_bytes) == 33 + 33 + 32 == 98 new_capsule = pre.Capsule.from_bytes(capsule_bytes) # Three ways to think about equality. # First, the public approach for the Capsule. Simply: assert new_capsule == capsule # Second, we show that the original components (which is all we have here since we haven't activated) are the same: assert new_capsule.original_components() == capsule.original_components() # Third, we can directly compare the private original component attributes # (though this is not a supported approach): assert new_capsule._point_eph_e == capsule._point_eph_e assert new_capsule._point_eph_v == capsule._point_eph_v assert new_capsule._bn_sig == capsule._bn_sig
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(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_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, challenges, metadata = [], [], [] for i, kfrag in enumerate(kfrags[:M]): cfrag = pre.reencrypt(kfrag, capsule_alice) # Example of potential metadata to describe the challenge request metadata_i = { 'ursula_id': i, 'timestamp': time.time(), 'capsule': bytes(capsule_alice), 'cfrag': bytes(cfrag) } metadata_i = str(metadata_i).encode() metadata.append(metadata_i) challenge = pre._challenge(kfrag, capsule_alice, cfrag, metadata_i) capsule_alice.attach_cfrag(cfrag) assert pre._check_challenge(capsule_alice, cfrag, challenge, pub_key_alice.point_key, pub_key_bob.point_key, metadata_i) cfrags.append(cfrag) challenges.append(challenge) # Let's put random garbage in one of the cfrags cfrags[0].point_eph_e1 = Point.gen_rand() cfrags[0].point_eph_v1 = Point.gen_rand() capsule_alice._reconstruct_shamirs_secret(pub_key_alice, priv_key_bob) # activate capsule with pytest.raises(pre.GenericUmbralError): sym_key2 = pre._decapsulate_reencrypted(pub_key_bob.point_key, priv_key_bob.bn_key, pub_key_alice.point_key, capsule_alice) assert not pre._check_challenge(capsule_alice, 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 chould be correct: for i, challenge in enumerate(challenges[1:], 1): cfrag = cfrags[i] assert pre._check_challenge(capsule_alice, cfrag, challenge, pub_key_alice.point_key, pub_key_bob.point_key, metadata[i])
def test_capsule_serialization(alices_keys): delegating_privkey, _signing_privkey = alices_keys params = delegating_privkey.params _symmetric_key, capsule = pre._encapsulate(delegating_privkey.get_pubkey()) capsule_bytes = capsule.to_bytes() capsule_bytes_casted = bytes(capsule) assert capsule_bytes == capsule_bytes_casted # A Capsule can be represented as the 98 total bytes of two Points (33 each) and a CurveBN (32). assert len(capsule_bytes) == pre.Capsule.expected_bytes_length() new_capsule = pre.Capsule.from_bytes(capsule_bytes, params) # Three ways to think about equality. # First, the public approach for the Capsule. Simply: assert new_capsule == capsule # Second, we show that the original components (which is all we have here since we haven't activated) are the same: assert new_capsule.original_components() == capsule.original_components() # Third, we can directly compare the private original component attributes # (though this is not a supported approach): assert new_capsule._point_e == capsule._point_e assert new_capsule._point_v == capsule._point_v assert new_capsule._bn_sig == capsule._bn_sig
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_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 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_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_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
def test_decapsulation_by_alice(alices_keys): alice_priv, alice_pub = alices_keys sym_key, capsule = pre._encapsulate(alice_pub.point_key) assert len(sym_key) == 32 # The symmetric key sym_key is perhaps used for block cipher here in a real-world scenario. sym_key_2 = pre._decapsulate_original(alice_priv.bn_key, capsule) assert sym_key_2 == sym_key
def prepared_capsule(alices_keys, bobs_keys): delegating_privkey, signing_privkey = alices_keys _receiving_privkey, receiving_pubkey = bobs_keys _sym_key, capsule = pre._encapsulate(delegating_privkey.get_pubkey()) capsule.set_correctness_keys(delegating=delegating_privkey.get_pubkey(), receiving=receiving_pubkey, verifying=signing_privkey.get_pubkey()) return capsule
def test_decapsulation_by_alice(alices_keys): delegating_privkey, _signing_privkey = alices_keys sym_key, capsule = pre._encapsulate( delegating_privkey.get_pubkey().point_key) assert len(sym_key) == 32 # The symmetric key sym_key is perhaps used for block cipher here in a real-world scenario. sym_key_2 = pre._decapsulate_original(delegating_privkey.bn_key, capsule) assert sym_key_2 == sym_key
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) k_frags = pre.split_rekey(priv_key_alice, pub_key_bob, M, N) c_frags, challenges = [], [] for k_frag in k_frags[0:M]: c_frag = pre.reencrypt(k_frag, capsule_alice) challenge = pre.challenge(k_frag, capsule_alice, c_frag) capsule_alice.attach_cfrag(c_frag) assert pre.check_challenge( capsule_alice, c_frag, challenge, pub_key_alice.point_key, pub_key_bob.point_key, ) c_frags.append(c_frag) challenges.append(challenge) # Let's put random garbage in one of the c_frags c_frags[0].point_eph_e1 = Point.gen_rand() c_frags[0].point_eph_v1 = Point.gen_rand() capsule_alice._reconstruct_shamirs_secret() # activate capsule with pytest.raises(pre.GenericUmbralError): sym_key2 = pre.decapsulate_reencrypted(pub_key_bob.point_key, priv_key_bob.bn_key, pub_key_alice.point_key, capsule_alice) assert sym_key2 != sym_key assert not pre.check_challenge(capsule_alice, 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_alice, 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 fragments(metadata): delegating_privkey = UmbralPrivateKey.gen_key() _symmetric_key, capsule = pre._encapsulate(delegating_privkey.get_pubkey()) signing_privkey = UmbralPrivateKey.gen_key() 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_privkey.get_pubkey()) cfrag = pre.reencrypt(kfrags[0], capsule, metadata=metadata) return capsule, cfrag
def test_cfrag_serialization(alices_keys): priv_key_alice, pub_key_alice = alices_keys _unused_key, capsule = pre._encapsulate(pub_key_alice.point_key) k_frags = pre.split_rekey(priv_key_alice, pub_key_alice, 1, 2) c_frag = pre.reencrypt(k_frags[0], capsule) c_frag_bytes = c_frag.to_bytes() # A CFrag can be represented as the 131 total bytes of three Points (33 each) and a BigNum (32). assert len(c_frag_bytes) == 33 + 33 + 33 + 32 == 131 new_cfrag = pre.CapsuleFrag.from_bytes(c_frag_bytes) assert new_cfrag.point_eph_e1 == c_frag.point_eph_e1 assert new_cfrag.point_eph_v1 == c_frag.point_eph_v1 assert new_cfrag.bn_kfrag_id == c_frag.bn_kfrag_id assert new_cfrag.point_eph_ni == c_frag.point_eph_ni
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 test_cfrag_serialization_with_proof_and_metadata(alices_keys): priv_key_alice, pub_key_alice = alices_keys _unused_key, capsule = pre._encapsulate(pub_key_alice.point_key) kfrags = pre.split_rekey(priv_key_alice, pub_key_alice, 1, 2) # Example of potential metadata to describe the re-encryption request metadata = { 'ursula_id': 42, 'timestamp': time.time(), 'capsule': bytes(capsule), } metadata = str(metadata).encode() cfrag = pre.reencrypt(kfrags[0], 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 # 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 = 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._bn_kfrag_id == cfrag._bn_kfrag_id assert new_cfrag._point_noninteractive == cfrag._point_noninteractive 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_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 == metadata assert new_proof.metadata == proof.metadata
def test_capsule_length(alices_keys, bobs_keys): delegating_privkey, signing_privkey = alices_keys signer = Signer(signing_privkey) priv_key_bob, pub_key_bob = bobs_keys sym_key, capsule = pre._encapsulate(delegating_privkey.get_pubkey()) kfrags = pre.split_rekey(delegating_privkey, signer, pub_key_bob, 10, 15) capsule.set_correctness_keys(delegating=delegating_privkey.get_pubkey(), receiving=pub_key_bob, verifying=signing_privkey.get_pubkey()) for counter, kfrag in enumerate(kfrags): assert len(capsule) == counter cfrag = pre.reencrypt(kfrag, capsule) capsule.attach_cfrag(cfrag)
def test_challenge_response_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) cfrag = pre.reencrypt(kfrags[0], capsule) capsule.attach_cfrag(cfrag) # Example of potential metadata to describe the challenge request challenge_metadata = { 'ursula_id': 0, 'timestamp': time.time(), 'capsule': bytes(capsule), 'cfrag': bytes(cfrag) } challenge_metadata = str(challenge_metadata).encode() ch_resp = pre._challenge(kfrags[0], capsule, cfrag, challenge_metadata) 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_activated_capsule_serialization(alices_keys, bobs_keys): delegating_privkey, signing_privkey = alices_keys delegating_pubkey = delegating_privkey.get_pubkey() signer_alice = Signer(signing_privkey) params = delegating_privkey.params receiving_privkey, receiving_pubkey = bobs_keys _unused_key, capsule = pre._encapsulate(delegating_pubkey) kfrags = pre.split_rekey(delegating_privkey, signer_alice, receiving_pubkey, 1, 2) cfrag = pre.reencrypt(kfrags[0], capsule) capsule.set_correctness_keys(delegating=delegating_pubkey, receiving=receiving_pubkey, verifying=signing_privkey.get_pubkey()) capsule.attach_cfrag(cfrag) capsule._reconstruct_shamirs_secret(receiving_privkey) rec_capsule_bytes = capsule.to_bytes() assert len(rec_capsule_bytes) == pre.Capsule.expected_bytes_length( activated=True) new_rec_capsule = pre.Capsule.from_bytes(rec_capsule_bytes, params) # 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_e_prime == capsule._point_e_prime assert new_rec_capsule._point_v_prime == capsule._point_v_prime assert new_rec_capsule._point_noninteractive == capsule._point_noninteractive
def test_cfrag_serialization_with_proof_and_metadata(alices_keys, bobs_keys): delegating_privkey, signing_privkey = alices_keys delegating_pubkey = delegating_privkey.get_pubkey() signer_alice = Signer(signing_privkey) _receiving_privkey, receiving_pubkey = bobs_keys _unused_key, capsule = pre._encapsulate(delegating_pubkey.point_key) kfrags = pre.split_rekey(delegating_privkey, signer_alice, receiving_pubkey, 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, 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 = 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 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