Merge pull request #9 from jMyles/master

Some more naming things, some more questions.
pull/16/head
David Núñez 2018-01-03 20:54:28 +01:00 committed by GitHub
commit 07e626438d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 60 additions and 51 deletions

View File

@ -13,7 +13,7 @@ parameters = [
]
def test_encrypt_decrypt():
def test_encapsulation():
pre = umbral.PRE()
priv_key = pre.gen_priv()
@ -22,7 +22,7 @@ def test_encrypt_decrypt():
sym_key, capsule = pre.encapsulate(pub_key)
assert len(sym_key) == 32
# The symmetric key sym_key should be used for block cipher
# The symmetric key sym_key is perhaps used for block cipher here in a real-world scenario.
sym_key_2 = pre.decapsulate_original(priv_key, capsule)
assert sym_key_2 == sym_key
@ -36,6 +36,7 @@ def test_m_of_n(N, threshold):
priv_bob = pre.gen_priv()
pub_bob = pre.priv2pub(priv_bob)
sym_key, capsule_alice = pre.encapsulate(pub_alice)
kfrags, vkeys = pre.split_rekey(priv_alice, pub_bob, threshold, N)
@ -44,18 +45,20 @@ def test_m_of_n(N, threshold):
assert pre.check_kFrag_signature(kfrag, pub_alice)
assert pre.check_kFrag_consistency(kfrag, vkeys)
cFrags = []
cfrags = []
for kFrag in kfrags[:threshold]:
cFrag = pre.reencrypt(kFrag, capsule_alice)
ch = pre.challenge(kFrag, capsule_alice, cFrag)
assert pre.check_challenge(capsule_alice, cFrag, ch, pub_alice)
cFrags.append(cFrag)
cfrags.append(cFrag)
capsule_bob = pre.reconstruct_capsule(cFrags)
capsule_bob = pre.reconstruct_capsule(cfrags)
sym_key_2 = pre.decapsulate_reencrypted(pub_bob, priv_bob, pub_alice, capsule_bob, capsule_alice)
sym_key_2 = pre.decapsulate_reencrypted(pub_bob, priv_bob, capsule_bob, pub_alice, capsule_alice)
assert sym_key_2 == sym_key
@pytest.mark.parametrize("N,threshold", parameters)
def test_cheating_Ursula_replays_old_reencryption(N, threshold):
pre = umbral.PRE()
@ -72,31 +75,31 @@ def test_cheating_Ursula_replays_old_reencryption(N, threshold):
for kfrag in kfrags:
assert pre.check_kFrag_consistency(kfrag, vkeys)
cFrags = []
cfrags = []
challenges = []
for kFrag in kfrags[:threshold]:
cFrag = pre.reencrypt(kFrag, capsule_alice)
challenge = pre.challenge(kFrag, capsule_alice, cFrag)
#assert pre.check_challenge(ekey_alice, cFrag, ch, pub_alice)
cFrags.append(cFrag)
cfrags.append(cFrag)
challenges.append(challenge)
# Let's put the re-encryption of a different Alice ciphertext
cFrags[0] = pre.reencrypt(kfrags[0], other_capsule_alice)
cfrags[0] = pre.reencrypt(kfrags[0], other_capsule_alice)
capsule_bob = pre.reconstruct_capsule(cFrags)
capsule_bob = pre.reconstruct_capsule(cfrags)
try:
# This line should always raise an AssertionError ("Generic Umbral Error")
sym_key_2 = pre.decapsulate_reencrypted(pub_bob, priv_bob, capsule_bob, pub_alice, capsule_alice)
sym_key_2 = pre.decapsulate_reencrypted(pub_bob, priv_bob, pub_alice, capsule_bob, capsule_alice)
assert not sym_key_2 == sym_key
except AssertionError as e:
assert str(e) == "Generic Umbral Error"
assert not pre.check_challenge(capsule_alice, cFrags[0], challenges[0], pub_alice)
assert not pre.check_challenge(capsule_alice, cfrags[0], challenges[0], pub_alice)
# The response of cheating Ursula is in capsules[0],
# so the rest of challenges chould be correct:
for (cFrag,ch) in zip(cFrags[1:], challenges[1:]):
for (cFrag,ch) in zip(cfrags[1:], challenges[1:]):
assert pre.check_challenge(capsule_alice, cFrag, ch, pub_alice)
@ -115,35 +118,36 @@ def test_cheating_ursula_sends_gargabe(N, threshold):
for kfrag in kfrags:
assert pre.check_kFrag_consistency(kfrag, vkeys)
cFrags = []
cfrags = []
challenges = []
for kFrag in kfrags[0:threshold]:
cFrag = pre.reencrypt(kFrag, capsule_alice)
challenge = pre.challenge(kFrag, capsule_alice, cFrag)
#assert pre.check_challenge(ekey_alice, cFrag, ch, pub_alice)
cFrags.append(cFrag)
cfrags.append(cFrag)
challenges.append(challenge)
# Let's put a random garbage in one of the cFrags
cFrags[0].e1 = Point.gen_rand(pre.curve)
cFrags[0].v1 = Point.gen_rand(pre.curve)
cfrags[0].e1 = Point.gen_rand(pre.curve)
cfrags[0].v1 = Point.gen_rand(pre.curve)
capsule_bob = pre.reconstruct_capsule(cFrags)
capsule_bob = pre.reconstruct_capsule(cfrags)
try:
# This line should always raise an AssertionError ("Generic Umbral Error")
sym_key_2 = pre.decapsulate_reencrypted(pub_bob, priv_bob, capsule_bob, pub_alice, capsule_alice)
sym_key_2 = pre.decapsulate_reencrypted(pub_bob, priv_bob, pub_alice, capsule_bob, capsule_alice)
assert not sym_key_2 == sym_key
except AssertionError as e:
assert str(e) == "Generic Umbral Error"
assert not pre.check_challenge(capsule_alice, cFrags[0], challenges[0], pub_alice)
assert not pre.check_challenge(capsule_alice, cfrags[0], challenges[0], pub_alice)
# The response of cheating Ursula is in capsules[0],
# so the rest of challenges chould be correct:
for (cFrag,ch) in zip(cFrags[1:], challenges[1:]):
for (cFrag,ch) in zip(cfrags[1:], challenges[1:]):
assert pre.check_challenge(capsule_alice, cFrag, ch, pub_alice)
@pytest.mark.parametrize("N,threshold", parameters)
def test_alice_sends_fake_kFrag_to_ursula(N, threshold):
pre = umbral.PRE()

View File

@ -1,10 +1,12 @@
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
from umbral.bignum import BigNum
from umbral.point import Point
from umbral.utils import poly_eval,lambda_coeff
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
from umbral.utils import poly_eval, lambda_coeff
class KFrag(object):
def __init__(self, id_, key, x, u1, z1, z2):
@ -15,12 +17,14 @@ class KFrag(object):
self.bn_sig1 = z1
self.bn_sig2 = z2
class Capsule(object):
def __init__(self, point_eph_e, point_eph_v, bn_sig):
self.point_eph_e = point_eph_e
self.point_eph_v = point_eph_v
self.bn_sig = bn_sig
class CapsuleFrag(object):
def __init__(self, e1, v1, id_, x):
self.e1 = e1
@ -28,12 +32,14 @@ class CapsuleFrag(object):
self.bn_kfrag_id = id_
self.point_eph_ni = x
class ReconstructedCapsule(object):
def __init__(self, e_prime, v_prime, x):
self.e_prime = e_prime
self.v_prime = v_prime
self.point_eph_ni = x
class ChallengeResponse(object):
def __init__(self, e2, v2, u1, u2, z1, z2, z3):
self.e2 = e2
@ -44,9 +50,11 @@ class ChallengeResponse(object):
self.bn_kfrag_sig2 = z2
self.bn_sig = z3
# minVal = (1 << 256) % self.order (i.e., 2^256 % order)
MINVAL_SECP256K1_HASH_256 = 432420386565659656852420866394968145599
class PRE(object):
def __init__(self):
self.backend = default_backend()
@ -59,14 +67,14 @@ class PRE(object):
digest = hashes.Hash(hashes.SHA256(), backend=default_backend())
for x in list:
if isinstance(x, Point):
bytes = x.to_bytes()
bytes = x.to_bytes()
elif isinstance(x, BigNum):
bytes = int(x).to_bytes(32, byteorder='big')
else:
#print(type(x))
# print(type(x))
bytes = x
digest.update(bytes)
i = 0
h = 0
while h < MINVAL_SECP256K1_HASH_256:
@ -76,14 +84,13 @@ class PRE(object):
h = int.from_bytes(hash, byteorder='big', signed=False)
i += 1
hash_bn = h % int(self.order)
#print()
#print("hash_bn: ", hash_bn)
#print("order: ", int(self.order))
# print()
# print("hash_bn: ", hash_bn)
# print("order: ", int(self.order))
res = BigNum.from_int(hash_bn, self.curve)
#print("res: ", int(res))
# print("res: ", int(res))
return res
def gen_priv(self):
return BigNum.gen_rand(self.curve)
@ -123,7 +130,7 @@ class PRE(object):
rk = poly_eval(coeffs, id_)
u1 = u * rk
y = BigNum.gen_rand(self.curve)
y = BigNum.gen_rand(self.curve)
z1 = self.hash_to_bn([xcomp, u1, self.g * y, id_])
z2 = y - priv_a * z1
@ -136,7 +143,7 @@ class PRE(object):
def check_kFrag_consistency(self, kFrag, vKeys):
if vKeys is None or len(vKeys) == 0:
raise ValueError('vKeys must not be empty')
# TODO: change this!
h = self.g
lh_exp = h * kFrag.point_key
@ -150,7 +157,7 @@ class PRE(object):
return lh_exp == rh_exp
def check_kFrag_signature(self, kFrag, pub_a):
u1 = kFrag.point_commitment
z1 = kFrag.bn_sig1
z2 = kFrag.bn_sig2
@ -231,10 +238,9 @@ class PRE(object):
return check31 & check32 & check33
def encapsulate(self, pub_key, key_length=32):
"""Generates a symmetric key and its associated KEM ciphertext"""
priv_r = BigNum.gen_rand(self.curve)
pub_r = self.g * priv_r
@ -273,7 +279,7 @@ class PRE(object):
def reconstruct_capsule(self, cFrags):
cFrag_0 = cFrags[0]
if len(cFrags) > 1:
ids = [cFrag.bn_kfrag_id for cFrag in cFrags]
lambda_0 = lambda_coeff(cFrag_0.bn_kfrag_id, ids)
@ -285,28 +291,27 @@ class PRE(object):
v = v + (cFrag.v1 * lambda_i)
return ReconstructedCapsule(e_prime=e, v_prime=v, x=cFrag_0.point_eph_ni)
else: #if len(reencrypted_keys) == 1:
return ReconstructedCapsule(e_prime=cFrag_0.e1, v_prime=cFrag_0.v1, x=cFrag_0.point_eph_ni)
def decapsulate_reencrypted(self, pub_key, priv_key, ctxt_combined, orig_pk, orig_ciphertext, key_length=32):
def decapsulate_reencrypted(self, pub_key: Point, priv_key: BigNum, orig_pub_key: Point,
recapsule: ReconstructedCapsule, original_capsule: Capsule, key_length=32):
"""Derive the same symmetric key"""
xcomp = ctxt_combined.point_eph_ni
xcomp = recapsule.point_eph_ni
d = self.hash_to_bn([xcomp, pub_key, xcomp * priv_key])
e_prime = ctxt_combined.e_prime
v_prime = ctxt_combined.v_prime
e_prime = recapsule.e_prime
v_prime = recapsule.v_prime
shared_key = (e_prime + v_prime) * d
key = self.kdf(shared_key, key_length)
e = orig_ciphertext.point_eph_e
v = orig_ciphertext.point_eph_v
s = orig_ciphertext.bn_sig
e = original_capsule.point_eph_e
v = original_capsule.point_eph_v
s = original_capsule.bn_sig
h = self.hash_to_bn([e, v])
inv_d = ~d
assert orig_pk * (s * inv_d) == v_prime + (e_prime * h), "Generic Umbral Error"
assert orig_pub_key * (s * inv_d) == v_prime + (e_prime * h), "Generic Umbral Error"
return key