Skip to content

Commit

Permalink
Simplified public API for umbral.pre
Browse files Browse the repository at this point in the history
* Functions in `pre` now only take Umbral keys as arguments, rather than primitive types (Point, CurveBN)
* Remove unnecessary arguments from public facing and internal methods when they can be extracted from a Capsule, UmbralPublicKey or UmbralPrivateKey
* Adds a getter in Capsule for correctness keys
* Adapts the test suite to new simplified API
  • Loading branch information
cygnusv committed Jun 4, 2018
1 parent 015fae6 commit 09832ec
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 125 deletions.
7 changes: 3 additions & 4 deletions tests/test_capsule/test_capsule_operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@ def test_decapsulation_by_alice(alices_keys):

delegating_privkey, _signing_privkey = alices_keys

sym_key, capsule = pre._encapsulate(delegating_privkey.get_pubkey().point_key, params)
sym_key, capsule = pre._encapsulate(delegating_privkey.get_pubkey())
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)
sym_key_2 = pre._decapsulate_original(delegating_privkey, capsule)
assert sym_key_2 == sym_key


Expand Down Expand Up @@ -115,8 +115,7 @@ def test_capsule_as_dict_key(alices_keys, bobs_keys):
capsule.attach_cfrag(cfrag)

# Even if we activate the capsule, it still serves as the same key.
cleartext = pre.decrypt(ciphertext, capsule, receiving_privkey,
delegating_pubkey, signing_pubkey)
cleartext = pre.decrypt(ciphertext, capsule, receiving_privkey)
assert some_dict[capsule] == "Thing that Bob wants to try per-Capsule"
assert cleartext == plain_data

Expand Down
13 changes: 7 additions & 6 deletions tests/test_capsule/test_capsule_serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ 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().point_key, 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
Expand Down Expand Up @@ -44,16 +44,17 @@ def test_activated_capsule_serialization(alices_keys, bobs_keys):

receiving_privkey, receiving_pubkey = bobs_keys

_unused_key, capsule = pre._encapsulate(delegating_pubkey.point_key, params)

capsule.set_correctness_keys(delegating=delegating_pubkey,
receiving=receiving_pubkey,
verifying=signing_privkey.get_pubkey())
_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)
Expand Down
88 changes: 29 additions & 59 deletions tests/test_correctness.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def test_correctness_proof_serialization(alices_keys):

params = delegating_privkey.params

_unused_key, capsule = pre._encapsulate(delegating_pubkey.point_key, 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
Expand Down Expand Up @@ -53,15 +53,15 @@ def test_cheating_ursula_replays_old_reencryption(N, M, alices_keys):

params = delegating_privkey.params

_unused_key1, capsule_alice1 = pre._encapsulate(delegating_pubkey.point_key, params)
_unused_key2, capsule_alice2 = pre._encapsulate(delegating_pubkey.point_key, params)
_unused_key1, capsule_alice1 = pre._encapsulate(delegating_pubkey)
_unused_key2, capsule_alice2 = pre._encapsulate(delegating_pubkey)

kfrags = pre.split_rekey(delegating_privkey, signer, pub_key_bob, M, N)

capsule_alice1.set_correctness_keys(delegating=delegating_pubkey,
receiving=pub_key_bob,
verifying=signing_privkey.get_pubkey())

kfrags = pre.split_rekey(delegating_privkey, signer, pub_key_bob, M, N)

cfrags, metadata = [], []
for i, kfrag in enumerate(kfrags[:M]):

Expand All @@ -76,34 +76,25 @@ def test_cheating_ursula_replays_old_reencryption(N, M, alices_keys):
else:
cfrag = pre.reencrypt(kfrag, capsule_alice1, metadata=metadata_i)

capsule_alice1.attach_cfrag(cfrag)
# Next, we bypass the public method to attach CFrags to the capsule,
# -- called Capsule.append(cfrag) -- and insert it directly in the private
# list of CFrags. In case you were wondering...DON'T DO THIS!
capsule_alice1._attached_cfrags.append(cfrag)
cfrags.append(cfrag)

# Let's activate the capsule
capsule_alice1._reconstruct_shamirs_secret(priv_key_bob)

with pytest.raises(pre.GenericUmbralError):
sym_key = pre._decapsulate_reencrypted(pub_key_bob.point_key,
priv_key_bob.bn_key,
delegating_pubkey.point_key,
capsule_alice1
)

assert not cfrags[0].verify_correctness(capsule_alice1,
delegating_pubkey,
signing_privkey.get_pubkey(),
pub_key_bob,
)
sym_key = pre._decapsulate_reencrypted(priv_key_bob, capsule_alice1)

assert not cfrags[0].verify_correctness(capsule_alice1)

# The response of cheating Ursula is in cfrags[0],
# so the rest of CFrags should be correct:
correct_cases = 0
for cfrag_i, metadata_i in zip(cfrags[1:], metadata[1:]):
if cfrag_i.verify_correctness(capsule_alice1,
delegating_pubkey,
signing_privkey.get_pubkey(),
pub_key_bob,
):
if cfrag_i.verify_correctness(capsule_alice1):
correct_cases += 1
else:
pytest.fail("One of the cfrags that was supposed to be correct wasn't.")
Expand All @@ -112,11 +103,7 @@ def test_cheating_ursula_replays_old_reencryption(N, M, alices_keys):
# 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,
delegating_pubkey,
signing_privkey.get_pubkey(),
)
_ = pre._open_capsule(capsule_alice1, priv_key_bob)
correctness_error = exception_info.value
assert cfrags[0] in correctness_error.offending_cfrags
assert len(correctness_error.offending_cfrags) == 1
Expand All @@ -133,14 +120,14 @@ def test_cheating_ursula_sends_garbage(N, M, alices_keys):

params = delegating_privkey.params

sym_key, capsule_alice = pre._encapsulate(delegating_pubkey.point_key, params)
sym_key, capsule_alice = pre._encapsulate(delegating_pubkey)

kfrags = pre.split_rekey(delegating_privkey, signer, pub_key_bob, M, N)

capsule_alice.set_correctness_keys(delegating=delegating_pubkey,
receiving=pub_key_bob,
verifying=signing_privkey.get_pubkey())

kfrags = pre.split_rekey(delegating_privkey, signer, pub_key_bob, M, N)

cfrags, metadata = [], []
for i, kfrag in enumerate(kfrags[:M]):
# Example of potential metadata to describe the re-encryption request
Expand All @@ -159,32 +146,20 @@ def test_cheating_ursula_sends_garbage(N, M, alices_keys):
capsule_alice._reconstruct_shamirs_secret(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,
delegating_pubkey.point_key,
capsule_alice)
_unused_key = pre._decapsulate_reencrypted(priv_key_bob, capsule_alice)

assert not cfrags[0].verify_correctness(capsule_alice,
delegating_pubkey,
signing_privkey.get_pubkey(),
pub_key_bob,
)
assert not cfrags[0].verify_correctness(capsule_alice)

# 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 cfrag_i.verify_correctness(capsule_alice,
delegating_pubkey,
signing_privkey.get_pubkey(),
pub_key_bob,
)
assert cfrag_i.verify_correctness(capsule_alice)

# 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:
_decapsulated_key = pre._open_capsule(capsule_alice, priv_key_bob,
delegating_pubkey,
signing_privkey.get_pubkey())
_decapsulated_key = pre._open_capsule(capsule_alice, priv_key_bob)

correctness_error = exception_info.value
assert cfrags[0] in correctness_error.offending_cfrags
assert len(correctness_error.offending_cfrags) == 1
Expand All @@ -202,12 +177,12 @@ def test_decryption_fails_when_it_expects_a_proof_and_there_isnt(N, M, alices_ke
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())

kfrags = pre.split_rekey(delegating_privkey, signer, pub_key_bob, M, N)
for kfrag in kfrags:
for kfrag in kfrags[:M]:
cfrag = pre.reencrypt(kfrag, capsule)
capsule.attach_cfrag(cfrag)

Expand All @@ -217,9 +192,7 @@ def test_decryption_fails_when_it_expects_a_proof_and_there_isnt(N, M, alices_ke
cfrag.proof = None

with pytest.raises(cfrag.NoProofProvided):
_cleartext = pre.decrypt(ciphertext, capsule, priv_key_bob,
delegating_privkey.get_pubkey(),
signing_privkey.get_pubkey())
_cleartext = pre.decrypt(ciphertext, capsule, priv_key_bob)


@pytest.mark.parametrize("N, M", parameters)
Expand All @@ -232,7 +205,7 @@ def test_m_of_n(N, M, alices_keys, bobs_keys):

params = delegating_privkey.params

sym_key, capsule = pre._encapsulate(delegating_pubkey.point_key, params)
sym_key, capsule = pre._encapsulate(delegating_pubkey)

capsule.set_correctness_keys(delegating=delegating_privkey.get_pubkey(),
receiving=pub_key_bob,
Expand All @@ -251,10 +224,7 @@ def test_m_of_n(N, M, alices_keys, bobs_keys):
cfrag = pre.reencrypt(kfrag, capsule, metadata=metadata)
capsule.attach_cfrag(cfrag)

assert cfrag.verify_correctness(capsule, delegating_pubkey,
signing_privkey.get_pubkey(), pub_key_bob,
)
assert cfrag.verify_correctness(capsule)

sym_key_from_capsule = pre._open_capsule(capsule, priv_key_bob, delegating_pubkey,
signing_privkey.get_pubkey())
sym_key_from_capsule = pre._open_capsule(capsule, priv_key_bob)
assert sym_key == sym_key_from_capsule
6 changes: 3 additions & 3 deletions tests/test_keys/test_key_fragments.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def test_cfrag_serialization_with_proof_and_metadata(alices_keys, bobs_keys):
_receiving_privkey, receiving_pubkey = bobs_keys


_unused_key, capsule = pre._encapsulate(delegating_pubkey.point_key, delegating_pubkey.params)
_unused_key, capsule = pre._encapsulate(delegating_pubkey)
kfrags = pre.split_rekey(delegating_privkey, signer_alice,
receiving_pubkey, 1, 2)

Expand Down Expand Up @@ -70,7 +70,7 @@ def test_cfrag_serialization_with_proof_but_no_metadata(alices_keys, bobs_keys):
_receiving_privkey, receiving_pubkey = bobs_keys
signer_alice = Signer(signing_privkey)

_unused_key, capsule = pre._encapsulate(delegating_pubkey.point_key, delegating_pubkey.params)
_unused_key, capsule = pre._encapsulate(delegating_pubkey)
kfrags = pre.split_rekey(delegating_privkey, signer_alice,
receiving_pubkey, 1, 2)

Expand Down Expand Up @@ -108,7 +108,7 @@ def test_cfrag_serialization_no_proof_no_metadata(alices_keys, bobs_keys):
_receiving_privkey, receiving_pubkey = bobs_keys
signer_alice = Signer(signing_privkey)

_unused_key, capsule = pre._encapsulate(delegating_pubkey.point_key, delegating_pubkey.params)
_unused_key, capsule = pre._encapsulate(delegating_pubkey)
kfrags = pre.split_rekey(delegating_privkey, signer_alice,
receiving_pubkey, 1, 2)

Expand Down
6 changes: 2 additions & 4 deletions tests/test_simple_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@ def test_simple_api(N, M, curve=default_curve()):
cfrag = pre.reencrypt(kfrag, capsule)
capsule.attach_cfrag(cfrag)

reenc_cleartext = pre.decrypt(ciphertext, capsule, receiving_privkey,
delegating_pubkey, signing_pubkey)
reenc_cleartext = pre.decrypt(ciphertext, capsule, receiving_privkey)
assert reenc_cleartext == plain_data


Expand Down Expand Up @@ -164,8 +163,7 @@ def new_keypair_bytes():
cfrag = CapsuleFrag.from_bytes(cfrag_bytes, params.curve)
capsule.attach_cfrag(cfrag)

reenc_cleartext = pre.decrypt(ciphertext, capsule, receiving_privkey,
delegating_pubkey, signing_pubkey)
reenc_cleartext = pre.decrypt(ciphertext, capsule, receiving_privkey)
assert reenc_cleartext == plain_data


Expand Down
18 changes: 14 additions & 4 deletions umbral/_pre.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,20 @@ def prove_cfrag_correctness(cfrag: "CapsuleFrag",


def assess_cfrag_correctness(cfrag,
capsule: "Capsule",
delegating_point,
signing_pubkey,
receiving_point):
capsule: "Capsule"):

correctness_keys = capsule.get_correctness_keys()

delegating_pubkey = correctness_keys['delegating']
signing_pubkey = correctness_keys['verifying']
receiving_pubkey = correctness_keys['receiving']

if not all((delegating_pubkey, signing_pubkey, receiving_pubkey)):
raise TypeError("Need all three keys to verify correctness.")

delegating_point = delegating_pubkey.point_key
receiving_point = receiving_pubkey.point_key

params = capsule._umbral_params

####
Expand Down
15 changes: 2 additions & 13 deletions umbral/fragments.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,19 +222,8 @@ def to_bytes(self):

return serialized_cfrag

def verify_correctness(self,
capsule: "Capsule",
delegating_pubkey: UmbralPublicKey,
signing_pubkey,
receiving_pubkey: UmbralPublicKey):
if not all((delegating_pubkey, signing_pubkey, receiving_pubkey)):
raise TypeError("Need all three keys to verify correctness.")

pubkey_a_point = delegating_pubkey.point_key
pubkey_b_point = receiving_pubkey.point_key

return assess_cfrag_correctness(self, capsule, pubkey_a_point,
signing_pubkey, pubkey_b_point)
def verify_correctness(self, capsule: "Capsule"):
return assess_cfrag_correctness(self, capsule)

def attach_proof(self, e2, v2, u1, u2, z3, kfrag_signature, metadata):
self.proof = CorrectnessProof(point_e2=e2,
Expand Down
Loading

0 comments on commit 09832ec

Please sign in to comment.