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 encode(cls, m): """Encode message m in the first coefficient of a form.""" D = cls.discriminant gap = cls.gap assert (m + 1) * gap <= isqrt(-D) / 2 # ensure M (and Z) will be reduced assert gap % 4 == 0 for i in range(0, gap, 4): a_0 = i + 3 b_0 = int(powmod(D, (a_0 + 1) // 4, a_0)) if (b_0**2 - D) % a_0 == 0: # NB: gcd(a_0,b_0)=1 because -D is prime a_m = m * gap + i + 3 b_m = int(powmod(D, (a_m + 1) // 4, a_m)) if (b_m**2 - D) % a_m == 0: # NB: gcd(a_m,b_m)=1 because -D is prime b_m = a_m - b_m if D % 2 != b_m % 2 else b_m c_m = (b_m**2 - D) // (4 * a_m) M = cls((a_m, b_m, c_m), check=False) b_0 = a_0 - b_0 if D % 2 != b_0 % 2 else b_0 c_0 = (b_0**2 - D) // (4 * a_0) Z = cls((a_0, b_0, c_0), check=False) return M, Z # NB: M and Z are reduced raise ValueError('message encoding failed, try larger gap')
def encrypt(g, h, M): """ElGamal encryption.""" group = type(g) n = group.order if n is None: n = isqrt(-group.discriminant) u = random.randrange(n) c = (g ^ u, (h ^ u) @ M) return c
def _class_number(D): # Cohen: Algorithm 5.3.5 """Compute the class number h(D) for squarefree discriminant D < 0, D = 1 (mod 4).""" h = 1 for b in range(1, 1 + isqrt(-D // 3), 2): b2 = b**2 a = max(b, 2) a2 = max(b2, 4) q = (b2 - D) >> 2 while a2 <= q: if q % a == 0: h += 1 if a == b or a2 == q else 2 a2 += (a << 1) | 1 a += 1 return h
async def keygen(g): """Threshold ElGamal key generation.""" group = type(g) secgrp = mpc.SecGrp(group) n = group.order if n is not None and is_prime(n): secnum = mpc.SecFld(n) else: l = isqrt(-group.discriminant).bit_length() secnum = mpc.SecInt(l) while True: x = mpc._random(secnum) h = await secgrp.repeat_public(g, x) # g^x if h != group.identity: # NB: this branch will always be followed unless n is artificially small return x, h
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)