Verify Capsules once on creation

pull/258/head
Bogdan Opanchuk 2020-09-11 22:17:39 -07:00
parent 3e95809fea
commit 6696ebb2b3
4 changed files with 48 additions and 51 deletions

View File

@ -33,16 +33,6 @@ def test_capsule_creation(alices_keys):
with pytest.raises(TypeError):
rare_capsule = Capsule(params) # Alice cannot make a capsule this way.
# Some users may create capsules their own way.
custom_capsule = Capsule(params,
point_e=Point.gen_rand(),
point_v=Point.gen_rand(),
bn_sig=CurveBN.gen_rand())
assert isinstance(custom_capsule, Capsule)
# Typical Alice, constructing a typical capsule
delegating_privkey, _signing_key = alices_keys
plaintext = b'peace at dawn'
@ -50,19 +40,41 @@ def test_capsule_creation(alices_keys):
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=typical_capsule.point_e,
point_v=typical_capsule.point_v,
bn_sig=typical_capsule.bn_sig)
def test_capsule_equality():
assert isinstance(custom_capsule, 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)
one_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)
same_capsule = Capsule(params,
point_e=typical_capsule.point_e,
point_v=typical_capsule.point_v,
bn_sig=typical_capsule.bn_sig)
assert one_capsule == same_capsule
# 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
@ -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):

View File

@ -26,7 +26,7 @@ from umbral.keys import UmbralPrivateKey, UmbralPublicKey
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
@ -43,6 +43,10 @@ bns = integers(min_value=1, max_value=backend._bn_to_int(curve.order)).map(
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'))
@ -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)

View File

@ -61,10 +61,6 @@ class CorrectnessProof:
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)
####

View File

@ -74,6 +74,10 @@ class Capsule:
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.
@ -128,7 +132,7 @@ class Capsule:
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()
@ -182,9 +186,6 @@ class PreparedCapsule:
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,
@ -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
@ -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
@ -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)
@ -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)