def test_open_reencrypted(alices_keys, bobs_keys): threshold = 6 shares = 10 delegating_sk, signing_sk = alices_keys receiving_sk, receiving_pk = bobs_keys signer = Signer(signing_sk) delegating_pk = delegating_sk.public_key() capsule, key = Capsule.from_public_key(delegating_pk) kfrags = generate_kfrags(delegating_sk=delegating_sk, signer=signer, receiving_pk=receiving_pk, threshold=threshold, shares=shares) cfrags = [reencrypt(capsule, kfrag).cfrag for kfrag in kfrags] key_back = capsule.open_reencrypted(receiving_sk, delegating_pk, cfrags[:threshold]) assert key_back == key # No cfrags at all with pytest.raises(ValueError, match="Empty CapsuleFrag sequence"): capsule.open_reencrypted(receiving_sk, delegating_pk, []) # Not enough cfrags with pytest.raises(ValueError, match="Internal validation failed"): capsule.open_reencrypted(receiving_sk, delegating_pk, cfrags[:threshold - 1]) # Repeating cfrags with pytest.raises(ValueError, match="Some of the CapsuleFrags are repeated"): capsule.open_reencrypted(receiving_sk, delegating_pk, [cfrags[0]] + cfrags[:threshold - 1]) # Mismatched cfrags kfrags2 = generate_kfrags(delegating_sk=delegating_sk, signer=signer, receiving_pk=receiving_pk, threshold=threshold, shares=shares) cfrags2 = [reencrypt(capsule, kfrag).cfrag for kfrag in kfrags2] with pytest.raises(ValueError, match="CapsuleFrags are not pairwise consistent"): capsule.open_reencrypted(receiving_sk, delegating_pk, [cfrags2[0]] + cfrags[:threshold - 1])
def test_cfrag_str(capsule, kfrags): cfrag0 = reencrypt(capsule, kfrags[0]) s = str(cfrag0) assert 'VerifiedCapsuleFrag' in s s = str(CapsuleFrag.from_bytes(bytes(cfrag0))) assert "VerifiedCapsuleFrag" not in s assert "CapsuleFrag" in s
def test_cfrag_is_hashable(verification_keys, capsule, kfrags): verifying_pk, delegating_pk, receiving_pk = verification_keys cfrag0 = reencrypt(capsule, kfrags[0]) cfrag1 = reencrypt(capsule, kfrags[1]) assert hash(cfrag0) != hash(cfrag1) new_cfrag = CapsuleFrag.from_bytes(bytes(cfrag0)) assert hash(new_cfrag) != hash(cfrag0) verified_cfrag = new_cfrag.verify(capsule, verifying_pk=verifying_pk, delegating_pk=delegating_pk, receiving_pk=receiving_pk, ) assert hash(verified_cfrag) == hash(cfrag0)
def test_simple_api(num_kfrags, threshold): """ This test models the main interactions between actors (i.e., Alice, Bob, Data Source, and Ursulas) and artifacts (i.e., public and private keys, ciphertexts, capsules, KFrags, CFrags, etc). The test covers all the main stages of data sharing: key generation, delegation, encryption, decryption by Alice, re-encryption by Ursula, and decryption by Bob. """ # Key Generation (Alice) delegating_sk = SecretKey.random() delegating_pk = delegating_sk.public_key() signing_sk = SecretKey.random() signer = Signer(signing_sk) verifying_pk = signing_sk.public_key() # Key Generation (Bob) receiving_sk = SecretKey.random() receiving_pk = receiving_sk.public_key() # Encryption by an unnamed data source plaintext = b'peace at dawn' capsule, ciphertext = encrypt(delegating_pk, plaintext) # Decryption by Alice plaintext_decrypted = decrypt_original(delegating_sk, capsule, ciphertext) assert plaintext_decrypted == plaintext # Split Re-Encryption Key Generation (aka Delegation) kfrags = generate_kfrags(delegating_sk=delegating_sk, receiving_pk=receiving_pk, signer=signer, threshold=threshold, num_kfrags=num_kfrags) # Bob requests re-encryption to some set of M ursulas cfrags = [reencrypt(capsule, kfrag) for kfrag in kfrags] # Decryption by Bob plaintext_reenc = decrypt_reencrypted( receiving_sk=receiving_sk, delegating_pk=delegating_pk, capsule=capsule, verified_cfrags=cfrags[:threshold], ciphertext=ciphertext, ) assert plaintext_reenc == plaintext
def test_decrypt_unverified_cfrag(verification_keys, bobs_keys, capsule_and_ciphertext, kfrags): verifying_pk, delegating_pk, receiving_pk = verification_keys receiving_sk, _receiving_pk = bobs_keys capsule, ciphertext = capsule_and_ciphertext cfrags = [reencrypt(capsule, kfrag) for kfrag in kfrags] cfrags[0] = CapsuleFrag.from_bytes(bytes(cfrags[0])) with pytest.raises(TypeError): plaintext_reenc = decrypt_reencrypted( receiving_sk=receiving_sk, delegating_pk=delegating_pk, capsule=capsule, verified_cfrags=cfrags, ciphertext=ciphertext, )
def test_cfrag_with_wrong_capsule(verification_keys, kfrags, capsule_and_ciphertext, message): capsule, ciphertext = capsule_and_ciphertext verifying_pk, delegating_pk, receiving_pk = verification_keys capsule_alice1 = capsule capsule_alice2, _unused_key2 = Capsule.from_public_key(delegating_pk) cfrag = reencrypt(capsule_alice2, kfrags[0]) cfrag = CapsuleFrag.from_bytes(bytes(cfrag)) # de-verify with pytest.raises(VerificationError): cfrag.verify(capsule_alice1, verifying_pk=verifying_pk, delegating_pk=delegating_pk, receiving_pk=receiving_pk, )
def test_cfrag_with_wrong_data(verification_keys, kfrags, capsule_and_ciphertext, message): capsule, ciphertext = capsule_and_ciphertext verifying_pk, delegating_pk, receiving_pk = verification_keys cfrag = reencrypt(capsule, kfrags[0]) # Let's put random garbage in one of the cfrags cfrag = CapsuleFrag.from_bytes(bytes(cfrag)) # de-verify cfrag.point_e1 = CurvePoint.random() cfrag.point_v1 = CurvePoint.random() with pytest.raises(VerificationError): cfrag.verify(capsule, verifying_pk=verifying_pk, delegating_pk=delegating_pk, receiving_pk=receiving_pk, )
def test_cfrag_serialization(verification_keys, capsule, kfrags): verifying_pk, delegating_pk, receiving_pk = verification_keys for kfrag in kfrags: cfrag = reencrypt(capsule, kfrag) cfrag_bytes = bytes(cfrag) new_cfrag = CapsuleFrag.from_bytes(cfrag_bytes) verified_cfrag = new_cfrag.verify(capsule, verifying_pk=verifying_pk, delegating_pk=delegating_pk, receiving_pk=receiving_pk, ) assert verified_cfrag == cfrag # Wrong delegating key with pytest.raises(VerificationError): new_cfrag.verify(capsule, verifying_pk=verifying_pk, delegating_pk=receiving_pk, receiving_pk=receiving_pk, ) # Wrong receiving key with pytest.raises(VerificationError): new_cfrag.verify(capsule, verifying_pk=verifying_pk, delegating_pk=delegating_pk, receiving_pk=delegating_pk, ) # Wrong signing key with pytest.raises(VerificationError): new_cfrag.verify(capsule, verifying_pk=receiving_pk, delegating_pk=delegating_pk, receiving_pk=receiving_pk, )
def firehose(m: int = 6, n: int = 10) -> None: print("Making kfrags...") kfrags, capsule = __produce_kfrags_and_capsule(m=m, n=n) one_kfrag, *remaining_kfrags = kfrags print('Re-encrypting...') successful_reencryptions = 0 for iteration in range(int(REENCRYPTIONS)): _cfrag = umbral.reencrypt(capsule, one_kfrag) # <<< REENCRYPTION HAPPENS HERE successful_reencryptions += 1 if iteration % 20 == 0: print('Performed {} Re-encryptions...'.format(iteration)) failure_message = "A Reencryption failed. {} of {} succeeded".format( successful_reencryptions, REENCRYPTIONS) assert successful_reencryptions == REENCRYPTIONS, failure_message print("Successfully performed {} reencryptions".format( successful_reencryptions), end='\n')
def test_serialized_size(capsule, kfrags): verified_cfrag = reencrypt(capsule, kfrags[0]) cfrag = CapsuleFrag.from_bytes(bytes(verified_cfrag)) assert verified_cfrag.serialized_size() == cfrag.serialized_size()
# ------------------------------ # Bob asks several Ursulas to re-encrypt the capsule so he can open it. # Each Ursula performs re-encryption on the capsule using the `kfrag` # provided by Alice, obtaining this way a "capsule fragment", or `cfrag`. # Let's mock a network or transport layer by sampling `threshold` random `kfrags`, # one for each required Ursula. kfrags = random.sample(kfrags, # All kfrags from above 10) # M - Threshold # Bob collects the resulting `cfrags` from several Ursulas. # Bob must gather at least `threshold` `cfrags` in order to open the capsule. cfrags = list() # Bob's cfrag collection for kfrag in kfrags: cfrag = reencrypt(capsule=capsule, kfrag=kfrag) cfrags.append(cfrag) # Bob collects a cfrag assert len(cfrags) == 10 # Bob checks the capsule fragments # -------------------------------- # If Bob received the capsule fragments in serialized form, # he can verify that they are valid and really originate from Alice, # using Alice's public keys. suspicious_cfrags = [CapsuleFrag.from_bytes(bytes(cfrag)) for cfrag in cfrags] cfrags = [cfrag.verify(capsule, verifying_pk=alices_verifying_key, delegating_pk=alices_public_key,
verifying_pk = signing_sk.public_key() delegating_pk = delegating_sk.public_key() receiving_pk = receiving_sk.public_key() kfrags = generate_kfrags(delegating_sk=delegating_sk, receiving_pk=receiving_pk, signer=Signer(signing_sk), threshold=6, shares=10, ) plain_data = b'peace at dawn' capsule, ciphertext = encrypt(delegating_pk, plain_data) cfrag = CapsuleFrag.from_bytes(bytes(reencrypt(capsule, kfrags[0]))) points = [capsule.point_e, cfrag.point_e1, cfrag.proof.point_e2, capsule.point_v, cfrag.point_v1, cfrag.proof.point_v2, cfrag.proof.kfrag_commitment, cfrag.proof.kfrag_pok] z = cfrag.proof.signature ########################### # CurveScalar arithmetics # ########################### # Let's generate two random CurveScalars bn1 = CurveScalar.random_nonzero() bn2 = CurveScalar.random_nonzero()
def test_reencrypt_unverified_kfrag(capsule, kfrags): kfrag = KeyFrag.from_bytes(bytes(kfrags[0])) with pytest.raises(TypeError): reencrypt(capsule, kfrag)
def test_from_verified_bytes(capsule, kfrags): verified_cfrag = reencrypt(capsule, kfrags[0]) cfrag_bytes = bytes(verified_cfrag) verified_cfrag_back = VerifiedCapsuleFrag.from_verified_bytes(cfrag_bytes) assert verified_cfrag == verified_cfrag_back