Skip to content

Commit

Permalink
Verify Capsules once on creation
Browse files Browse the repository at this point in the history
  • Loading branch information
fjarri committed Sep 12, 2020
1 parent 3e95809 commit 6696ebb
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 49 deletions.
57 changes: 33 additions & 24 deletions tests/unit/test_capsule_operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,36 +33,48 @@ def test_capsule_creation(alices_keys):
with pytest.raises(TypeError):
rare_capsule = Capsule(params) # Alice cannot make a capsule this way.

# Typical Alice, constructing a typical capsule
delegating_privkey, _signing_key = alices_keys
plaintext = b'peace at dawn'
ciphertext, typical_capsule = pre.encrypt(delegating_privkey.get_pubkey(), plaintext)

assert isinstance(typical_capsule, Capsule)

# Some users may create capsules their own way.
# Using the data from the previously created capsule to make sure it will pass verification.
custom_capsule = Capsule(params,
point_e=Point.gen_rand(),
point_v=Point.gen_rand(),
bn_sig=CurveBN.gen_rand())
point_e=typical_capsule.point_e,
point_v=typical_capsule.point_v,
bn_sig=typical_capsule.bn_sig)

assert isinstance(custom_capsule, Capsule)

# Typical Alice, constructing a typical capsule

def test_capsule_equality(alices_keys):
params = default_params()
delegating_privkey, _signing_key = alices_keys
plaintext = b'peace at dawn'
ciphertext, typical_capsule = pre.encrypt(delegating_privkey.get_pubkey(), plaintext)
_ciphertext, typical_capsule = pre.encrypt(delegating_privkey.get_pubkey(), plaintext)

assert isinstance(typical_capsule, Capsule)
one_capsule = Capsule(params,
point_e=typical_capsule.point_e,
point_v=typical_capsule.point_v,
bn_sig=typical_capsule.bn_sig)

same_capsule = Capsule(params,
point_e=typical_capsule.point_e,
point_v=typical_capsule.point_v,
bn_sig=typical_capsule.bn_sig)

def test_capsule_equality():
params = default_params()
assert one_capsule == same_capsule

one_capsule = Capsule(params,
point_e=Point.gen_rand(),
point_v=Point.gen_rand(),
bn_sig=CurveBN.gen_rand())
# Capsule creation involves RNG, so it will have different components
_ciphertext, another_typical_capsule = pre.encrypt(delegating_privkey.get_pubkey(), plaintext)

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

assert one_capsule != another_capsule

Expand All @@ -80,17 +92,14 @@ def test_decapsulation_by_alice(alices_keys):
assert sym_key_2 == sym_key


def test_bad_capsule_fails_reencryption(kfrags):
def test_bad_capsule_cannot_be_created():
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)
with pytest.raises(Capsule.NotValid, match="Capsule verification failed."):
bollocks_capsule = Capsule(params,
point_e=Point.gen_rand(),
point_v=Point.gen_rand(),
bn_sig=CurveBN.gen_rand())


def test_capsule_as_dict_key(alices_keys, bobs_keys):
Expand Down
12 changes: 8 additions & 4 deletions tests/unit/test_serialization_property_based.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from umbral.params import UmbralParameters
from umbral.point import Point
from umbral.random_oracles import unsafe_hash_to_point
from umbral.pre import Capsule
from umbral.pre import Capsule, _encapsulate

# test parameters
max_examples = 1000
Expand All @@ -43,6 +43,10 @@
points = binary(min_size=1).map(
lambda x: unsafe_hash_to_point(x, label=b'hypothesis', params=params))

public_keys = points.map(lambda p: UmbralPublicKey(p, params))

capsules = public_keys.map(lambda pk: _encapsulate(pk)[1])

signatures = tuples(integers(min_value=1, max_value=backend._bn_to_int(curve.order)),
integers(min_value=1, max_value=backend._bn_to_int(curve.order))).map(
lambda tup: tup[0].to_bytes(bn_size, 'big') + tup[1].to_bytes(bn_size, 'big'))
Expand Down Expand Up @@ -86,10 +90,10 @@ def test_kfrag_roundtrip(d, b0, p0, p1, sig_proxy, sig_bob):
signature_for_proxy=sig_proxy, signature_for_bob=sig_bob)
assert_kfrag_eq(k, KFrag.from_bytes(k.to_bytes()))

@given(points, points, bns)
@given(capsules)
@settings(max_examples=max_examples)
def test_capsule_roundtrip_0(p0, p1, b):
c = Capsule(params=params, point_e=p0, point_v=p1, bn_sig=b)
def test_capsule_roundtrip_0(capsule):
c = Capsule(params=params, point_e=capsule.point_e, point_v=capsule.point_v, bn_sig=capsule.bn_sig)
assert(c == Capsule.from_bytes(c.to_bytes(), params=params))

@given(points, points, points, points, bns, signatures)
Expand Down
4 changes: 0 additions & 4 deletions umbral/cfrags.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,6 @@ def from_kfrag_and_cfrag(cls,

params = capsule.params

# Check correctness of original ciphertext
if not capsule.verify():
raise capsule.NotValid("Capsule verification failed.")

rk = kfrag.bn_key
t = CurveBN.gen_rand(params.curve)
####
Expand Down
22 changes: 5 additions & 17 deletions umbral/pre.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ def __init__(self,
self.point_v = point_v
self.bn_sig = bn_sig

if not self._verify():
# Check correctness of original ciphertext
raise self.NotValid("Capsule verification failed.")

class NotValid(ValueError):
"""
raised if the capsule does not pass verification.
Expand Down Expand Up @@ -128,7 +132,7 @@ def to_bytes(self) -> bytes:
e, v, s = self.components()
return e.to_bytes() + v.to_bytes() + s.to_bytes()

def verify(self) -> bool:
def _verify(self):

g = self.params.g
e, v, s = self.components()
Expand Down Expand Up @@ -182,9 +186,6 @@ def check_key(key):

self._attached_cfrags = set() # type: set

def verify(self):
return self.capsule.verify()

def verify_cfrag(self, cfrag) -> bool:
return cfrag.verify_correctness(capsule=self.capsule,
delegating_pubkey=self.delegating_key,
Expand Down Expand Up @@ -319,9 +320,6 @@ def reencrypt(kfrag: KFrag,
if not isinstance(prepared_capsule, PreparedCapsule):
raise Capsule.NotValid

if not prepared_capsule.verify():
raise Capsule.NotValid

if verify_kfrag:
if not isinstance(kfrag, KFrag) or not prepared_capsule.verify_kfrag(kfrag):
raise KFrag.NotValid
Expand Down Expand Up @@ -358,10 +356,6 @@ def _decapsulate_original(private_key: UmbralPrivateKey,
key_length: int = DEM_KEYSIZE) -> bytes:
"""Derive the same symmetric key"""

if not capsule.verify():
# Check correctness of original ciphertext
raise capsule.NotValid("Capsule verification failed.")

shared_key = private_key.bn_key * (capsule.point_e + capsule.point_v) # type: Any
key = kdf(shared_key, key_length)
return key
Expand Down Expand Up @@ -482,9 +476,6 @@ def decrypt_original(ciphertext: bytes,
We hope that's a symmetric key, which we use to decrypt the ciphertext
and return the resulting cleartext.
"""
if not capsule.verify():
raise Capsule.NotValid

encapsulated_key = _decapsulate_original(decrypting_key, capsule)
return _dem_decrypt(encapsulated_key, ciphertext, capsule)

Expand All @@ -499,8 +490,5 @@ def decrypt_reencrypted(ciphertext: bytes,
We hope that's a symmetric key, which we use to decrypt the ciphertext
and return the resulting cleartext.
"""
if not capsule.verify():
raise Capsule.NotValid

encapsulated_key = _open_capsule(capsule, cfrags, decrypting_key, check_proof=check_proof)
return _dem_decrypt(encapsulated_key, ciphertext, capsule.capsule)

0 comments on commit 6696ebb

Please sign in to comment.