def ClassGroup(Delta=None, l=None): """Create type for class group, given (bit length l of) discriminant Delta. The following conditions are imposed on discriminant Delta: - Delta < 0, only supporting class groups of imaginary quadratic field - Delta = 1 (mod 4), preferably Delta = 1 (mod 8) - -Delta is prime This implies that Delta is a fundamental discriminant. """ if l is not None: if Delta is None: # find fundamental discriminant Delta of bit length l >= 2 p = next_prime(1 << l-1) while p != 3 and p != 11 and p%8 != 7: p = next_prime(p) Delta = int(-p) # D = 1 mod 4, and even D = 1 mod 8 if possible (and -D is prime) elif Delta is None: Delta = -3 if Delta%4 != 1: raise ValueError('discriminant required to be 1 modulo 4, preferably 1 modulo 8') if Delta >= 0 or not is_prime(-Delta): raise ValueError('negative prime discriminant required') return _ClassGroup(Delta)
def test_basic(self): self.assertFalse(gmpy.is_prime(1)) self.assertTrue(gmpy.is_prime(2)) self.assertTrue(gmpy.is_prime(101)) self.assertFalse(gmpy.is_prime(561)) self.assertTrue(gmpy.is_prime(2**16 + 1)) self.assertFalse(gmpy.is_prime(41041)) self.assertEqual(gmpy.next_prime(1), 2) self.assertEqual(gmpy.next_prime(2), 3) self.assertEqual(gmpy.next_prime(256), 257) self.assertEqual(gmpy.powmod(3, 256, 257), 1) self.assertEqual(gmpy.invert(3, 257), 86) self.assertRaises(ZeroDivisionError, gmpy.invert, 2, 4) self.assertEqual(gmpy.legendre(0, 101), 0) self.assertEqual(gmpy.legendre(42, 101), -1) self.assertEqual(gmpy.legendre(54, 101), 1) self.assertTrue(gmpy.is_square(625)) self.assertFalse(gmpy.is_square(652)) self.assertEqual(gmpy.isqrt(0), 0) self.assertEqual(gmpy.isqrt(1225), 35) self.assertTrue(gmpy.iroot(0, 10)[1]) self.assertFalse(gmpy.iroot(1226, 2)[1]) self.assertEqual(gmpy.iroot(1226, 2)[0], 35) self.assertEqual(gmpy.iroot(3**10 + 42, 10)[0], 3)
def find_prime_root(l, blum=True, n=1): """Find smallest prime of bit length l satisfying given constraints. Default is to return Blum primes (primes p with p % 4 == 3). Also, a primitive root w is returned of prime order at least n. """ if l == 1: assert not blum assert n == 1 p = 2 w = 1 elif n <= 2: n = 2 w = -1 p = gmpy2.next_prime(2**(l - 1)) if blum: while p % 4 != 3: p = gmpy2.next_prime(p) p = int(p) else: assert blum if not gmpy2.is_prime(n): n = int(gmpy2.next_prime(n)) p = 1 + n * (1 + (n**2) % 4 + 4 * ((2**(l - 2)) // n)) while not gmpy2.is_prime(p): p += 4 * n a = 1 w = 1 while w == 1: a += 1 w = gmpy2.powmod(a, (p - 1) // n, p) p, w = int(p), int(w) return p, n, w
def find_prime_root(l, blum=True, n=1): """Find smallest prime of bit length at least l satisfying given constraints. Default is to return Blum primes (primes p with p % 4 == 3). Also, a primitive root w is returned of prime order at least n (0 < w < p). """ if l <= 2: if not blum: p = 2 assert n == 1 w = 1 else: p = 3 n, w = 2, p - 1 elif n <= 2: p = gmpy2.next_prime(1 << l - 1) if blum: while p % 4 != 3: p = gmpy2.next_prime(p) p = int(p) w = p - 1 if n == 2 else 1 else: assert blum if not gmpy2.is_prime(n): n = gmpy2.next_prime(n) p = 1 + 2 * n * (3 + 2 * ((1 << l - 3) // n)) while not gmpy2.is_prime(p): p += 4 * n a = 2 while (w := gmpy2.powmod(a, (p - 1) // n, p)) == 1: a += 1 p, w = int(p), int(w)
def _find_safe_prime(l): """Find safe prime p of bit length l, l>=2. Hence, q=(p-1)/2 is also prime (except when l=2 and p=3). It is also ensured that p=3 (mod 4), hence p is a Blum prime. """ IKE_options_l_k = { 768: 149686, 1024: 129093, 1536: 741804, 2048: 124476, 3072: 1690314, 4096: 240904, 6144: 929484, 8192: 4743158 } if l in IKE_options_l_k: # Compute pi to the required precision. decimal.setcontext(decimal.Context(prec=round(l / math.log2(10)))) # See https://docs.python.org/3/library/decimal.html for following recipe: decimal.getcontext().prec += 2 # extra digits for intermediate steps three = decimal.Decimal(3) lasts, t, s, n, na, d, da = 0, three, 3, 1, 0, 0, 24 while s != lasts: lasts = s n, na = n + na, na + 8 d, da = d + da, da + 32 t = (t * n) / d s += t decimal.getcontext().prec -= 2 pi_l = +s # NB: unary plus applies the new precision # Following https://kivinen.iki.fi/primes to compute IKE prime p: k = IKE_options_l_k[l] fixedbits = 64 epi = math.floor(pi_l * 2**(l - 2 * fixedbits - 2)) + k p = 2**l - 2**(l - fixedbits) - 1 + epi * 2**fixedbits else: if l == 2: p = 3 else: q = next_prime(1 << l - 2) while not is_prime(2 * q + 1): q = next_prime(q) # q is a Sophie Germain prime p = int(2 * q + 1) return p
def SchnorrGroup(p=None, q=None, g=None, l=None, n=None): """Create type for Schnorr group of odd prime order q. If q is not given, q will be the smallest n-bit prime, n>=2. If p is not given, p will be the least l-bit prime, l>n, such that q divides p-1. If l and/or n are not given, default bit lengths will be set (2<=n<l). """ n_l = ((160, 1024), (192, 1536), (224, 2048), (256, 3072), (384, 7680)) if p is None: if q is None: if n is None: if l is None: l = 2048 n = next((n for n, _ in n_l if _ >= l), 512) q = next_prime(1 << n-1) else: if n is None: n = q.bit_length() assert q%2 and is_prime(q) if l is None: l = next((l for _, l in n_l if _ >= n), 15360) # n-bit prime q w = (1 << l-2) // q + 1 # w*q >= 2^(l-2), so p = 2*w*q + 1 > 2^(l-1) p = 2*w*q + 1 while not is_prime(p): p += 2*q # 2^(l-1) < p < 2^l else: assert q is not None # if p is given, q must be given as well assert (p - 1) % q == 0 assert q%2 and is_prime(q) assert is_prime(p) if l is None: l = p.bit_length() if n is None: n = q.bit_length() assert l == p.bit_length() assert n == q.bit_length() p = int(p) q = int(q) if g is None: w = (p-1) // q i = 2 while True: g = powmod(i, w, p) if g != 1 and powmod(g, q, p) == 1: break i += 1 g = int(g) return _SchnorrGroup(p, q, g)
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_basic(self): self.assertFalse(gmpy.is_prime(1)) self.assertTrue(gmpy.is_prime(2)) self.assertTrue(gmpy.is_prime(101)) self.assertFalse(gmpy.is_prime(561)) self.assertTrue(gmpy.is_prime(2**16 + 1)) self.assertFalse(gmpy.is_prime(41041)) self.assertEqual(gmpy.next_prime(1), 2) self.assertEqual(gmpy.next_prime(2), 3) self.assertEqual(gmpy.next_prime(256), 257) self.assertEqual(gmpy.powmod(3, 256, 257), 1) self.assertEqual(gmpy.gcdext(3, 257), (1, 86, -1)) self.assertEqual(gmpy.gcdext(1234, 257), (1, -126, 605)) self.assertEqual(gmpy.gcdext(-1234 * 3, -257 * 3), (3, 126, -605)) def te_s_t(a, b): g, s, t = gmpy.gcdext(a, b) if abs(a) == abs(b): test_s = s == 0 elif b == 0 or abs(b) == 2 * g: test_s = s == bool(a > 0) - bool(a < 0) # sign of a else: test_s = abs(s) < abs(b) / (2 * g) if abs(a) == abs(b) or a == 0 or abs(a) == 2 * g: test_t = t == bool(b > 0) - bool(b < 0) # sign of b else: test_t = abs(t) < abs(a) / (2 * g) return g == a * s + b * t and test_s and test_t self.assertTrue( all((te_s_t(0, 0), te_s_t(0, -1), te_s_t(1, 0), te_s_t(-1, 1)))) self.assertTrue(te_s_t(-1234, 257)) self.assertTrue(te_s_t(-12537, -257)) self.assertTrue(te_s_t(-11 * 1234, -11 * 2567)) self.assertTrue(te_s_t(1234, -2 * 1234)) self.assertTrue(te_s_t(-2 * 12364, 12364)) # self.assertEqual(gmpy.invert(3, -1), 0) # pending gmpy2 issue if modulus is 1 or -1 self.assertEqual(gmpy.invert(3, 257), 86) self.assertRaises(ZeroDivisionError, gmpy.invert, 2, 0) self.assertRaises(ZeroDivisionError, gmpy.invert, 2, 4) self.assertEqual(gmpy.legendre(0, 101), 0) self.assertEqual(gmpy.legendre(42, 101), -1) self.assertEqual(gmpy.legendre(54, 101), 1) self.assertRaises(ValueError, gmpy.legendre, 1, 2) self.assertEqual(gmpy.jacobi(9, 99), 0) self.assertEqual(gmpy.jacobi(43, 99), -1) self.assertEqual(gmpy.jacobi(53, 99), 1) self.assertRaises(ValueError, gmpy.jacobi, 1, 20) self.assertEqual(gmpy.kronecker(0, 0), 0) self.assertEqual(gmpy.kronecker(-1, 0), 1) self.assertEqual(gmpy.kronecker(43, -98), -1) self.assertEqual(gmpy.kronecker(-53, -98), 1) self.assertEqual(gmpy.kronecker(-54, -98), 0) self.assertTrue(gmpy.is_square(625)) self.assertFalse(gmpy.is_square(652)) self.assertEqual(gmpy.isqrt(0), 0) self.assertEqual(gmpy.isqrt(1225), 35) self.assertTrue(gmpy.iroot(0, 10)[1]) self.assertFalse(gmpy.iroot(1226, 2)[1]) self.assertEqual(gmpy.iroot(1226, 2)[0], 35) self.assertEqual(gmpy.iroot(3**10 + 42, 10)[0], 3)