def from_bytes(cls, data: bytes, curve: ec.EllipticCurve = None): """ Instantiate CorrectnessProof from serialized data. """ curve = curve if curve is not None else default_curve() key_size = get_curve_keysize_bytes(curve) data = BytesIO(data) # CurveBNs are the keysize in bytes, Points are compressed and the # keysize + 1 bytes long. e2 = Point.from_bytes(data.read(key_size + 1), curve) v2 = Point.from_bytes(data.read(key_size + 1), curve) kfrag_commitment = Point.from_bytes(data.read(key_size + 1), curve) kfrag_pok = Point.from_bytes(data.read(key_size + 1), curve) kfrag_sig1 = CurveBN.from_bytes(data.read(key_size), curve) kfrag_sig2 = CurveBN.from_bytes(data.read(key_size), curve) sig = CurveBN.from_bytes(data.read(key_size), curve) metadata = data.read() or None return cls(e2, v2, kfrag_commitment, kfrag_pok, kfrag_sig1, kfrag_sig2, sig, metadata=metadata)
def expected_bytes_length(cls, curve: Optional[Curve] = None) -> int: """ Returns the size (in bytes) of a compressed Point given a curve. If no curve is provided, it uses the default curve. """ curve = curve if curve is not None else default_curve() return get_field_order_size_in_bytes(curve) + 1
def from_affine(cls, coords, curve: ec.EllipticCurve = None): """ Returns a Point object from the given affine coordinates in a tuple in the format of (x, y) and a given curve. """ curve = curve if curve is not None else default_curve() try: curve_nid = backend._elliptic_curve_to_nid(curve) except AttributeError: # Presume that the user passed in the curve_nid curve_nid = curve affine_x, affine_y = coords if type(affine_x) == int: affine_x = openssl._int_to_bn(affine_x) if type(affine_y) == int: affine_y = openssl._int_to_bn(affine_y) group = openssl._get_ec_group_by_curve_nid(curve_nid) ec_point = openssl._get_EC_POINT_via_affine(affine_x, affine_y, ec_group=group) return cls(ec_point, curve_nid, group)
def get_generator_from_curve(cls, curve: Optional[Curve] = None) -> 'Point': """ Returns the generator Point from the given curve as a Point object. """ curve = curve if curve is not None else default_curve() return cls(curve.generator, curve)
def expected_bytes_length(cls, curve: ec.EllipticCurve = None): """ 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_curve_keysize_bytes(curve)
def get_size(cls, curve: ec.EllipticCurve=None): """ Returns the size (in bytes) of a compressed Point given a curve. If no curve is provided, it uses the default curve. """ curve = curve if curve is not None else default_curve() return get_curve_keysize_bytes(curve) + 1
def test_simple_api(N, M, curve=default_curve()): """Manually injects umbralparameters for multi-curve testing.""" params = UmbralParameters(curve=curve) priv_key_alice = keys.UmbralPrivateKey.gen_key(params=params) pub_key_alice = priv_key_alice.get_pubkey() priv_key_bob = keys.UmbralPrivateKey.gen_key(params=params) pub_key_bob = priv_key_bob.get_pubkey() plain_data = b'peace at dawn' ciphertext, capsule = pre.encrypt(pub_key_alice, plain_data, params=params) cleartext = pre.decrypt(ciphertext, capsule, priv_key_alice, params=params) assert cleartext == plain_data kfrags = pre.split_rekey(priv_key_alice, pub_key_bob, M, N, params=params) for kfrag in kfrags: cfrag = pre.reencrypt(kfrag, capsule, params=params) capsule.attach_cfrag(cfrag) reenc_cleartext = pre.decrypt(ciphertext, capsule, priv_key_bob, pub_key_alice, params=params) assert reenc_cleartext == plain_data
def gen_rand(cls, curve: ec.EllipticCurve = None): """ Returns a BigNum object with a cryptographically secure BigNum based on the given curve. """ curve = curve if curve is not None else default_curve() curve_nid = backend._elliptic_curve_to_nid(curve) group = backend._lib.EC_GROUP_new_by_curve_name(curve_nid) backend.openssl_assert(group != backend._ffi.NULL) order = backend._lib.BN_new() backend.openssl_assert(order != backend._ffi.NULL) order = backend._ffi.gc(order, backend._lib.BN_clear_free) with backend._tmp_bn_ctx() as bn_ctx: res = backend._lib.EC_GROUP_get_order(group, order, bn_ctx) backend.openssl_assert(res == 1) new_rand_bn = backend._lib.BN_new() backend.openssl_assert(new_rand_bn != backend._ffi.NULL) new_rand_bn = backend._ffi.gc(new_rand_bn, backend._lib.BN_clear_free) rand_res = backend._lib.BN_rand_range(new_rand_bn, order) backend.openssl_assert(rand_res == 1) return cls(new_rand_bn, curve_nid, group, order)
def gen_rand(cls, curve: ec.EllipticCurve = None): """ Returns a Point object with a cryptographically secure EC_POINT based on the provided curve. """ curve = curve if curve is not None else default_curve() curve_nid = backend._elliptic_curve_to_nid(curve) group = backend._lib.EC_GROUP_new_by_curve_name(curve_nid) backend.openssl_assert(group != backend._ffi.NULL) generator = backend._lib.EC_GROUP_get0_generator(group) backend.openssl_assert(generator != backend._ffi.NULL) rand_point = backend._lib.EC_POINT_new(group) backend.openssl_assert(rand_point != backend._ffi.NULL) rand_point = backend._ffi.gc(rand_point, backend._lib.EC_POINT_clear_free) rand_bn = BigNum.gen_rand(curve).bignum with backend._tmp_bn_ctx() as bn_ctx: res = backend._lib.EC_POINT_mul(group, rand_point, backend._ffi.NULL, generator, rand_bn, bn_ctx) backend.openssl_assert(res == 1) return Point(rand_point, curve_nid, group)
def gen_rand(cls, curve: ec.EllipticCurve = None): """ Returns a BigNum object with a cryptographically secure BigNum based on the given curve. """ curve = curve if curve is not None else default_curve() curve_nid = backend._elliptic_curve_to_nid(curve) group = backend._lib.EC_GROUP_new_by_curve_name(curve_nid) backend.openssl_assert(group != backend._ffi.NULL) order = backend._lib.BN_new() backend.openssl_assert(order != backend._ffi.NULL) order = backend._ffi.gc(order, backend._lib.BN_free) with backend._tmp_bn_ctx() as bn_ctx: res = backend._lib.EC_GROUP_get_order(group, order, bn_ctx) backend.openssl_assert(res == 1) order_int = backend._bn_to_int(order) # Generate random number on curve key_size = get_curve_keysize_bytes(curve) rand_num = int.from_bytes(os.urandom(key_size), 'big') while rand_num >= order_int or rand_num <= 0: rand_num = int.from_bytes(os.urandom(key_size), 'big') new_rand_bn = backend._int_to_bn(rand_num) new_rand_bn = backend._ffi.gc(new_rand_bn, backend._lib.BN_free) return cls(new_rand_bn, curve_nid, group, order)
def test_cfrag_serialization_no_proof_no_metadata(alices_keys, bobs_keys): delegating_privkey, signing_privkey = alices_keys delegating_pubkey = delegating_privkey.get_pubkey() _receiving_privkey, receiving_pubkey = bobs_keys signer_alice = Signer(signing_privkey) _unused_key, capsule = pre._encapsulate(delegating_pubkey.point_key) kfrags = pre.split_rekey(delegating_privkey, signer_alice, receiving_pubkey, 1, 2) cfrag = pre.reencrypt(kfrags[0], capsule, provide_proof=False) cfrag_bytes = cfrag.to_bytes() proof = cfrag.proof assert proof is None curve = default_curve() assert len(cfrag_bytes) == CapsuleFrag.expected_bytes_length(curve) new_cfrag = pre.CapsuleFrag.from_bytes(cfrag_bytes) assert new_cfrag._point_e1 == cfrag._point_e1 assert new_cfrag._point_v1 == cfrag._point_v1 assert new_cfrag._kfrag_id == cfrag._kfrag_id assert new_cfrag._point_noninteractive == cfrag._point_noninteractive new_proof = new_cfrag.proof assert new_proof is None
def from_bytes(cls, data: bytes, curve: Optional[Curve] = None) -> 'KFrag': """ Instantiate a KFrag object from the serialized data. """ curve = curve if curve is not None else default_curve() bn_size = CurveBN.expected_bytes_length(curve) point_size = Point.expected_bytes_length(curve) signature_size = Signature.expected_bytes_length(curve) arguments = {'curve': curve} splitter = BytestringSplitter( bn_size, # id (CurveBN, bn_size, arguments), # bn_key (Point, point_size, arguments), # point_commitment (Point, point_size, arguments), # point_precursor 1, # keys_in_signature (Signature, signature_size, arguments), # signature_for_proxy (Signature, signature_size, arguments), # signature_for_bob ) components = splitter(data) return cls(identifier=components[0], bn_key=components[1], point_commitment=components[2], point_precursor=components[3], keys_in_signature=components[4], signature_for_proxy=components[5], signature_for_bob=components[6])
def test_simple_api(N, M, curve=default_curve()): """Manually injects umbralparameters for multi-curve testing.""" params = UmbralParameters(curve=curve) delegating_privkey = UmbralPrivateKey.gen_key(params=params) delegating_pubkey = delegating_privkey.get_pubkey() signing_privkey = UmbralPrivateKey.gen_key(params=params) signing_pubkey = signing_privkey.get_pubkey() signer = Signer(signing_privkey) receiving_privkey = UmbralPrivateKey.gen_key(params=params) receiving_pubkey = receiving_privkey.get_pubkey() plain_data = b'peace at dawn' ciphertext, capsule = pre.encrypt(delegating_pubkey, plain_data) cleartext = pre.decrypt(ciphertext, capsule, delegating_privkey) assert cleartext == plain_data capsule.set_correctness_keys(delegating=delegating_pubkey, receiving=receiving_pubkey, verifying=signing_pubkey) kfrags = pre.split_rekey(delegating_privkey, signer, receiving_pubkey, M, N) for kfrag in kfrags: cfrag = pre.reencrypt(kfrag, capsule) capsule.attach_cfrag(cfrag) reenc_cleartext = pre.decrypt(ciphertext, capsule, receiving_privkey) assert reenc_cleartext == plain_data
def from_int(cls, num, curve: ec.EllipticCurve = None): """ Returns a BigNum object from a given integer on a curve. """ curve = curve if curve is not None else default_curve() try: curve_nid = backend._elliptic_curve_to_nid(curve) except AttributeError: # Presume that the user passed in the curve_nid curve_nid = curve group = backend._lib.EC_GROUP_new_by_curve_name(curve_nid) backend.openssl_assert(group != backend._ffi.NULL) order = backend._lib.BN_new() backend.openssl_assert(order != backend._ffi.NULL) order = backend._ffi.gc(order, backend._lib.BN_clear_free) with backend._tmp_bn_ctx() as bn_ctx: res = backend._lib.EC_GROUP_get_order(group, order, bn_ctx) backend.openssl_assert(res == 1) order_int = backend._bn_to_int(order) if num <= 0 or num >= order_int: # TODO: Handle this better maybe? Ask David. raise ValueError("Integer provided is not on the given curve.") bignum = backend._int_to_bn(num) bignum = backend._ffi.gc(bignum, backend._lib.BN_clear_free) return cls(bignum, curve_nid, group, order)
def from_affine(cls, coords, curve: ec.EllipticCurve = None): """ Returns a Point object from the given affine coordinates in a tuple in the format of (x, y) and a given curve. """ curve = curve if curve is not None else default_curve() try: curve_nid = backend._elliptic_curve_to_nid(curve) except AttributeError: # Presume that the user passed in the curve_nid curve_nid = curve affine_x, affine_y = coords if type(affine_x) == int: affine_x = backend._int_to_bn(affine_x) affine_x = backend._ffi.gc(affine_x, backend._lib.BN_clear_free) if type(affine_y) == int: affine_y = backend._int_to_bn(affine_y) affine_y = backend._ffi.gc(affine_y, backend._lib.BN_clear_free) group = backend._lib.EC_GROUP_new_by_curve_name(curve_nid) backend.openssl_assert(group != backend._ffi.NULL) ec_point = backend._lib.EC_POINT_new(group) backend.openssl_assert(ec_point != backend._ffi.NULL) with backend._tmp_bn_ctx() as bn_ctx: res = backend._lib.EC_POINT_set_affine_coordinates_GFp( group, ec_point, affine_x, affine_y, bn_ctx) backend.openssl_assert(res == 1) return Point(ec_point, curve_nid, group)
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 curve.field_order_size_in_bytes
def from_bytes(cls, capsule_bytes: bytes, curve: ec.EllipticCurve = None): """ Instantiates a Capsule object from the serialized data. """ curve = curve if curve is not None else default_curve() key_size = get_curve_keysize_bytes(curve) capsule_buff = BytesIO(capsule_bytes) # CurveBNs are the keysize in bytes, Points are compressed and the # keysize + 1 bytes long. if len(capsule_bytes) == 197: e = Point.from_bytes(capsule_buff.read(key_size + 1), curve) v = Point.from_bytes(capsule_buff.read(key_size + 1), curve) sig = CurveBN.from_bytes(capsule_buff.read(key_size), curve) e_prime = Point.from_bytes(capsule_buff.read(key_size + 1), curve) v_prime = Point.from_bytes(capsule_buff.read(key_size + 1), curve) ni = Point.from_bytes(capsule_buff.read(key_size + 1), curve) else: e = Point.from_bytes(capsule_buff.read(key_size + 1), curve) v = Point.from_bytes(capsule_buff.read(key_size + 1), curve) sig = CurveBN.from_bytes(capsule_buff.read(key_size), curve) e_prime = v_prime = ni = None return cls(point_e=e, point_v=v, bn_sig=sig, point_e_prime=e_prime, point_v_prime=v_prime, point_noninteractive=ni)
def from_bytes(cls, capsule_bytes: bytes, curve: ec.EllipticCurve = None): """ Instantiates a Capsule object from the serialized data. """ curve = curve if curve is not None else default_curve() bn_size = CurveBN.expected_bytes_length(curve) point_size = Point.expected_bytes_length(curve) if len(capsule_bytes) == cls.expected_bytes_length(curve, activated=True): splitter = BytestringSplitter( (Point, point_size), # point_e (Point, point_size), # point_v (CurveBN, bn_size), # bn_sig (Point, point_size), # point_e_prime (Point, point_size), # point_v_prime (Point, point_size) # point_noninteractive ) else: splitter = BytestringSplitter( (Point, point_size), # point_e (Point, point_size), # point_v (CurveBN, bn_size) # bn_sig ) components = splitter(capsule_bytes) return cls(*components)
def from_bytes(cls, data: bytes, curve: Optional[Curve] = None) -> 'CapsuleFrag': """ Instantiates a CapsuleFrag object from the serialized data. """ curve = curve if curve is not None else default_curve() bn_size = CurveBN.expected_bytes_length(curve) point_size = Point.expected_bytes_length(curve) arguments = {'curve': curve} splitter = BytestringSplitter( (Point, point_size, arguments), # point_e1 (Point, point_size, arguments), # point_v1 bn_size, # kfrag_id (Point, point_size, arguments), # point_precursor ) components = splitter(data, return_remainder=True) proof = components.pop() or None components.append( CorrectnessProof.from_bytes(proof, curve) if proof else None) return cls(*components)
def expected_bytes_length(cls, curve: Optional[Curve] = None) -> int: """ Returns the size (in bytes) of a CurveBN given the curve, which comes from the size of the order of the generated group. If no curve is provided, it uses the default. """ curve = curve if curve is not None else default_curve() return curve.group_order_size_in_bytes
def from_bytes(cls, data, curve: ec.EllipticCurve = None): """ Returns a BigNum object from the given byte data that's within the size of the provided curve's order. """ curve = curve if curve is not None else default_curve() num = int.from_bytes(data, 'big') return BigNum.from_int(num, curve)
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 constant time operations. """ curve = curve if curve is not None else default_curve() conv_bn = openssl._int_to_bn(num, curve) return cls(conv_bn, curve)
def get_size(cls, curve: ec.EllipticCurve = None): """ Returns the size (in bytes) of a KFrag given the curve. If no curve is provided, it will use the default curve. """ curve = curve if curve is not None else default_curve() bn_size = CurveBN.get_size(curve) point_size = Point.get_size(curve) return (bn_size * 4) + (point_size * 2)
def expected_bytes_length(cls, curve: Optional[Curve] = None) -> int: """ Returns the size (in bytes) of a Capsule given the curve. If no curve is provided, it will use the default curve. """ curve = curve if curve is not None else default_curve() bn_size = CurveBN.expected_bytes_length(curve) point_size = Point.expected_bytes_length(curve) return (bn_size * 1) + (point_size * 2)
def get_size(cls, curve: ec.EllipticCurve = None): """ Returns the size (in bytes) of a CorrectnessProof without the metadata. If no curve is given, it will use the default curve. """ curve = curve if curve is not None else default_curve() bn_size = CurveBN.get_size(curve=curve) point_size = Point.get_size(curve=curve) return (bn_size * 3) + (point_size * 4)
def from_bytes(cls, data: bytes, curve: Curve = None) -> 'CurveBN': """ Returns a CurveBN object from the given byte data that's within the size of the provided curve's order. By default, the underlying OpenSSL BIGNUM has BN_FLG_CONSTTIME set for constant time operations. """ curve = curve if curve is not None else default_curve() num = int.from_bytes(data, 'big') return cls.from_int(num, curve)
def expected_bytes_length(cls, curve: Optional[Curve] = None): """ Returns the size (in bytes) of a CorrectnessProof without the metadata. If no curve is given, it will use the default curve. """ curve = curve if curve is not None else default_curve() bn_size = CurveBN.expected_bytes_length(curve=curve) point_size = Point.expected_bytes_length(curve=curve) return (bn_size * 3) + (point_size * 4)
def get_size(cls, curve: ec.EllipticCurve = None): """ Returns the size (in bytes) of a CapsuleFrag given the curve without the CorrectnessProof. If no curve is provided, it will use the default curve. """ curve = curve if curve is not None else default_curve() bn_size = CurveBN.get_size(curve) point_size = Point.get_size(curve) return (bn_size * 1) + (point_size * 3)
def expected_bytes_length(cls, curve: Optional[EllipticCurve] = None) -> int: """ Returns the size (in bytes) of a CapsuleFrag given the curve without the CorrectnessProof. If no curve is provided, it will use the default curve. """ curve = curve if curve is not None else default_curve() bn_size = CurveBN.expected_bytes_length(curve) point_size = Point.expected_bytes_length(curve) return (bn_size * 1) + (point_size * 4)
def from_bytes(cls, data: bytes, curve: Optional[Curve] = None) -> 'Point': """ Returns a Point object from the given byte data on the curve provided. """ curve = curve if curve is not None else default_curve() point = openssl._get_new_EC_POINT(curve) with backend._tmp_bn_ctx() as bn_ctx: res = backend._lib.EC_POINT_oct2point(curve.ec_group, point, data, len(data), bn_ctx) backend.openssl_assert(res == 1) return cls(point, curve)