Example #1
0
    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)
Example #2
0
    def encode(cls, m):
        """Encode message m in a quadratic residue."""
        gap = cls.gap
        field = cls.field
        modulus = field.modulus
        for i in range(1, gap):
            if legendre(i, modulus) == 1:
                a = m * gap + i
                if legendre(a, modulus) == 1:
                    M = cls(field(a), check=False)
                    Z = cls(field(i), check=False)
                    return M, Z

        raise ValueError('message encoding failed, try larger gap')
Example #3
0
async def bsgn_1(a):
    """Compute binary sign of a securely.

    Binary sign of a (1 if a>=0 else -1) is obtained by securely computing
    (u+v+w - u*v*w)/2 with u=(2a-1 | p), v=(2a+1 | p), and w=(2a+3 | p).
    """
    stype = type(a)
    await mpc.returnType(stype)
    Zp = stype.field
    p = Zp.modulus
    legendre_p = lambda a: gmpy2.legendre(a.value, p)

    s = mpc.random_bits(Zp, 3, signed=True)  # 3 random signs
    r = mpc._randoms(Zp, 3)
    r = mpc.schur_prod(r, r)  # 3 random squares modulo p
    a, s, r = await mpc.gather(a, s, r)
    y = [b + 2 * i for b in (2 * a + 1, ) for i in (-1, 0, 1)]
    y.append(s[0])
    s.append(s[1])
    r.append(s[2])
    y = await mpc.schur_prod(y, s)
    y = await mpc.schur_prod(y, r)
    y = await mpc.output(y)
    h = [legendre_p(y[i]) for i in range(3)]
    u, v, w = [s[i] * h[i] for i in range(3)]
    uvw = h[0] * h[1] * h[2] * y[3]
    return (u + v + w - uvw) / 2
Example #4
0
async def vector_bsgn_1(x):
    """Compute bsgn_1(a) for all elements a of x in parallel."""
    stype = type(x[0])
    n = len(x)
    await mpc.returnType(stype, n)
    Zp = stype.field
    p = Zp.modulus
    legendre_p = lambda a: gmpy2.legendre(a.value, p)

    s = mpc.random_bits(Zp, 3 * n, signed=True)  # 3n random signs
    r = mpc._randoms(Zp, 3 * n)
    r = mpc.schur_prod(r, r)  # 3n random squares modulo p
    x, s, r = await mpc.gather(x, s, r)
    y = [b + 2 * i for b in (2 * a + 1 for a in x) for i in (-1, 0, 1)]
    y.extend(s[:n])
    s.extend(s[n:2 * n])
    r.extend(s[-n:])
    y = await mpc.schur_prod(y, s)
    y = await mpc.schur_prod(y, r)
    y = await mpc.output(y)
    h = [legendre_p(y[j]) for j in range(3 * n)]
    t = [s[j] * h[j] for j in range(3 * n)]
    z = [
        h[3 * j] * h[3 * j + 1] * h[3 * j + 2] * y[3 * n + j] for j in range(n)
    ]
    q = (p + 1) >> 1  # q = 1/2 mod p
    return [
        Zp((u.value + v.value + w.value - uvw.value) * q)
        for u, v, w, uvw in zip(*[iter(t)] * 3, z)
    ]
Example #5
0
    def sqrt(self, INV=False):
        """Modular (inverse) square roots."""
        a = self.value
        p = type(self).modulus
        if p == 2:
            return type(self)(a)
        if p & 3 == 3:
            if INV:
                q = (3 * p - 5) // 4  # a**q == a**(-1/2) == 1/sqrt(a) mod p
            else:
                q = (p + 1) // 4
            return type(self)(int(gmpy2.powmod(a, q, p)))

        # 1 (mod 4) primes are covered using Cipolla-Lehmer's algorithm.
        # find b s.t. b^2 - 4*a is not a square (maybe cache this for p)
        b = 1
        while gmpy2.legendre(b * b - 4 * a, p) != -1:
            b += 1

        # compute u*X + v = X^{(p+1)/2} mod f, for f = X^2 - b*X + a
        u, v = 0, 1
        e = (p + 1) // 2
        for i in range(e.bit_length() - 1, -1, -1):
            u2 = (u * u) % p
            u = ((u << 1) * v + b * u2) % p
            v = (v * v - a * u2) % p
            if (e >> i) & 1:
                u, v = (v + b * u) % p, (-a * u) % p
        if INV:
            return type(self)(v)._reciprocal()
        else:
            return type(self)(v)
Example #6
0
 def is_sqr(self):
     """Test for quadratic residuosity (0 is also square)."""
     p = type(self).modulus
     if p == 2:
         return True
     else:
         return gmpy2.legendre(self.value, p) != -1
Example #7
0
    def sqrt(self, INV=False):
        a = self.value
        p = self.modulus
        if p == 2:
            return type(self)(a)

        if p & 3 == 3:
            if INV:
                p4 = (p * 3 - 5) >> 2  # a**p4 == a**(-1/2) == 1/sqrt(a) mod p
            else:
                p4 = (p + 1) >> 2
            return type(self)(int(gmpy2.powmod(a, p4, p)))

        # 1 (mod 4) primes are covered using Cipolla-Lehmer's algorithm.
        # find b s.t. b^2 - 4*a is not a square
        b = 1
        while gmpy2.legendre(b * b - 4 * a, p) != -1:
            b += 1

        # compute u*X + v = X^{(p+1)/2} mod f, for f = X^2 - b*X + a
        u, v = 0, 1
        e = (p + 1) >> 1
        for i in range(e.bit_length() - 1, -1, -1):
            u2 = (u * u) % p
            u = ((u << 1) * v + b * u2) % p
            v = (v * v - a * u2) % p
            if (e >> i) & 1:
                u, v = (v + b * u) % p, (-a * u) % p
        if INV:
            return type(self)(v).reciprocal()

        return type(self)(v)
Example #8
0
    def encode(cls, m):
        """Encode message m in x-coordinate of a point on the curve."""
        field = cls.field  # TODO: extend this to non-prime fields
        gap = cls.gap
        modulus = field.modulus
        for i in range(gap):
            x_0 = field(i)
            ysquared_0 = cls.ysquared(x_0)
            if legendre(int(ysquared_0), modulus) == 1:
                x_m = field(m * gap + i)
                ysquared_m = cls.ysquared(x_m)
                if legendre(int(ysquared_m), modulus) == 1:
                    M = cls((x_m, ysquared_m.sqrt()), check=False)
                    Z = cls((x_0, ysquared_0.sqrt()), check=False)
                    return M, Z

        raise ValueError('message encoding failed, try larger gap')
Example #9
0
def _QuadraticResidues(p):
    field = GF(p)  # raises if p is not prime
    g = 2
    while legendre(g, p) != 1:
        g += 1
    # g is generator if p is a safe prime

    l = p.bit_length()
    name = f'QR{l}({p})'
    QR = type(name, (QuadraticResidue,), {'__slots__': ()})
    QR.field = field
    QR.gap = 128  # TODO: calculate gap as a function of bit length of p
    QR.order = p >> 1
    QR.identity = QR()
    QR.generator = QR(g)
    globals()[name] = QR  # NB: exploit (almost?) unique name dynamic QR type
    return QR
Example #10
0
async def vector_bsgn_0(x):
    """Compute bsgn_0(a) for all elements a of x in parallel."""
    stype = type(x[0])
    n = len(x)
    await mpc.returnType(stype, n)
    Zp = stype.field
    p = Zp.modulus
    legendre_p = lambda a: gmpy2.legendre(a.value, p)

    s = mpc.random_bits(Zp, n, signed=True)  # n random signs
    r = mpc._randoms(Zp, n)
    r = mpc.schur_prod(r, r)  # n random squares modulo p
    x, s, r = await mpc.gather(x, s, r)
    y = [2 * a + 1 for a in x]
    y = await mpc.schur_prod(y, s)
    y = await mpc.schur_prod(y, r)
    y = await mpc.output(y)
    return [s[j] * legendre_p(y[j]) for j in range(n)]
Example #11
0
async def vector_bsgn_2(x):
    """Compute bsgn_2(a) for all elements a of x in parallel."""
    stype = type(x[0])
    n = len(x)
    await mpc.returnType(stype, n)
    Zp = stype.field
    p = Zp.modulus
    legendre_p = lambda a: gmpy2.legendre(a.value, p)

    s = mpc.random_bits(Zp, 6*n, signed=True)  # 6n random signs
    r = mpc._randoms(Zp, 6*n)
    r = mpc.schur_prod(r, r)  # 6n random squares modulo p
    x, s, r = await mpc.gather(x, s, r)
    y = [b + 2 * i for b in (2 * a + 1 for a in x) for i in (-2, -1, 0, 1, 2)]
    y = await mpc.schur_prod(y, s[:-n])
    y.extend(s[-n:])
    y = await mpc.schur_prod(y, r)
    y = await mpc.output(y)
    t = [sum(s[5*j + i] * legendre_p(y[5*j + i]) for i in range(5)) for j in range(n)]
    t = await mpc.output(await mpc.schur_prod(t, y[-n:]))
    return [c * legendre_p(d) for c, d in zip(s[-n:], t)]
Example #12
0
async def bsgn_0(a):
    """Compute binary sign of a securely.

    Binary sign of a (1 if a>=0 else -1) is obtained by securely computing (2a+1 | p).

    Legendre symbols (a | p) for secret a are computed securely by evaluating
    (a s r^2 | p) in the clear for secret random sign s and secret random r modulo p,
    and outputting secret s * (a s r^2 | p).
    """
    stype = type(a)
    await mpc.returnType(stype)
    Zp = stype.field
    p = Zp.modulus
    legendre_p = lambda a: gmpy2.legendre(a.value, p)

    s = mpc.random_bits(Zp, 1, signed=True)  # random sign
    r = mpc._random(Zp)
    r = mpc.prod([r, r])  # random square modulo p
    a, s, r = await mpc.gather(a, s, r)
    b = await mpc.prod([2 * a + 1, s[0], r])
    b = await mpc.output(b)
    return s[0] * legendre_p(b)
Example #13
0
    def _sqrt(cls, a, INV=False):
        p = cls.modulus
        if a == 0:
            if INV:
                raise ZeroDivisionError('no inverse sqrt of 0')

            return a

        if p == 2:
            return a

        if p & 3 == 3:
            if INV:
                p4 = (p * 3 - 5) >> 2  # a**p4 == a**(-1/2) == 1/sqrt(a) mod p
            else:
                p4 = (p + 1) >> 2
            return int(gmpy2.powmod(a, p4, p))

        # 1 (mod 4) primes are covered using Cipolla-Lehmer's algorithm.
        # find b s.t. b^2 - 4*a is not a square
        b = 1
        while gmpy2.legendre(b * b - 4 * a, p) != -1:
            b += 1

        # compute u*X + v = X^{(p+1)/2} mod f, for f = X^2 - b*X + a
        u, v = 0, 1
        e = (p + 1) >> 1
        for i in range(e.bit_length() - 1, -1, -1):
            u2 = (u * u) % p
            u = ((u << 1) * v + b * u2) % p
            v = (v * v - a * u2) % p
            if (e >> i) & 1:
                u, v = (v + b * u) % p, (-a * u) % p
        if INV:
            v = cls._reciprocal(v)

        return v
Example #14
0
async def bsgn_2(a):
    """Compute binary sign of a securely.

    Binary sign of a (1 if a>=0 else -1) is obtained by securely computing
    (t | p), with t = sum((2a+1+2i | p) for i=-2,-1,0,1,2).
    """
    stype = type(a)
    await mpc.returnType(stype)
    Zp = stype.field
    p = Zp.modulus
    legendre_p = lambda a: gmpy2.legendre(a.value, p)

    s = mpc.random_bits(Zp, 6, signed=True)  # 6 random signs
    r = mpc._randoms(Zp, 6)
    r = mpc.schur_prod(r, r)  # 6 random squares modulo p
    a, s, r = await mpc.gather(a, s, r)
    y = [b + 2 * i for b in (2 * a + 1, ) for i in (-2, -1, 0, 1, 2)]
    y = await mpc.schur_prod(y, s[:-1])
    y.append(s[-1])
    y = await mpc.schur_prod(y, r)
    y = await mpc.output(y)
    t = sum(s[i] * legendre_p(y[i]) for i in range(5))
    t = await mpc.output(t * y[-1])
    return s[-1] * legendre_p(t)
Example #15
0
    def _is_sqr(cls, a):
        p = cls.modulus
        if p == 2:
            return True

        return gmpy2.legendre(a, p) != -1
Example #16
0
    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)
Example #17
0
    def is_sqr(self):
        p = self.modulus
        if p == 2:
            return True

        return gmpy2.legendre(self.value, p) != -1