mirror of https://github.com/nucypher/pyUmbral.git
commit
ef2ff044d8
|
@ -1,3 +1,4 @@
|
|||
from cryptography.hazmat.backends.openssl import backend
|
||||
from umbral.curvebn import CurveBN
|
||||
|
||||
|
||||
|
@ -9,9 +10,10 @@ def test_mocked_openssl_curvebn_arithmetic(mock_openssl, random_ec_curvebn1, ran
|
|||
random_ec_curvebn1 ** int(random_ec_curvebn2), # __pow__ (as int)
|
||||
random_ec_curvebn1 + random_ec_curvebn2, # __add__
|
||||
random_ec_curvebn1 - random_ec_curvebn2, # __sub__
|
||||
-random_ec_curvebn1, # __neg__
|
||||
random_ec_curvebn1 % random_ec_curvebn2, # __mod__
|
||||
random_ec_curvebn1 % int(random_ec_curvebn2), # __mod__ (as int)
|
||||
~random_ec_curvebn1, # __invert__
|
||||
~random_ec_curvebn1, # __invert__
|
||||
random_ec_curvebn1 / random_ec_curvebn2 # __truediv__
|
||||
)
|
||||
|
||||
|
@ -21,3 +23,25 @@ def test_mocked_openssl_curvebn_arithmetic(mock_openssl, random_ec_curvebn1, ran
|
|||
assert operator_result
|
||||
assert isinstance(operator_result, CurveBN)
|
||||
|
||||
order = backend._bn_to_int(random_ec_curvebn1.curve.order)
|
||||
random_ec_curvebn1 = int(random_ec_curvebn1)
|
||||
random_ec_curvebn2 = int(random_ec_curvebn2)
|
||||
|
||||
# For simplicity, we test these two cases separately
|
||||
assert (int(operations_that_construct[-2]) * random_ec_curvebn1) % order == 1
|
||||
assert (int(operations_that_construct[-1]) * random_ec_curvebn2) % order == random_ec_curvebn1
|
||||
|
||||
# The remaining cases can be tested in bulk
|
||||
expected_results = (
|
||||
(random_ec_curvebn1 * random_ec_curvebn2) % order, # __mul__
|
||||
pow(random_ec_curvebn1, random_ec_curvebn2, order), # __pow__
|
||||
pow(random_ec_curvebn1, random_ec_curvebn2, order), # __pow__ (as int)
|
||||
(random_ec_curvebn1 + random_ec_curvebn2) % order, # __add__
|
||||
(random_ec_curvebn1 - random_ec_curvebn2) % order, # __sub__
|
||||
(-random_ec_curvebn1) % order, # __neg__
|
||||
random_ec_curvebn1 % random_ec_curvebn2, # __mod__
|
||||
random_ec_curvebn1 % int(random_ec_curvebn2), # __mod__ (as int)
|
||||
)
|
||||
|
||||
for (result, expected) in zip(operations_that_construct[:-2], expected_results):
|
||||
assert result == expected
|
|
@ -1,6 +1,6 @@
|
|||
from cryptography.hazmat.backends import default_backend
|
||||
from umbral import openssl
|
||||
|
||||
|
||||
_AVAIL_CURVES = {
|
||||
'secp256r1': 415,
|
||||
'secp256k1': 714,
|
||||
|
@ -40,6 +40,12 @@ class Curve:
|
|||
def __repr__(self):
|
||||
return "<OpenSSL Curve w/ NID {}>".format(self.curve_nid)
|
||||
|
||||
def get_field_order_size_in_bytes(self) -> int:
|
||||
backend = default_backend()
|
||||
size_in_bits = openssl._get_ec_group_degree(self.ec_group)
|
||||
return (size_in_bits + 7) // 8
|
||||
|
||||
|
||||
|
||||
SECP256R1 = Curve(_AVAIL_CURVES['secp256r1'])
|
||||
SECP256K1 = Curve(_AVAIL_CURVES['secp256k1'])
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
from typing import Optional, Union
|
||||
|
||||
from cryptography.hazmat.backends.openssl import backend
|
||||
from cryptography.hazmat.primitives import hashes
|
||||
|
||||
|
@ -5,7 +7,6 @@ from umbral import openssl
|
|||
from umbral.config import default_curve
|
||||
from umbral.curve import Curve
|
||||
from umbral.params import UmbralParameters
|
||||
from umbral.utils import get_field_order_size_in_bytes
|
||||
|
||||
|
||||
class CurveBN(object):
|
||||
|
@ -25,16 +26,16 @@ class CurveBN(object):
|
|||
self.curve = curve
|
||||
|
||||
@classmethod
|
||||
def expected_bytes_length(cls, curve: Curve=None) -> int:
|
||||
def expected_bytes_length(cls, curve: Optional[Curve] = None) -> int:
|
||||
"""
|
||||
Returns the size (in bytes) of a CurveBN given the curve.
|
||||
If no curve is provided, it uses the default.
|
||||
"""
|
||||
curve = curve if curve is not None else default_curve()
|
||||
return get_field_order_size_in_bytes(curve)
|
||||
return curve.get_field_order_size_in_bytes()
|
||||
|
||||
@classmethod
|
||||
def gen_rand(cls, curve: Curve=None) -> 'CurveBN':
|
||||
def gen_rand(cls, curve: Optional[Curve] = None) -> 'CurveBN':
|
||||
"""
|
||||
Returns a CurveBN object with a cryptographically secure OpenSSL BIGNUM
|
||||
based on the given curve.
|
||||
|
@ -54,7 +55,7 @@ class CurveBN(object):
|
|||
return cls(new_rand_bn, curve)
|
||||
|
||||
@classmethod
|
||||
def from_int(cls, num: int, curve: Curve=None) -> 'CurveBN':
|
||||
def from_int(cls, num: int, curve: Optional[Curve] = None) -> 'CurveBN':
|
||||
"""
|
||||
Returns a CurveBN object from a given integer on a curve.
|
||||
By default, the underlying OpenSSL BIGNUM has BN_FLG_CONSTTIME set for
|
||||
|
@ -99,7 +100,7 @@ class CurveBN(object):
|
|||
return cls(bignum, params.curve)
|
||||
|
||||
@classmethod
|
||||
def from_bytes(cls, data: bytes, curve: Curve=None) -> 'CurveBN':
|
||||
def from_bytes(cls, data: bytes, curve: Optional[Curve] = None) -> 'CurveBN':
|
||||
"""
|
||||
Returns a CurveBN object from the given byte data that's within the size
|
||||
of the provided curve's order.
|
||||
|
@ -123,7 +124,7 @@ class CurveBN(object):
|
|||
"""
|
||||
return backend._bn_to_int(self.bignum)
|
||||
|
||||
def __eq__(self, other) -> bool:
|
||||
def __eq__(self, other : Union[int, 'CurveBN']) -> bool:
|
||||
"""
|
||||
Compares the two BIGNUMS or int.
|
||||
"""
|
||||
|
@ -135,7 +136,7 @@ class CurveBN(object):
|
|||
# -1 less than, 0 is equal to, 1 is greater than
|
||||
return not bool(backend._lib.BN_cmp(self.bignum, other.bignum))
|
||||
|
||||
def __pow__(self, other) -> 'CurveBN':
|
||||
def __pow__(self, other : Union[int, 'CurveBN']) -> 'CurveBN':
|
||||
"""
|
||||
Performs a BN_mod_exp on two BIGNUMS.
|
||||
|
||||
|
@ -171,7 +172,7 @@ class CurveBN(object):
|
|||
|
||||
return CurveBN(product, self.curve)
|
||||
|
||||
def __truediv__(self, other) -> 'CurveBN':
|
||||
def __truediv__(self, other : 'CurveBN') -> 'CurveBN':
|
||||
"""
|
||||
Performs a BN_div on two BIGNUMs (modulo the order of the curve).
|
||||
|
||||
|
@ -183,6 +184,7 @@ class CurveBN(object):
|
|||
backend._ffi.NULL, other.bignum, self.curve.order, bn_ctx
|
||||
)
|
||||
backend.openssl_assert(inv_other != backend._ffi.NULL)
|
||||
inv_other = backend._ffi.gc(inv_other, backend._lib.BN_clear_free)
|
||||
|
||||
res = backend._lib.BN_mod_mul(
|
||||
product, self.bignum, inv_other, self.curve.order, bn_ctx
|
||||
|
@ -191,10 +193,15 @@ class CurveBN(object):
|
|||
|
||||
return CurveBN(product, self.curve)
|
||||
|
||||
def __add__(self, other) -> 'CurveBN':
|
||||
|
||||
def __add__(self, other : Union[int, 'CurveBN']) -> 'CurveBN':
|
||||
"""
|
||||
Performs a BN_mod_add on two BIGNUMs.
|
||||
"""
|
||||
if type(other) == int:
|
||||
other = openssl._int_to_bn(other)
|
||||
other = CurveBN(other, self.curve)
|
||||
|
||||
op_sum = openssl._get_new_BN()
|
||||
with backend._tmp_bn_ctx() as bn_ctx:
|
||||
res = backend._lib.BN_mod_add(
|
||||
|
@ -204,10 +211,14 @@ class CurveBN(object):
|
|||
|
||||
return CurveBN(op_sum, self.curve)
|
||||
|
||||
def __sub__(self, other) -> 'CurveBN':
|
||||
def __sub__(self, other : Union[int, 'CurveBN']) -> 'CurveBN':
|
||||
"""
|
||||
Performs a BN_mod_sub on two BIGNUMS.
|
||||
"""
|
||||
if type(other) == int:
|
||||
other = openssl._int_to_bn(other)
|
||||
other = CurveBN(other, self.curve)
|
||||
|
||||
diff = openssl._get_new_BN()
|
||||
with backend._tmp_bn_ctx() as bn_ctx:
|
||||
res = backend._lib.BN_mod_sub(
|
||||
|
@ -233,7 +244,24 @@ class CurveBN(object):
|
|||
|
||||
return CurveBN(inv, self.curve)
|
||||
|
||||
def __mod__(self, other) -> 'CurveBN':
|
||||
def __neg__(self) -> 'CurveBN':
|
||||
"""
|
||||
Computes the modular opposite (i.e., additive inverse) of a BIGNUM
|
||||
|
||||
"""
|
||||
zero = backend._int_to_bn(0)
|
||||
zero = backend._ffi.gc(zero, backend._lib.BN_clear_free)
|
||||
|
||||
the_opposite = openssl._get_new_BN()
|
||||
with backend._tmp_bn_ctx() as bn_ctx:
|
||||
res = backend._lib.BN_mod_sub(
|
||||
the_opposite, zero, self.bignum, self.curve.order, bn_ctx
|
||||
)
|
||||
backend.openssl_assert(res == 1)
|
||||
|
||||
return CurveBN(the_opposite, self.curve)
|
||||
|
||||
def __mod__(self, other : Union[int, 'CurveBN']) -> 'CurveBN':
|
||||
"""
|
||||
Performs a BN_nnmod on two BIGNUMS.
|
||||
"""
|
||||
|
|
|
@ -288,7 +288,7 @@ class UmbralKeyingMaterial(object):
|
|||
algorithm=hashes.BLAKE2b(64),
|
||||
length=64,
|
||||
salt=salt,
|
||||
info=b"NuCypherKMS/KeyDerivation/"+label,
|
||||
info=b"NuCypher/KeyDerivation/"+label,
|
||||
backend=default_backend()
|
||||
).derive(self.keying_material)
|
||||
|
||||
|
|
|
@ -7,15 +7,14 @@ from umbral.curve import Curve
|
|||
class UmbralParameters(object):
|
||||
def __init__(self, curve: Curve) -> None:
|
||||
from umbral.point import Point, unsafe_hash_to_point
|
||||
from umbral.utils import get_field_order_size_in_bytes
|
||||
|
||||
self.curve = curve
|
||||
self.CURVE_KEY_SIZE_BYTES = get_field_order_size_in_bytes(self.curve)
|
||||
self.CURVE_KEY_SIZE_BYTES = self.curve.get_field_order_size_in_bytes()
|
||||
|
||||
self.g = Point.get_generator_from_curve(curve=curve)
|
||||
g_bytes = self.g.to_bytes()
|
||||
|
||||
parameters_seed = b'NuCypherKMS/UmbralParameters/'
|
||||
parameters_seed = b'NuCypher/UmbralParameters/'
|
||||
self.u = unsafe_hash_to_point(g_bytes, self, parameters_seed + b'u')
|
||||
|
||||
def __eq__(self, other: 'UmbralParameters') -> bool:
|
||||
|
|
|
@ -9,7 +9,6 @@ from umbral.config import default_curve
|
|||
from umbral.curve import Curve
|
||||
from umbral.curvebn import CurveBN
|
||||
from umbral.params import UmbralParameters
|
||||
from umbral.utils import get_field_order_size_in_bytes
|
||||
|
||||
|
||||
class Point(object):
|
||||
|
@ -29,12 +28,13 @@ class Point(object):
|
|||
If no curve is provided, it uses the default curve.
|
||||
"""
|
||||
curve = curve if curve is not None else default_curve()
|
||||
base_size = get_field_order_size_in_bytes(curve)
|
||||
|
||||
if not is_compressed:
|
||||
base_size += get_field_order_size_in_bytes(curve)
|
||||
coord_size = curve.get_field_order_size_in_bytes()
|
||||
|
||||
return base_size + 1
|
||||
if is_compressed:
|
||||
return 1 + coord_size
|
||||
else:
|
||||
return 1 + 2 * coord_size
|
||||
|
||||
@classmethod
|
||||
def gen_rand(cls, curve: Optional[Curve] = None) -> 'Point':
|
||||
|
@ -129,7 +129,7 @@ class Point(object):
|
|||
if is_compressed is set to True.
|
||||
"""
|
||||
affine_x, affine_y = self.to_affine()
|
||||
key_size = get_field_order_size_in_bytes(self.curve)
|
||||
key_size = self.curve.get_field_order_size_in_bytes()
|
||||
|
||||
if is_compressed:
|
||||
y_bit = (affine_y & 1) + 2
|
||||
|
|
|
@ -10,7 +10,6 @@ from umbral.config import default_curve
|
|||
from umbral.curve import Curve
|
||||
from umbral.curvebn import CurveBN
|
||||
from umbral.keys import UmbralPublicKey, UmbralPrivateKey
|
||||
from umbral.utils import get_field_order_size_in_bytes
|
||||
|
||||
|
||||
_BLAKE2B = hashes.BLAKE2b(64)
|
||||
|
@ -32,7 +31,7 @@ class Signature:
|
|||
@classmethod
|
||||
def expected_bytes_length(cls, curve: Optional[Curve] = None) -> int:
|
||||
curve = curve if curve is not None else default_curve()
|
||||
return get_field_order_size_in_bytes(curve) * 2
|
||||
return 2 * curve.get_field_order_size_in_bytes()
|
||||
|
||||
def verify(self, message: bytes, verifying_key: UmbralPublicKey) -> bool:
|
||||
"""
|
||||
|
|
|
@ -4,29 +4,26 @@ from cryptography.hazmat.backends import default_backend
|
|||
from cryptography.hazmat.primitives import hashes
|
||||
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
|
||||
|
||||
from umbral import openssl
|
||||
from umbral.curve import Curve
|
||||
from umbral.curvebn import CurveBN
|
||||
|
||||
|
||||
def lambda_coeff(id_i: 'CurveBN', selected_ids: List['CurveBN']) -> 'CurveBN':
|
||||
def lambda_coeff(id_i: CurveBN, selected_ids: List[CurveBN]) -> CurveBN:
|
||||
ids = [x for x in selected_ids if x != id_i]
|
||||
|
||||
if not ids:
|
||||
return None
|
||||
|
||||
div_0 = ~(ids[0] - id_i)
|
||||
result = ids[0] * div_0
|
||||
result = ids[0] / (ids[0] - id_i)
|
||||
for id_j in ids[1:]:
|
||||
div_j = ~(id_j - id_i)
|
||||
result = result * (id_j * div_j)
|
||||
result = result * id_j / (id_j - id_i)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def poly_eval(coeff: List['CurveBN'], x: 'CurveBN') -> 'CurveBN':
|
||||
def poly_eval(coeff: List[CurveBN], x: CurveBN) -> CurveBN:
|
||||
result = coeff[-1]
|
||||
for i in range(-2, -len(coeff) - 1, -1):
|
||||
result = ((result * x) + coeff[i])
|
||||
result = (result * x) + coeff[i]
|
||||
|
||||
return result
|
||||
|
||||
|
@ -41,9 +38,3 @@ def kdf(ecpoint: 'Point', key_length: int) -> bytes:
|
|||
info=None,
|
||||
backend=default_backend()
|
||||
).derive(data)
|
||||
|
||||
|
||||
def get_field_order_size_in_bytes(curve: Curve) -> int:
|
||||
backend = default_backend()
|
||||
size_in_bits = openssl._get_ec_group_degree(curve.ec_group)
|
||||
return (size_in_bits + 7) // 8
|
||||
|
|
Loading…
Reference in New Issue