def _SecFld(field): l = (field.order - 1).bit_length() name = f'SecFld{l}({field.__name__})' secfld = type(name, (SecureFiniteField, ), {'__slots__': ()}) secfld.__doc__ = 'Class of secret-shared finite field elements.' t = runtime.threshold m = len(runtime.parties) q = field.order if t == 0 or m < q: # TODO: cover case m=q using MDS codes secfld.subfield = None secfld.field = field else: secfld.subfield = field assert field.ext_deg == 1 # TODO: cover case ext_deg > 1 e = math.ceil(math.log(m + 1, q)) # ensure q**e > m with e>=2 modulus = finfields.find_irreducible(field.characteristic, e) secfld.field = finfields.GF(modulus) @classmethod def out_conv(cls, a): # field -> subfield assert a.value.degree() <= 0 return cls.subfield(int(a)) secfld._output_conversion = out_conv secfld.bit_length = l globals( )[name] = secfld # TODO: check name dynamic SecureFiniteField type sufficiently unique return secfld
def SecFld(order=None, modulus=None, char=None, ext_deg=None, min_order=None, signed=False): """Secure finite field of order q = p**d. Order q >= min_order. Field is prime (d = 1) by default and if modulus is prime. Extension degree d > 1 if order is a prime power p**d with d > 1, if modulus is a polynomial or a string or an integer > char, or if ext_deg is an integer > 1, or if min_order > char. """ # TODO: raise errors instead of assert statements if order is not None: p, d = gmpy2.factor_prime_power(order) char = char or p assert char == p ext_deg = ext_deg or d assert ext_deg == d # order now represented by (char, ext_deg) if isinstance(modulus, str): char = char or 2 modulus = gfpx.GFpX(char)(modulus) if isinstance(modulus, int): if char and modulus > char: modulus = gfpx.GFpX(char)(modulus) if isinstance(modulus, gfpx.Polynomial): char = char or modulus.p assert char == modulus.p ext_deg = ext_deg or modulus.degree() elif isinstance(modulus, int): char = char or modulus assert char == modulus ext_deg = ext_deg or 1 assert ext_deg == 1 else: assert modulus is None if min_order is None: char = char or 2 ext_deg = ext_deg or 1 min_order = char**ext_deg else: if char is None: ext_deg = ext_deg or 1 root, exact = gmpy2.iroot(min_order, ext_deg) min_char = root + (not exact ) # ceiling of min_order^(1/ext_deg) char = int(gmpy2.next_prime(min_char - 1)) else: if ext_deg is None: ext_deg = math.ceil(math.log(min_order, char)) if ext_deg == 1: modulus = char else: modulus = finfields.find_irreducible(char, ext_deg) order = order or char**ext_deg min_order = min_order or order assert min_order <= order field = finfields.GF(modulus) assert runtime.threshold == 0 or field.order > len(runtime.parties), \ 'Field order must exceed number of parties, unless threshold is 0.' # TODO: field.order >= number of parties for MDS field.is_signed = signed return _SecFld(field)