From 43714203de4e67c483c3b2de99a4cabe0eb87b05 Mon Sep 17 00:00:00 2001 From: jMyles Date: Mon, 23 Oct 2017 23:12:01 -0700 Subject: [PATCH 1/6] A sketch of how we might tackle #9. --- npre/umbral.py | 23 ++++++++++++++++++++++- tests/test_umbral.py | 11 +++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/npre/umbral.py b/npre/umbral.py index 5a3f542..3a854c7 100644 --- a/npre/umbral.py +++ b/npre/umbral.py @@ -12,7 +12,28 @@ EncryptedKey = namedtuple('EncryptedKey', ['ekey', 're_id']) -RekeyFrag = namedtuple('RekeyFrag', ['id', 'key']) + + +class RekeyFrag(object): + + DELIMETER = b"||" + + def __init__(self, id, key): + self.id = id + self.key = key + + def __bytes__(self): + return int(self.id).to_bytes(32, byteorder='big') + self.DELIMETER + int(self.key).to_bytes(32, byteorder='big') + + def __eq__(self, other_kfrag): + return self.id == other_kfrag.id and self.key == other_kfrag.key + + + @classmethod + def from_bytes(cls, kfrag_bytes): + # TODO: Obviously this needs to actually do something that reconstructs the kFrag. + id, key = kfrag_bytes.split(cls.DELIMETER) + return RekeyFrag(id, key) # XXX serialization probably should be done through decorators # XXX write tests diff --git a/tests/test_umbral.py b/tests/test_umbral.py index 0d4b613..e17c8ff 100644 --- a/tests/test_umbral.py +++ b/tests/test_umbral.py @@ -1,5 +1,6 @@ import pytest from npre import umbral +from npre.umbral import RekeyFrag def test_encrypt_decrypt(): @@ -60,3 +61,13 @@ def test_m_of_n(N, threshold): sym_key_2 = pre.decapsulate(priv_bob, ekey_bob) assert sym_key_2 == sym_key + + return kfrags + + +def test_frag_as_bytes(): + kfrags = test_m_of_n(5, 5) + some_particular_kfrag = kfrags[3] + kfrag_as_bytes = bytes(some_particular_kfrag) + back_to_kfrag = RekeyFrag.from_bytes(kfrag_as_bytes) + assert some_particular_kfrag == back_to_kfrag \ No newline at end of file From 5b2a01f889f5ac46769527b778b187d1b2c32f04 Mon Sep 17 00:00:00 2001 From: jMyles Date: Fri, 27 Oct 2017 13:08:51 -0700 Subject: [PATCH 2/6] Using de/serialize methods in RekeyFrag class, but they don't seem to work properly. --- npre/constants.py | 1 + npre/umbral.py | 11 ++++++----- tests/test_umbral.py | 8 ++++++++ 3 files changed, 15 insertions(+), 5 deletions(-) create mode 100644 npre/constants.py diff --git a/npre/constants.py b/npre/constants.py new file mode 100644 index 0000000..d572802 --- /dev/null +++ b/npre/constants.py @@ -0,0 +1 @@ +UNKNOWN_KFRAG = 550 \ No newline at end of file diff --git a/npre/umbral.py b/npre/umbral.py index 3a854c7..32e40e8 100644 --- a/npre/umbral.py +++ b/npre/umbral.py @@ -4,6 +4,7 @@ import npre.elliptic_curve as ec from npre import curves +from npre.constants import UNKNOWN_KFRAG from typing import Union from sha3 import keccak_256 as keccak from collections import namedtuple @@ -23,17 +24,17 @@ def __init__(self, id, key): self.key = key def __bytes__(self): - return int(self.id).to_bytes(32, byteorder='big') + self.DELIMETER + int(self.key).to_bytes(32, byteorder='big') + return ec.serialize(self.id) + ec.serialize(self.key) def __eq__(self, other_kfrag): + if other_kfrag == UNKNOWN_KFRAG: + return False return self.id == other_kfrag.id and self.key == other_kfrag.key - @classmethod def from_bytes(cls, kfrag_bytes): - # TODO: Obviously this needs to actually do something that reconstructs the kFrag. - id, key = kfrag_bytes.split(cls.DELIMETER) - return RekeyFrag(id, key) + return RekeyFrag(id=ec.deserialize(kfrag_bytes[:len(kfrag_bytes) // 2]), + key=ec.deserialize(kfrag_bytes[len(kfrag_bytes) // 2:])) # XXX serialization probably should be done through decorators # XXX write tests diff --git a/tests/test_umbral.py b/tests/test_umbral.py index e17c8ff..3cc90af 100644 --- a/tests/test_umbral.py +++ b/tests/test_umbral.py @@ -1,6 +1,7 @@ import pytest from npre import umbral from npre.umbral import RekeyFrag +import npre.elliptic_curve as ec def test_encrypt_decrypt(): @@ -65,6 +66,13 @@ def test_m_of_n(N, threshold): return kfrags +def test_kfrag_serialization(): + kfrags = test_m_of_n(5, 5) + some_particular_kfrag = kfrags[3] + serialized_id = ec.serialize(some_particular_kfrag.id) + deserialized_id = ec.deserialize(serialized_id) + + def test_frag_as_bytes(): kfrags = test_m_of_n(5, 5) some_particular_kfrag = kfrags[3] From 1bd7539f065650b906a2d5ee36787b795ed9be0c Mon Sep 17 00:00:00 2001 From: jMyles Date: Fri, 27 Oct 2017 15:18:55 -0700 Subject: [PATCH 3/6] Deserialization requires PRE - allowed injection into RekeyFrag class. --- npre/umbral.py | 56 +++++++++++++++++++++++++------------------- tests/test_umbral.py | 12 ++++++---- 2 files changed, 39 insertions(+), 29 deletions(-) diff --git a/npre/umbral.py b/npre/umbral.py index 32e40e8..3ee0d11 100644 --- a/npre/umbral.py +++ b/npre/umbral.py @@ -14,28 +14,6 @@ EncryptedKey = namedtuple('EncryptedKey', ['ekey', 're_id']) - -class RekeyFrag(object): - - DELIMETER = b"||" - - def __init__(self, id, key): - self.id = id - self.key = key - - def __bytes__(self): - return ec.serialize(self.id) + ec.serialize(self.key) - - def __eq__(self, other_kfrag): - if other_kfrag == UNKNOWN_KFRAG: - return False - return self.id == other_kfrag.id and self.key == other_kfrag.key - - @classmethod - def from_bytes(cls, kfrag_bytes): - return RekeyFrag(id=ec.deserialize(kfrag_bytes[:len(kfrag_bytes) // 2]), - key=ec.deserialize(kfrag_bytes[len(kfrag_bytes) // 2:])) - # XXX serialization probably should be done through decorators # XXX write tests @@ -104,7 +82,7 @@ def save_key(self, key): def rekey(self, priv1, priv2, dtype=None): # Same as in BBS98 rk = priv1 * (~priv2) - return RekeyFrag(id=None, key=rk) + return RekeyFrag(id=None, key=rk, pre=self) def split_rekey(self, priv_a, priv_b, threshold, N): coeffs = [priv_a * (~priv_b)] # Standard rekey @@ -112,7 +90,7 @@ def split_rekey(self, priv_a, priv_b, threshold, N): ids = [ec.random(self.ecgroup, ec.ZR) for _ in range(N)] rk_shares = [ - RekeyFrag(id, key=poly_eval(coeffs, id)) + RekeyFrag(id, key=poly_eval(coeffs, id), pre=self) for id in ids] return rk_shares @@ -151,3 +129,33 @@ def decapsulate(self, priv_key, ekey): shared_key = ekey.ekey ** priv_key key = self.kdf(shared_key) return key + + +class RekeyFrag(object): + + DELIMETER = b"||" + + _pre = PRE() + + def __init__(self, id, key, pre=None): + self.id = id + self.key = key + if pre is None: + pre = self._pre + self.pre = pre + + + def __bytes__(self): + return ec.serialize(self.id) + ec.serialize(self.key) + + def __eq__(self, other_kfrag): + if other_kfrag == UNKNOWN_KFRAG: + return False + return self.id == other_kfrag.id and self.key == other_kfrag.key + + @classmethod + def from_bytes(cls, kfrag_bytes, pre=None): + pre = pre or cls._pre + return RekeyFrag(id=ec.deserialize(pre.ecgroup, kfrag_bytes[:len(kfrag_bytes) // 2]), + key=ec.deserialize(pre.ecgroup, kfrag_bytes[len(kfrag_bytes) // 2:]), + pre=pre) diff --git a/tests/test_umbral.py b/tests/test_umbral.py index 3cc90af..5d4dbc6 100644 --- a/tests/test_umbral.py +++ b/tests/test_umbral.py @@ -63,18 +63,20 @@ def test_m_of_n(N, threshold): sym_key_2 = pre.decapsulate(priv_bob, ekey_bob) assert sym_key_2 == sym_key - return kfrags + return kfrags, pre def test_kfrag_serialization(): - kfrags = test_m_of_n(5, 5) + kfrags, pre = test_m_of_n(5, 5) some_particular_kfrag = kfrags[3] - serialized_id = ec.serialize(some_particular_kfrag.id) - deserialized_id = ec.deserialize(serialized_id) + original_id = some_particular_kfrag.id + serialized_id = ec.serialize(original_id) + deserialized_id = ec.deserialize(pre.ecgroup, serialized_id) + assert deserialized_id == original_id def test_frag_as_bytes(): - kfrags = test_m_of_n(5, 5) + kfrags, pre = test_m_of_n(5, 5) some_particular_kfrag = kfrags[3] kfrag_as_bytes = bytes(some_particular_kfrag) back_to_kfrag = RekeyFrag.from_bytes(kfrag_as_bytes) From 8fc916f36f4ac894b12c4839ced9beb3b7a19e10 Mon Sep 17 00:00:00 2001 From: jMyles Date: Fri, 27 Oct 2017 15:28:25 -0700 Subject: [PATCH 4/6] Removing DELIMITER. --- npre/umbral.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/npre/umbral.py b/npre/umbral.py index 3ee0d11..442a1df 100644 --- a/npre/umbral.py +++ b/npre/umbral.py @@ -133,8 +133,6 @@ def decapsulate(self, priv_key, ekey): class RekeyFrag(object): - DELIMETER = b"||" - _pre = PRE() def __init__(self, id, key, pre=None): From 34542b5021d7445e5d467b5a512807341ce28e27 Mon Sep 17 00:00:00 2001 From: tuxxy Date: Thu, 2 Nov 2017 14:44:16 -0700 Subject: [PATCH 5/6] Fix python 3.6 issue --- npre/constants.py | 1 - npre/umbral.py | 62 ++++++++++++++++++++++---------------------- tests/test_umbral.py | 14 ++-------- 3 files changed, 33 insertions(+), 44 deletions(-) delete mode 100644 npre/constants.py diff --git a/npre/constants.py b/npre/constants.py deleted file mode 100644 index d572802..0000000 --- a/npre/constants.py +++ /dev/null @@ -1 +0,0 @@ -UNKNOWN_KFRAG = 550 \ No newline at end of file diff --git a/npre/umbral.py b/npre/umbral.py index 442a1df..b4e91d9 100644 --- a/npre/umbral.py +++ b/npre/umbral.py @@ -4,7 +4,6 @@ import npre.elliptic_curve as ec from npre import curves -from npre.constants import UNKNOWN_KFRAG from typing import Union from sha3 import keccak_256 as keccak from collections import namedtuple @@ -14,6 +13,35 @@ EncryptedKey = namedtuple('EncryptedKey', ['ekey', 're_id']) + +class RekeyFrag(object): + """ + Represents a fragment of a Re-encryption key. + """ + + def __init__(self, id, key): + self.id = id + self.key = key + + def __bytes__(self): + id = int(self.id).to_bytes(32, 'big') + key = int(self.key).to_bytes(32, 'big') + return id + key + + def __eq__(self, other_kfrag): + return self.id == other_kfrag.id and self.key == other_kfrag.key + + @classmethod + def from_bytes(cls, kfrag_bytes): + id = int.from_bytes(kfrag_bytes[:32], 'big') + key = int.from_bytes(kfrag_bytes[32:], 'big') + return RekeyFrag(id, key) + + @classmethod + def to_bytes(cls, kfrag): + return bytes(kfrag) + + # XXX serialization probably should be done through decorators # XXX write tests @@ -82,7 +110,7 @@ def save_key(self, key): def rekey(self, priv1, priv2, dtype=None): # Same as in BBS98 rk = priv1 * (~priv2) - return RekeyFrag(id=None, key=rk, pre=self) + return RekeyFrag(id=None, key=rk) def split_rekey(self, priv_a, priv_b, threshold, N): coeffs = [priv_a * (~priv_b)] # Standard rekey @@ -90,7 +118,7 @@ def split_rekey(self, priv_a, priv_b, threshold, N): ids = [ec.random(self.ecgroup, ec.ZR) for _ in range(N)] rk_shares = [ - RekeyFrag(id, key=poly_eval(coeffs, id), pre=self) + RekeyFrag(id, key=poly_eval(coeffs, id)) for id in ids] return rk_shares @@ -129,31 +157,3 @@ def decapsulate(self, priv_key, ekey): shared_key = ekey.ekey ** priv_key key = self.kdf(shared_key) return key - - -class RekeyFrag(object): - - _pre = PRE() - - def __init__(self, id, key, pre=None): - self.id = id - self.key = key - if pre is None: - pre = self._pre - self.pre = pre - - - def __bytes__(self): - return ec.serialize(self.id) + ec.serialize(self.key) - - def __eq__(self, other_kfrag): - if other_kfrag == UNKNOWN_KFRAG: - return False - return self.id == other_kfrag.id and self.key == other_kfrag.key - - @classmethod - def from_bytes(cls, kfrag_bytes, pre=None): - pre = pre or cls._pre - return RekeyFrag(id=ec.deserialize(pre.ecgroup, kfrag_bytes[:len(kfrag_bytes) // 2]), - key=ec.deserialize(pre.ecgroup, kfrag_bytes[len(kfrag_bytes) // 2:]), - pre=pre) diff --git a/tests/test_umbral.py b/tests/test_umbral.py index 5d4dbc6..e17c8ff 100644 --- a/tests/test_umbral.py +++ b/tests/test_umbral.py @@ -1,7 +1,6 @@ import pytest from npre import umbral from npre.umbral import RekeyFrag -import npre.elliptic_curve as ec def test_encrypt_decrypt(): @@ -63,20 +62,11 @@ def test_m_of_n(N, threshold): sym_key_2 = pre.decapsulate(priv_bob, ekey_bob) assert sym_key_2 == sym_key - return kfrags, pre - - -def test_kfrag_serialization(): - kfrags, pre = test_m_of_n(5, 5) - some_particular_kfrag = kfrags[3] - original_id = some_particular_kfrag.id - serialized_id = ec.serialize(original_id) - deserialized_id = ec.deserialize(pre.ecgroup, serialized_id) - assert deserialized_id == original_id + return kfrags def test_frag_as_bytes(): - kfrags, pre = test_m_of_n(5, 5) + kfrags = test_m_of_n(5, 5) some_particular_kfrag = kfrags[3] kfrag_as_bytes = bytes(some_particular_kfrag) back_to_kfrag = RekeyFrag.from_bytes(kfrag_as_bytes) From cf33261747ad51e15a36135c169d14128da48765 Mon Sep 17 00:00:00 2001 From: tuxxy Date: Thu, 2 Nov 2017 15:14:22 -0700 Subject: [PATCH 6/6] Fix things --- npre/umbral.py | 61 ++++++++++++++++++++++---------------------- tests/test_umbral.py | 14 ++++++++-- 2 files changed, 42 insertions(+), 33 deletions(-) diff --git a/npre/umbral.py b/npre/umbral.py index b4e91d9..0e5dd52 100644 --- a/npre/umbral.py +++ b/npre/umbral.py @@ -4,6 +4,7 @@ import npre.elliptic_curve as ec from npre import curves +from npre.constants import UNKNOWN_KFRAG from typing import Union from sha3 import keccak_256 as keccak from collections import namedtuple @@ -13,35 +14,6 @@ EncryptedKey = namedtuple('EncryptedKey', ['ekey', 're_id']) - -class RekeyFrag(object): - """ - Represents a fragment of a Re-encryption key. - """ - - def __init__(self, id, key): - self.id = id - self.key = key - - def __bytes__(self): - id = int(self.id).to_bytes(32, 'big') - key = int(self.key).to_bytes(32, 'big') - return id + key - - def __eq__(self, other_kfrag): - return self.id == other_kfrag.id and self.key == other_kfrag.key - - @classmethod - def from_bytes(cls, kfrag_bytes): - id = int.from_bytes(kfrag_bytes[:32], 'big') - key = int.from_bytes(kfrag_bytes[32:], 'big') - return RekeyFrag(id, key) - - @classmethod - def to_bytes(cls, kfrag): - return bytes(kfrag) - - # XXX serialization probably should be done through decorators # XXX write tests @@ -110,7 +82,7 @@ def save_key(self, key): def rekey(self, priv1, priv2, dtype=None): # Same as in BBS98 rk = priv1 * (~priv2) - return RekeyFrag(id=None, key=rk) + return RekeyFrag(id=None, key=rk, pre=self) def split_rekey(self, priv_a, priv_b, threshold, N): coeffs = [priv_a * (~priv_b)] # Standard rekey @@ -118,7 +90,7 @@ def split_rekey(self, priv_a, priv_b, threshold, N): ids = [ec.random(self.ecgroup, ec.ZR) for _ in range(N)] rk_shares = [ - RekeyFrag(id, key=poly_eval(coeffs, id)) + RekeyFrag(id, key=poly_eval(coeffs, id), pre=self) for id in ids] return rk_shares @@ -157,3 +129,30 @@ def decapsulate(self, priv_key, ekey): shared_key = ekey.ekey ** priv_key key = self.kdf(shared_key) return key + + +class RekeyFrag(object): + + _pre = PRE() + + def __init__(self, id, key, pre=None): + self.id = id + self.key = key + if pre is None: + pre = self._pre + self.pre = pre + + def __bytes__(self): + return ec.serialize(self.id) + ec.serialize(self.key) + + def __eq__(self, other_kfrag): + if other_kfrag is UNKNOWN_KFRAG: + return False + return bytes(self) == bytes(other_kfrag) + + @classmethod + def from_bytes(cls, kfrag_bytes, pre=None): + pre = pre or cls._pre + return RekeyFrag(id=ec.deserialize(pre.ecgroup, kfrag_bytes[:len(kfrag_bytes) // 2]), + key=ec.deserialize(pre.ecgroup, kfrag_bytes[len(kfrag_bytes) // 2:]), + pre=pre) diff --git a/tests/test_umbral.py b/tests/test_umbral.py index e17c8ff..5d4dbc6 100644 --- a/tests/test_umbral.py +++ b/tests/test_umbral.py @@ -1,6 +1,7 @@ import pytest from npre import umbral from npre.umbral import RekeyFrag +import npre.elliptic_curve as ec def test_encrypt_decrypt(): @@ -62,11 +63,20 @@ def test_m_of_n(N, threshold): sym_key_2 = pre.decapsulate(priv_bob, ekey_bob) assert sym_key_2 == sym_key - return kfrags + return kfrags, pre + + +def test_kfrag_serialization(): + kfrags, pre = test_m_of_n(5, 5) + some_particular_kfrag = kfrags[3] + original_id = some_particular_kfrag.id + serialized_id = ec.serialize(original_id) + deserialized_id = ec.deserialize(pre.ecgroup, serialized_id) + assert deserialized_id == original_id def test_frag_as_bytes(): - kfrags = test_m_of_n(5, 5) + kfrags, pre = test_m_of_n(5, 5) some_particular_kfrag = kfrags[3] kfrag_as_bytes = bytes(some_particular_kfrag) back_to_kfrag = RekeyFrag.from_bytes(kfrag_as_bytes)