def setUp(self): gf2x = gfpx.GFpX(2) gf2x_ = gfpx.BinaryPolynomial gf3x = gfpx.GFpX(3) gf101x = gfpx.GFpX(101) self.mod_2 = (gf2x, gf2x_) self.mod_all = self.mod_2 + (gf3x, gf101x)
def setUp(self): global mod_2, mod_all gf2x = gfpx.GFpX(2) gf2x_ = gfpx.BinaryPolynomial gf3x = gfpx.GFpX(3) gf101x = gfpx.GFpX(101) mod_2 = (gf2x, gf2x_) mod_all = mod_2 + (gf3x, gf101x)
def setUp(self): self.f2 = finfields.GF(gfpx.GFpX(2)(2)) self.f256 = finfields.GF(gfpx.GFpX(2)(283)) # AES polynomial (283)_2 = X^8+X^4+X^3+X+1 self.f2p = finfields.GF(2) self.f19 = finfields.GF(19) # 19 % 4 = 3 self.f101 = finfields.GF(101) # 101 % 4 = 1 self.f101.is_signed = False self.f27 = finfields.GF(gfpx.GFpX(3)(46)) # irreducible polynomial X^3 + 2X^2 + 1 self.f81 = finfields.GF(gfpx.GFpX(3)(115)) # irreducible polynomial X^4 + X^3 + 2X + 1
def test_mod3(self): poly = gfpx.GFpX(3) self.assertEqual(poly(1) + poly(1), 2) self.assertEqual(poly(1) * poly(2), 2) self.assertEqual(poly(4) + poly(2), 3) self.assertEqual(poly(4) * poly(2), 8) self.assertEqual(poly(5) << 2, poly(45)) self.assertEqual(poly(45) >> 2, poly(5)) self.assertEqual(poly(82) % poly(46), 15) self.assertEqual(divmod(poly(81), poly(9)), (poly(9), 0)) self.assertEqual(divmod(poly(83), poly(9)), (poly(9), poly(2))) self.assertEqual(poly.gcd(poly(2), poly(5)), poly(1)) self.assertEqual(poly.gcd(poly(3), poly(5)), poly(1)) self.assertEqual(poly.gcd(poly(455), poly(410)), poly(5)) with self.assertRaises(ZeroDivisionError): poly.invert(poly(283), poly(283)) self.assertTrue(poly.is_irreducible(3)) self.assertFalse(poly.is_irreducible(99985)) self.assertTrue(poly.is_irreducible(99986)) self.assertEqual(poly.next_irreducible(53), 86) self.assertTrue(poly(7) >= poly(5)) self.assertTrue(poly(7) > poly(5)) self.assertTrue(poly(7) <= poly(8)) self.assertTrue(poly(7) < poly(8))
def _test_errors(self, poly): self.assertRaises(ValueError, poly.from_terms, 'x**2') self.assertRaises(TypeError, poly, 0.1) self.assertRaises(TypeError, poly, gfpx.GFpX(257)(0)) self.assertRaises(ValueError, poly, [poly.p]) self.assertRaises(TypeError, operator.add, poly(0), 0.1) self.assertRaises(TypeError, operator.sub, poly(0), 0.1) self.assertRaises(TypeError, operator.sub, 0.1, poly(0)) self.assertRaises(TypeError, operator.mul, poly(0), 0.1) self.assertRaises(TypeError, operator.lshift, poly(0), 0.1) self.assertRaises(TypeError, operator.lshift, 0.1, poly(0)) self.assertRaises(TypeError, operator.rshift, poly(0), 0.1) self.assertRaises(TypeError, operator.rshift, 0.1, poly(0)) self.assertRaises(TypeError, operator.floordiv, poly(0), 0.1) self.assertRaises(TypeError, operator.floordiv, 0.1, poly(0)) self.assertRaises(TypeError, operator.mod, poly(0), 0.1) self.assertRaises(TypeError, operator.mod, 0.1, poly(0)) self.assertRaises(TypeError, divmod, poly(0), 0.1) self.assertRaises(TypeError, divmod, 0.1, poly(0)) self.assertRaises(TypeError, operator.lt, poly(0), 0.1) self.assertRaises(TypeError, operator.lt, 0.1, poly(0)) # NB: tests > self.assertRaises(TypeError, operator.le, poly(0), 0.1) self.assertRaises(TypeError, operator.le, 0.1, poly(0)) # NB: tests < self.assertRaises(ZeroDivisionError, poly.invert, poly(283), poly(0)) self.assertRaises(ZeroDivisionError, poly.invert, poly(283), poly(283)) self.assertRaises(ZeroDivisionError, poly.mod, poly(283), poly(0)) self.assertRaises(ZeroDivisionError, poly.divmod, poly(283), poly(0)) self.assertRaises(ValueError, operator.pow, poly(3), -16)
def test_f256(self): f256 = self.f256 self.assertFalse(f256(0)) self.assertTrue(f256(1)) self.assertEqual(f256(1) + 0, f256(0) + f256(1)) self.assertEqual(f256(1) + 1, f256(0)) self.assertEqual(f256(3) * 0, f256(0)) self.assertEqual(f256(3) * 1, f256(3)) self.assertEqual(f256(16) * f256(16), f256(27)) self.assertEqual(f256(32) * f256(16), f256(54)) self.assertEqual(f256(57) * f256(67), f256(137)) self.assertEqual(f256(67) * f256(57), f256(137)) self.assertEqual(f256(137) / f256(57), f256(67)) self.assertEqual(f256(137) / f256(67), f256(57)) a = f256(0) b = f256(1) a += b self.assertEqual(a, f256(1)) a += 1 self.assertEqual(a, f256(0)) a -= b self.assertEqual(a, f256(1)) a *= b self.assertEqual(a, f256(1)) a *= 1 self.assertEqual(a, f256(1)) a /= 1 self.assertEqual(a, f256(1)) a <<= 0 a = a >> 0 self.assertEqual(a, f256(1)) a <<= 2 self.assertEqual(a, f256(4)) a >>= 2 self.assertEqual(a, f256(1)) a = f256(3) # generator X + 1 s = [int((a**i).value) for i in range(255)] self.assertListEqual(sorted(s), list(range(1, 256))) s = [int((a**i).value) for i in range(-255, 0)] self.assertListEqual(sorted(s), list(range(1, 256))) f256 = finfields.GF( gfpx.GFpX(2)(391)) # primitive polynomial X^8 + X^7 + X^2 + X + 1 a = f256(2) # generator X s = [int((a**i).value) for i in range(255)] self.assertListEqual(sorted(s), list(range(1, 256))) a = f256(0) self.assertEqual(a.sqrt(), 0) with self.assertRaises(ZeroDivisionError): a.sqrt(INV=True) a = f256(177) self.assertTrue(a.is_sqr()) self.assertEqual(a.sqrt()**2, a) a = f256(255) self.assertEqual(a.sqrt()**2, a) self.assertEqual(len({f256(i) for i in range(-120, 259)}), 256)
def test_field_caching(self): self.assertNotEqual(self.f2(1), self.f2p(1)) f2_cached = finfields.GF(gfpx.GFpX(2)(2)) self.assertEqual(self.f2(1), f2_cached(1)) self.assertEqual(self.f2(1) * f2_cached(1), self.f2(1)) f256_cached = finfields.GF(gfpx.GFpX(2)(283)) self.assertEqual(self.f256(3), f256_cached(3)) self.assertEqual(self.f256(3) * f256_cached(3), self.f256(5)) self.assertEqual(self.f256(48) * f256_cached(16), self.f256(45)) f2_cached = finfields.GF(2) self.assertEqual(self.f2p(1), f2_cached(1)) self.assertEqual(self.f2p(1) * f2_cached(1), 1) f19_cached = finfields.GF(19) self.assertEqual(self.f19(3), f19_cached(3)) self.assertEqual(self.f19(3) * f19_cached(3), 9) f101_cached = finfields.GF(101) self.assertEqual(self.f101(3), f101_cached(3)) self.assertEqual(self.f101(3) * f101_cached(23), 69)
def test_f256(self): f256 = self.f256 self.assertFalse(f256(0)) self.assertTrue(f256(1)) self.assertEqual(f256(1) + 0, f256(0) + f256(1)) self.assertEqual(f256(1) + 1, f256(0)) self.assertEqual(f256(3) * 0, f256(0)) self.assertEqual(f256(3) * 1, f256(3)) self.assertEqual(f256(16) * f256(16), f256(27)) self.assertEqual(f256(32) * f256(16), f256(54)) self.assertEqual(f256(57) * f256(67), f256(137)) self.assertEqual(f256(67) * f256(57), f256(137)) self.assertEqual(f256(137) / f256(57), f256(67)) self.assertEqual(f256(137) / f256(67), f256(57)) a = f256(0) b = f256(1) a += b self.assertEqual(a, f256(1)) a += 1 self.assertEqual(a, f256(0)) a -= b self.assertEqual(a, f256(1)) a *= b self.assertEqual(a, f256(1)) a *= 1 self.assertEqual(a, f256(1)) a /= 1 self.assertEqual(a, f256(1)) a <<= 0 a >>= 0 self.assertEqual(a, f256(1)) a <<= 2 self.assertEqual(a, f256(4)) a >>= 2 self.assertEqual(a, f256(1)) a = f256(3) # generator X + 1 s = [int((a**i).value) for i in range(255)] self.assertListEqual(sorted(s), list(range(1, 256))) s = [int((a**i).value) for i in range(-255, 0)] self.assertListEqual(sorted(s), list(range(1, 256))) f256 = finfields.GF( gfpx.GFpX(2)(391)) # primitive polynomial X^8 + X^7 + X^2 + X + 1 a = f256(2) # generator X s = [int((a**i).value) for i in range(255)] self.assertListEqual(sorted(s), list(range(1, 256))) a = f256(177) self.assertEqual(a.sqrt()**2, a) a = f256(255) self.assertEqual(a.sqrt()**2, a)
def test_mod11(self): poly = gfpx.GFpX(11) self.assertEqual(poly(7)(0), 7) self.assertEqual(poly(11)(17), 6) self.assertEqual(poly(34)(3), 10) self.assertEqual(poly.to_terms(poly(122)), f'{X}^2+1') self.assertEqual(poly.add(poly(9), poly(4)), 2) self.assertEqual(poly.mul(poly(4), poly(2)), 8) self.assertEqual(poly(1) + poly(1), 2) self.assertEqual(poly(1) * poly(2), 2) self.assertEqual(poly(4) + poly(2), 6) self.assertEqual(poly(5) << 2, poly(605)) self.assertEqual(poly(605) >> 2, poly(5)) self.assertEqual(divmod(poly(14641), poly(121)), (poly(121), 0)) self.assertEqual(poly.mod(poly(14643), poly(121)), poly(2)) a = poly(5) b = poly(6) a += b self.assertEqual(a, poly(0)) a -= b self.assertEqual(a, poly(5)) a *= b self.assertEqual(a, poly(8)) a //= b self.assertEqual(a, poly(5)) a <<= 0 self.assertEqual(a, poly(5)) a <<= 1 self.assertEqual(a, poly(55)) a >>= 1 self.assertEqual(a, poly(5)) self.assertEqual(poly.gcd(poly(2), poly(5)), poly(1)) self.assertEqual(poly.gcd(poly(3), poly(5)), poly(1)) self.assertEqual(poly.gcd(poly(455), poly(420)), poly(19)) a = poly('x + 10') # x - 1 b = a**2 * (a - 1)**2 c = a * (a - 2)**2 d, s, t = poly.gcdext(b, c) self.assertEqual(d, a) self.assertEqual(b * s + c * t, a) self.assertTrue(poly.is_irreducible(11)) self.assertFalse(poly.is_irreducible(19487)) self.assertTrue(poly.is_irreducible(19488)) self.assertEqual(poly.next_irreducible(53), 122) self.assertTrue(poly(17) < poly(18)) self.assertTrue(poly(17) <= poly(18)) self.assertTrue(poly(17) >= poly(15)) self.assertTrue(poly(17) > poly(15))
def xGF(p, modulus): """Create a finite field for given irreducible polynomial.""" poly = gfpx.GFpX(p) if not poly.is_irreducible(modulus): raise ValueError('modulus is not irreducible') BaseFieldElement = BinaryFieldElement if p == 2 else ExtensionFieldElement d = poly.deg(modulus) GFElement = type(f'GF({p}^{d})', (BaseFieldElement, ), {'__slots__': ()}) GFElement.modulus = poly(modulus) GFElement.order = p**d GFElement.characteristic = p GFElement.ext_deg = d GFElement.byte_length = (GFElement.order.bit_length() + 7) >> 3 return GFElement
def xGF(modulus): """Create a finite field for given irreducible polynomial.""" p = modulus.p poly = gfpx.GFpX(p) if not poly.is_irreducible(modulus): raise ValueError('modulus is not irreducible') d = poly.deg(modulus) BaseFieldElement = BinaryFieldElement if p == 2 else ExtensionFieldElement GFq = type(f'GF({p}^{d})', (BaseFieldElement, ), {'__slots__': ()}) GFq.__doc__ = f'Class of {"binary" if p == 2 else "extension"} field elements.' GFq.modulus = modulus GFq.order = p**d GFq.characteristic = p GFq.ext_deg = d GFq.byte_length = (GFq.order.bit_length() + 7) >> 3 return GFq
def test_errors(self): self.assertRaises(ValueError, finfields.GF, 4) self.assertRaises(ValueError, finfields.GF, gfpx.GFpX(2)(4)) f2 = self.f2 f2p = self.f2p f256 = self.f256 f19 = self.f19 self.assertRaises(TypeError, operator.add, f2(1), f2p(2)) self.assertRaises(TypeError, operator.iadd, f2(1), f2p(2)) self.assertRaises(TypeError, operator.sub, f2(1), f256(2)) self.assertRaises(TypeError, operator.isub, f2(1), f256(2)) self.assertRaises(TypeError, operator.mul, f2(1), f19(2)) self.assertRaises(TypeError, operator.imul, f2(1), f19(2)) self.assertRaises(TypeError, operator.truediv, f256(1), f19(2)) self.assertRaises(TypeError, operator.itruediv, f256(1), f19(2)) self.assertRaises(TypeError, operator.truediv, 3.14, f19(2)) self.assertRaises(TypeError, operator.lshift, f2(1), f2(1)) self.assertRaises(TypeError, operator.ilshift, f2(1), f2(1)) self.assertRaises(TypeError, operator.lshift, 1, f2(1)) self.assertRaises(TypeError, operator.rshift, f19(1), f19(1)) self.assertRaises(TypeError, operator.irshift, f19(1), f19(1)) self.assertRaises(TypeError, operator.irshift, f256(1), f256(1)) self.assertRaises(TypeError, operator.pow, f2(1), f19(2)) self.assertRaises(TypeError, operator.pow, f19(1), 3.14)
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)
def test_SecFld(self): SecFld = sectypes.SecFld secfld = SecFld() self.assertEqual(secfld.field.modulus, 2) secfld = SecFld(char=2) self.assertEqual(secfld.field.modulus, 2) secfld = SecFld(modulus=f'{X}') self.assertEqual(secfld.field.modulus, 2) secfld = SecFld(modulus=f'{X}+1') self.assertEqual(secfld.field.modulus, 3) secfld = SecFld(min_order=2) self.assertEqual(secfld.field.modulus, 2) secfld = SecFld(min_order=2, char=2) self.assertEqual(secfld.field.modulus, 2) secfld = SecFld(modulus=3, min_order=2) self.assertEqual(secfld.field.modulus, 3) self.assertEqual(secfld.field.order, 3) secfld = SecFld(modulus=3, char=2, min_order=2) self.assertEqual(secfld.field.modulus, 3) self.assertEqual(secfld.field.order, 2) secfld = SecFld(order=3, min_order=2) self.assertEqual(secfld.field.modulus, 3) self.assertEqual(secfld.field.order, 3) secfld = SecFld(order=4, char=2, min_order=4) self.assertEqual(secfld.field.modulus, 7) self.assertEqual(secfld.field.order, 4) secfld = SecFld(modulus=f'1+{X}^8+{X}^4+{X}^3+{X}') self.assertEqual(secfld.field.modulus, 283) # AES polynomial self.assertEqual(secfld.field.order, 256) secfld = SecFld(order=256) self.assertEqual(secfld.field.modulus, 283) # AES polynomial self.assertEqual(secfld.field.order, 256) secfld = SecFld(order=256, modulus=283) self.assertEqual(secfld.field.modulus, 283) # AES polynomial self.assertEqual(secfld.field.order, 256) secfld = SecFld(modulus=283, char=2) self.assertEqual(secfld.field.modulus, 283) # AES polynomial self.assertEqual(secfld.field.order, 256) secfld = SecFld(modulus=gfpx.GFpX(2)(283)) self.assertEqual(secfld.field.modulus, 283) # AES polynomial self.assertEqual(secfld.field.order, 256) secfld(None) secfld(False) secfld(True) secfld(secfld.field(0)) self.assertRaises(TypeError, secfld, float(0)) self.assertRaises(TypeError, secfld, SecFld().field(0)) a = secfld(1) self.assertRaises(TypeError, abs, a) self.assertRaises(TypeError, operator.floordiv, a, a) self.assertRaises(TypeError, operator.floordiv, 1, a) # tests __rfloordiv__ self.assertRaises(TypeError, operator.mod, a, a) self.assertRaises(TypeError, operator.mod, 1, a) # tests __rmod__ self.assertRaises(TypeError, divmod, a, a) self.assertRaises(TypeError, divmod, 1, a) # tests __rdivmod__ self.assertRaises(TypeError, operator.lshift, a, a) self.assertRaises(TypeError, operator.lshift, 1, a) # tests __rlshift__ self.assertRaises(TypeError, operator.rshift, a, a) self.assertRaises(TypeError, operator.rshift, 1, a) # tests __rrshift__ self.assertRaises(TypeError, operator.lt, a, a) # NB: also tests > self.assertRaises(TypeError, operator.le, a, a) # NB: also tests >=
def find_irreducible(p, d): """Find smallest irreducible polynomial of degree d over GF(p).""" # TODO: implement constraints, e.g., low weight, primitive return gfpx.GFpX(p).next_irreducible(p**d - 1)
def setUp(self): self.f2 = finfields.GF(2) self.f19 = finfields.GF(19) self.f27 = finfields.GF(gfpx.GFpX(3)(46)) self.f256 = finfields.GF(gfpx.GFpX(2)(283))