def pGF(modulus, f=0): """Create a finite field for given prime modulus.""" if isinstance(modulus, tuple): p, n, w = modulus else: p = modulus if p == 2: n, w = 1, 1 else: n, w = 2, -1 if not gmpy2.is_prime(p): raise ValueError('modulus is not a prime') GFElement = type(f'GF({p})', (PrimeFieldElement, ), {'__slots__': ()}) GFElement.modulus = p GFElement.order = p GFElement.characteristic = p GFElement.ext_deg = 1 GFElement.byte_length = (GFElement.order.bit_length() + 7) >> 3 GFElement.frac_length = f GFElement.rshift_factor = int(gmpy2.invert(1 << f, p)) # cache (1/2)^f mod p GFElement.is_signed = True GFElement.nth = n GFElement.root = w % p return GFElement
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 GF(modulus, f=0): """Create a Galois (finite) field for given prime modulus.""" if isinstance(modulus, tuple): p, n, w = modulus else: p = modulus if p == 2: n, w = 1, 1 else: n, w = 2, -1 if (p, f) in _field_cache: return _field_cache[(p, f)] if not gmpy2.is_prime(p): raise ValueError(f'{p} is not a prime') GFElement = type(f'GF({p})', (PrimeFieldElement, ), {'__slots__': ()}) GFElement.modulus = p GFElement.order = p GFElement.is_signed = True GFElement.nth = n GFElement.root = w % p GFElement.frac_length = f GFElement.rshift_factor = int(gmpy2.invert(1 << f, p)) # cache (1/2)^f mod p _field_cache[(p, f)] = GFElement return GFElement
def __rshift__(self, other): """Right shift.""" if not isinstance(other, int): return NotImplemented if other == self.frac_length: rsf = self.rshift_factor else: rsf = int(gmpy2.invert(1 << other, self.modulus)) return type(self)(self.value * rsf)
def __irshift__(self, other): if not isinstance(other, int): return NotImplemented if other == self.frac_length: rsf = self.rshift_factor else: rsf = int(gmpy2.invert(1 << other, self.modulus)) self.value *= rsf self.value %= self.modulus return self
def _gcd(cls, a, b): p = cls.p while b: a, b = b, cls._mod(a, b) # ensure monic a if a and a[-1] != 1: a1 = int(gmpy2.invert(a[-1], p)) for i in range(len(a) - 1): a[i] *= a1 a[i] %= p a[-1] = 1 return a
def verify(self, M, S): """DSA signature verification.""" g = self.group.generator q = self.group.order H = self.H y = self.y r, s = S if not (0 < r < q and 0 < s < q): return False w = int(invert(s, q)) # s^-1 mod q u_1 = H(M)*w % q u_2 = r*w % q v = self.to_int((g^u_1) @ (y^u_2)) % q return v == r
def _invert(cls, a, b): p = cls.p if b == []: raise ZeroDivisionError('division by zero polynomial') s, s1 = [1], [] while b: a, (q, b) = b, cls._divmod(a, b) s, s1 = s1, cls._sub(s, cls._mul(q, s1)) if len(a) != 1: raise ZeroDivisionError('inverse does not exist') # ensure monic a a1 = int(gmpy2.invert(a[0], p)) for i in range(len(s)): s[i] *= a1 s[i] %= p return s
def pGF(p, f, n, w): """Create a finite field for given prime modulus p.""" if not gmpy2.is_prime(p): raise ValueError('modulus is not a prime') GFp = type(f'GF({p})', (PrimeFieldElement, ), {'__slots__': ()}) GFp.__doc__ = 'Class of prime field elements.' GFp.modulus = p GFp.order = p GFp.characteristic = p GFp.ext_deg = 1 GFp.byte_length = (GFp.order.bit_length() + 7) >> 3 GFp._frac_length = f GFp._rshift_factor = int(gmpy2.invert(1 << f, p)) # cache (1/2)^f mod p GFp.is_signed = True GFp.nth = n GFp.root = w % p return GFp
def _divmod(cls, a, b): p = cls.p if b == []: raise ZeroDivisionError('division by zero polynomial') m = len(a) n = len(b) if m < n: return [], a[:] b1 = int(gmpy2.invert(b[-1], p)) q, r = [0] * (m - n + 1), a[:] for i in range(m - n, -1, -1): if len(r) >= i + n: q[i] = q_i = (r[-1] * b1) % p for j in range(n): r[i + j] -= q_i * b[j] r[i + j] %= p while r and not r[-1]: r.pop() return q, r
def _gcdext(cls, a, b): p = cls.p s, s1 = [1], [] t, t1 = [], [1] while b: a, (q, b) = b, cls._divmod(a, b) s, s1 = s1, cls._sub(s, cls._mul(q, s1)) t, t1 = t1, cls._sub(t, cls._mul(q, t1)) # ensure monic a if a and a[-1] != 1: a1 = int(gmpy2.invert(a[-1], p)) for i in range(len(a) - 1): a[i] *= a1 a[i] %= p a[-1] = 1 for i in range(len(s)): s[i] *= a1 s[i] %= p for i in range(len(t)): t[i] *= a1 t[i] %= p return a, s, t
def _mod(cls, a, b): p = cls.p if b is None: # see _powmod() return a # NB: in-place if b == []: raise ZeroDivisionError('division by zero polynomial') m = len(a) n = len(b) if m < n: return a[:] b1 = int(gmpy2.invert(b[-1], p)) r = a[:] for i in range(m - n, -1, -1): if len(r) >= i + n: q_i = (r[-1] * b1) % p for j in range(n): r[i + j] -= q_i * b[j] r[i + j] %= p while r and not r[-1]: r.pop() return r
def reciprocal(self): """Multiplicative inverse.""" return type(self)(int(gmpy2.invert(self.value, self.modulus)))
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)
def _reciprocal(cls, a): return int(gmpy2.invert(a, cls.modulus))