Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplified API #159

Merged
merged 11 commits into from
Jun 6, 2018
17 changes: 14 additions & 3 deletions tests/test_capsule/test_capsule_correctness_checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,19 @@
from umbral.point import Point
from umbral.pre import Capsule
from umbral.signing import Signer
from umbral.config import default_params


def test_cannot_attach_cfrag_without_keys():
"""
We need the proper keys to verify the correctness of CFrags
in order to attach them to a Capsule.
"""
capsule = Capsule(point_e=Point.gen_rand(),

params = default_params()

capsule = Capsule(params,
point_e=Point.gen_rand(),
point_v=Point.gen_rand(),
bn_sig=CurveBN.gen_rand())

Expand Down Expand Up @@ -59,7 +64,10 @@ def test_cannot_attach_cfrag_without_proof():
However, even when properly attaching keys, we can't attach the CFrag
if it is unproven.
"""
capsule = Capsule(point_e=Point.gen_rand(),
params = default_params()

capsule = Capsule(params,
point_e=Point.gen_rand(),
point_v=Point.gen_rand(),
bn_sig=CurveBN.gen_rand())

Expand All @@ -86,7 +94,10 @@ def test_cannot_set_different_keys():
"""
Once a key is set on a Capsule, it can't be changed to a different key.
"""
capsule = Capsule(point_e=Point.gen_rand(),
params = default_params()

capsule = Capsule(params,
point_e=Point.gen_rand(),
point_v=Point.gen_rand(),
bn_sig=CurveBN.gen_rand())

Expand Down
41 changes: 28 additions & 13 deletions tests/test_capsule/test_capsule_operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,21 @@
from umbral.pre import Capsule
from umbral.signing import Signer
from umbral.keys import UmbralPrivateKey
from umbral.config import default_params


def test_capsule_creation(alices_keys):

params = default_params()

with pytest.raises(TypeError):
rare_capsule = Capsule() # Alice cannot make a capsule this way.
rare_capsule = Capsule(params) # Alice cannot make a capsule this way.



# Some users may create capsules their own way.
custom_capsule = Capsule(point_e=Point.gen_rand(),
custom_capsule = Capsule(params,
point_e=Point.gen_rand(),
point_v=Point.gen_rand(),
bn_sig=CurveBN.gen_rand())

Expand All @@ -28,43 +35,52 @@ def test_capsule_creation(alices_keys):


def test_capsule_equality():
one_capsule = Capsule(point_e=Point.gen_rand(),
params = default_params()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We pass this in a ton. Should we make this a pytest fixture?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we should. Perhaps in another PR?


one_capsule = Capsule(params,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow - big change.

This is pretty cool I think.

But I'm left wondering: if Capsule is going to require params, does it perhaps make sense to make it private? Is there really ever a public reason for someone to init a Capsule?

point_e=Point.gen_rand(),
point_v=Point.gen_rand(),
bn_sig=CurveBN.gen_rand())

another_capsule = Capsule(point_e=Point.gen_rand(),
another_capsule = Capsule(params,
point_e=Point.gen_rand(),
point_v=Point.gen_rand(),
bn_sig=CurveBN.gen_rand())

assert one_capsule != another_capsule

activated_capsule = Capsule(point_e_prime=Point.gen_rand(),
activated_capsule = Capsule(params,
point_e_prime=Point.gen_rand(),
point_v_prime=Point.gen_rand(),
point_noninteractive=Point.gen_rand())

assert activated_capsule != one_capsule


def test_decapsulation_by_alice(alices_keys):
params = default_params()

delegating_privkey, _signing_privkey = alices_keys

sym_key, capsule = pre._encapsulate(delegating_privkey.get_pubkey().point_key)
sym_key, capsule = pre._encapsulate(delegating_privkey.get_pubkey())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh hallelujah. Holy shit what a relief.

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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh my goodness this is seriously amazing. This is how pyUmbral has always wanted to read. (Although again, as I outlined in #161, I might advocate even going all the way down to just delegating_key or delegating_secret and dropping the "priv" idea).

assert sym_key_2 == sym_key


def test_bad_capsule_fails_reencryption(alices_keys, bobs_keys):
params = default_params()
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(),
bollocks_capsule = Capsule(params,
point_e=Point.gen_rand(),
point_v=Point.gen_rand(),
bn_sig=CurveBN.gen_rand())

Expand Down Expand Up @@ -99,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 All @@ -116,14 +131,14 @@ def test_capsule_length(alices_keys, bobs_keys):

priv_key_bob, pub_key_bob = bobs_keys

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

kfrags = pre.split_rekey(delegating_privkey, signer, pub_key_bob, 10, 15)

for counter, kfrag in enumerate(kfrags):
assert len(capsule) == counter
cfrag = pre.reencrypt(kfrag, capsule)
Expand Down
36 changes: 23 additions & 13 deletions tests/test_capsule/test_capsule_serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,23 @@
from umbral import pre, keys
from umbral.curvebn import CurveBN
from umbral.point import Point
from umbral.config import default_curve
from umbral.config import default_curve, default_params
from umbral.signing import Signer


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)
_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)
new_capsule = pre.Capsule.from_bytes(capsule_bytes, params)

# Three ways to think about equality.
# First, the public approach for the Capsule. Simply:
Expand All @@ -39,26 +40,29 @@ def test_activated_capsule_serialization(alices_keys, bobs_keys):
delegating_pubkey = delegating_privkey.get_pubkey()
signer_alice = Signer(signing_privkey)

receiving_privkey, receiving_pubkey = bobs_keys
params = delegating_privkey.params
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an interesting paradigm where each key and capsule can have its own params.

This might be a great pattern in the future, but we should be careful with it for now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed on both points 100%. Interesting but be careful.


_unused_key, capsule = pre._encapsulate(delegating_pubkey.point_key)
receiving_privkey, receiving_pubkey = bobs_keys

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)
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)
new_rec_capsule = pre.Capsule.from_bytes(rec_capsule_bytes, params)

# Again, the same three perspectives on equality.
assert new_rec_capsule == capsule
Expand All @@ -71,22 +75,28 @@ def test_activated_capsule_serialization(alices_keys, bobs_keys):


def test_cannot_create_capsule_from_bogus_material(alices_keys):
params = alices_keys[0].params

with pytest.raises(TypeError):
capsule_of_questionable_parentage = pre.Capsule(point_e=Point.gen_rand(),
capsule_of_questionable_parentage = pre.Capsule(params,
point_e=Point.gen_rand(),
point_v=42,
bn_sig=CurveBN.gen_rand())

with pytest.raises(TypeError):
capsule_of_questionable_parentage = pre.Capsule(point_e=Point.gen_rand(),
capsule_of_questionable_parentage = pre.Capsule(params,
point_e=Point.gen_rand(),
point_v=Point.gen_rand(),
bn_sig=42)

with pytest.raises(TypeError):
capsule_of_questionable_parentage = pre.Capsule(point_e_prime=Point.gen_rand(),
capsule_of_questionable_parentage = pre.Capsule(params,
point_e_prime=Point.gen_rand(),
point_v_prime=42,
point_noninteractive=Point.gen_rand())

with pytest.raises(TypeError):
capsule_of_questionable_parentage = pre.Capsule(point_e_prime=Point.gen_rand(),
capsule_of_questionable_parentage = pre.Capsule(params,
point_e_prime=Point.gen_rand(),
point_v_prime=Point.gen_rand(),
point_noninteractive=42)
Loading