예제 #1
0
def test_minus_one_quadr_res() -> None:
    "Ensure that if p = 3 (mod 4) then p - 1 is not a quadratic residue"
    for p in primes:
        if (p % 4) == 3:
            with pytest.raises(ValueError, match="no root for "):
                mod_sqrt(p - 1, p)
        else:
            assert p == 2 or p % 4 == 1, "something is badly broken"
            root = mod_sqrt(p - 1, p)
            assert p - 1 == root * root % p
예제 #2
0
 def y(self, x: int, odd1even0: int) -> int:
     assert odd1even0 in (0, 1), "must be bool or 0/1"
     y2 = self.__y2(x)
     # if root does not exist, mod_sqrt will raise a ValueError
     root = mod_sqrt(y2, self.__prime)
     # switch even/odd root when needed
     return root if (root % 2 + odd1even0) != 1 else self.__prime - root
예제 #3
0
 def test_mod_sqrt(self):
     for p in primes[:30]:  # exhaustable only for small p
         hasRoot = set()
         hasRoot.add(0)
         hasRoot.add(1)
         for i in range(2, p):
             hasRoot.add(i * i % p)
         for i in range(p):
             if i in hasRoot:
                 root = mod_sqrt(i, p)
                 self.assertEqual(i, (root * root) % p)
                 root = p - root
                 self.assertEqual(i, (root * root) % p)
                 root = mod_sqrt(i + p, p)
                 self.assertEqual(i, (root * root) % p)
             else:
                 self.assertRaises(ValueError, mod_sqrt, i, p)
예제 #4
0
 def yLow(self, x: int, low1high0: int) -> int:
     assert low1high0 in (0, 1), "must be bool or 0/1"
     y2 = self.__y2(x)
     if y2 == 0: return 0
     # if root does not exist, mod_sqrt will raise a ValueError
     root = mod_sqrt(y2, self.__p)
     # switch low/high root when needed
     return root if (root < self.__p / 2) else self.__p - root
예제 #5
0
 def test_minus_one_quadr_res(self):
     """Ensure that if p = 3 (mod 4) then p - 1 is not a quadratic residue"""
     for p in primes:
         if (p % 4) == 3:
             self.assertRaises(ValueError, mod_sqrt, p - 1, p)
         else:
             assert p == 2 or p % 4 == 1, "something is badly broken"
             root = mod_sqrt(p - 1, p)
             self.assertEqual(p - 1, root * root % p)
예제 #6
0
def test_mod_sqrt() -> None:
    for p in primes[:30]:  # exhaustable only for small p
        has_root = {0, 1}
        for i in range(2, p):
            has_root.add(i * i % p)
        for i in range(p):
            if i in has_root:
                root1 = mod_sqrt(i, p)
                assert i == (root1 * root1) % p
                root2 = p - root1
                assert i == (root2 * root2) % p
                root = mod_sqrt(i + p, p)
                assert i == (root * root) % p
                if p % 4 == 3 or p % 8 == 5:
                    assert tonelli(i, p) in (root1, root2)
            else:
                with pytest.raises(ValueError, match="no root for "):
                    mod_sqrt(i, p)
예제 #7
0
 def yQuadraticResidue(self, x: int, quadres: int) -> int:
     assert quadres in (0, 1), "must be bool or 0/1"
     y2 = self.__y2(x)
     if y2 == 0: return 0
     # if root does not exist, mod_sqrt will raise a ValueError
     root = mod_sqrt(y2, self.__p)
     # switch to the quadratic residue root when needed
     if quadres:
         return self.__p - root if (self.jacobi(root) != 1) else root
     else:
         return root if (self.jacobi(root) != 1) else self.__p - root
 def test_mod_sqrt(self):
     for p in [3, 5, 7, 11, 13, 17, 19, 23, 29]:
         hasRoot = set()
         hasRoot.add(1)
         for i in range(2, p):
             hasRoot.add(i * i % p)
         for i in range(1, p):
             if i in hasRoot:
                 root = mod_sqrt(i, p)
                 self.assertEqual(i, (root * root) % p)
                 root = p - root
                 self.assertEqual(i, (root * root) % p)
             else:
                 self.assertRaises(ValueError, mod_sqrt, i, p)
 def test_minus_one_quadr_res(self):
     for p in [3, 5, 7, 11, 13, 17, 19, 23, 29]:
         hasRoot = set()
         hasRoot.add(1)
         for i in range(2, p):
             hasRoot.add(i * i % p)
         if (p % 4) == 3:
             self.assertNotIn(p - 1, hasRoot)
             self.assertRaises(ValueError, mod_sqrt, p - 1, p)
         else:
             assert p % 4 == 1
             self.assertIn(p - 1, hasRoot)
             root = mod_sqrt(p - 1, p)
             self.assertEqual(p - 1, root * root % p)
예제 #10
0
    def test_symmetry(self):
        """Methods to break simmetry: quadratic residue, odd/even, low/high"""
        for ec in low_card_curves:

            # setup phase
            # compute quadratic residues
            hasRoot = set()
            hasRoot.add(1)

            for i in range(2, ec._p):
                hasRoot.add(i*i % ec._p)

            # test phase
            Q = mult(ec, ec._p, ec.G)  # just a random point, not Inf
            x = Q[0]
            if ec._p % 4 == 3:
                quad_res = ec.y_quadratic_residue(x, True)
                not_quad_res = ec.y_quadratic_residue(x, False)
                # in this case only quad_res is a quadratic residue
                self.assertIn(quad_res, hasRoot)
                root = mod_sqrt(quad_res, ec._p)
                self.assertEqual(quad_res, (root*root) % ec._p)
                root = ec._p - root
                self.assertEqual(quad_res, (root*root) % ec._p)

                self.assertTrue(not_quad_res == ec._p - quad_res)
                self.assertNotIn(not_quad_res, hasRoot)
                self.assertRaises(ValueError, mod_sqrt, not_quad_res, ec._p)

                y_odd = ec.y_odd(x, True)
                self.assertTrue(y_odd in (quad_res, not_quad_res))
                self.assertTrue(y_odd % 2 == 1)
                y_even = ec.y_odd(x, False)
                self.assertTrue(y_even in (quad_res, not_quad_res))
                self.assertTrue(y_even % 2 == 0)

                y_low = ec.y_low(x, True)
                self.assertTrue(y_low in (y_odd, y_even))
                y_high = ec.y_low(x, False)
                self.assertTrue(y_high in (y_odd, y_even))
                self.assertTrue(y_low < y_high)
            else:
                self.assertTrue(ec._p % 4 == 1)
                # cannot use y_quadratic_residue in this case
                self.assertRaises(ValueError, ec.y_quadratic_residue, x, True)
                self.assertRaises(ValueError, ec.y_quadratic_residue, x, False)

                y_odd = ec.y_odd(x, True)
                self.assertTrue(y_odd % 2 == 1)
                y_even = ec.y_odd(x, False)
                self.assertTrue(y_even % 2 == 0)
                # in this case neither or both are quadratic residues
                self.assertTrue((y_odd in hasRoot and y_even in hasRoot) or
                                (y_odd not in hasRoot and y_even not in hasRoot))
                if y_odd in hasRoot:  # both have roots
                    root = mod_sqrt(y_odd, ec._p)
                    self.assertEqual(y_odd, (root*root) % ec._p)
                    root = ec._p - root
                    self.assertEqual(y_odd, (root*root) % ec._p)
                    root = mod_sqrt(y_even, ec._p)
                    self.assertEqual(y_even, (root*root) % ec._p)
                    root = ec._p - root
                    self.assertEqual(y_even, (root*root) % ec._p)
                else:
                    self.assertRaises(ValueError, mod_sqrt, y_odd, ec._p)
                    self.assertRaises(ValueError, mod_sqrt, y_even, ec._p)

                y_low = ec.y_low(x, True)
                self.assertTrue(y_low in (y_odd, y_even))
                y_high = ec.y_low(x, False)
                self.assertTrue(y_high in (y_odd, y_even))
                self.assertTrue(y_low < y_high)
        
        # with the last curve
        self.assertRaises(ValueError, ec.y_low, x, 2)
        self.assertRaises(ValueError, ec.y_odd, x, 2)
        self.assertRaises(ValueError, ec.y_quadratic_residue, x, 2)
예제 #11
0
def test_symmetry() -> None:
    """Methods to break simmetry: quadratic residue, odd/even, low/high"""
    for ec in low_card_curves.values():

        # just a random point, not INF
        q = 1 + secrets.randbelow(ec.n - 1)
        Q = mult(q, ec.G, ec)
        x_Q = Q[0]

        y_odd = ec.y_odd(x_Q)
        assert y_odd % 2 == 1
        y_even = ec.y_odd(x_Q, False)
        assert y_even % 2 == 0
        assert y_even == ec.p - y_odd

        y_low = ec.y_low(x_Q)
        y_high = ec.y_low(x_Q, False)
        assert y_low < y_high
        assert y_high == ec.p - y_low

        # compute quadratic residues
        hasRoot = {1}
        for i in range(2, ec.p):
            hasRoot.add(i * i % ec.p)

        if ec.p % 4 == 3:
            quad_res = ec.y_quadratic_residue(x_Q)
            not_quad_res = ec.y_quadratic_residue(x_Q, False)

            # in this case only quad_res is a quadratic residue
            assert quad_res in hasRoot
            root = mod_sqrt(quad_res, ec.p)
            assert quad_res == (root * root) % ec.p
            root = ec.p - root
            assert quad_res == (root * root) % ec.p

            assert not_quad_res == ec.p - quad_res
            assert not_quad_res not in hasRoot
            with pytest.raises(ValueError, match="no root for "):
                mod_sqrt(not_quad_res, ec.p)
        else:
            assert ec.p % 4 == 1
            # cannot use y_quadratic_residue in this case
            err_msg = "field prime is not equal to 3 mod 4: "
            with pytest.raises(ValueError, match=err_msg):
                ec.y_quadratic_residue(x_Q)
            with pytest.raises(ValueError, match=err_msg):
                ec.y_quadratic_residue(x_Q, False)

            # in this case neither or both y_Q are quadratic residues
            neither = y_odd not in hasRoot and y_even not in hasRoot
            both = y_odd in hasRoot and y_even in hasRoot
            assert neither or both
            if y_odd in hasRoot:  # both have roots
                root = mod_sqrt(y_odd, ec.p)
                assert y_odd == (root * root) % ec.p
                root = ec.p - root
                assert y_odd == (root * root) % ec.p
                root = mod_sqrt(y_even, ec.p)
                assert y_even == (root * root) % ec.p
                root = ec.p - root
                assert y_even == (root * root) % ec.p
            else:
                err_msg = "no root for "
                with pytest.raises(ValueError, match=err_msg):
                    mod_sqrt(y_odd, ec.p)
                with pytest.raises(ValueError, match=err_msg):
                    mod_sqrt(y_even, ec.p)

    # with the last curve
    with pytest.raises(ValueError, match="low1high0 must be bool or 1/0"):
        ec.y_low(x_Q, 2)
    with pytest.raises(ValueError, match="odd1even0 must be bool or 1/0"):
        ec.y_odd(x_Q, 2)
    with pytest.raises(ValueError, match="quad_res must be bool or 1/0"):
        ec.y_quadratic_residue(x_Q, 2)
예제 #12
0
def test_symmetry() -> None:
    "Methods to break simmetry: quadratic residue, even/odd, low/high."
    for ec in low_card_curves.values():

        # just a random point, not INF
        q = 1 + secrets.randbelow(ec.n - 1)
        Q = mult(q, ec.G, ec)
        x_Q = Q[0]

        assert not ec.y_even(x_Q) % 2
        assert ec.y_low(x_Q) <= ec.p // 2

        # compute quadratic residues
        hasRoot = {1}
        for i in range(2, ec.p):
            hasRoot.add(i * i % ec.p)

        if ec.p % 4 == 3:
            quad_res = ec.y_quadratic_residue(x_Q)

            # in this case only quad_res is a quadratic residue
            assert quad_res in hasRoot
            root = mod_sqrt(quad_res, ec.p)
            assert quad_res == (root * root) % ec.p
            root = ec.p - root
            assert quad_res == (root * root) % ec.p

            assert ec.p - quad_res not in hasRoot
            with pytest.raises(BTClibValueError, match="no root for "):
                mod_sqrt(ec.p - quad_res, ec.p)
        else:
            assert ec.p % 4 == 1
            # cannot use y_quadratic_residue in this case
            err_msg = "field prime is not equal to 3 mod 4: "
            with pytest.raises(BTClibValueError, match=err_msg):
                ec.y_quadratic_residue(x_Q)

            y_even = ec.y_even(x_Q)
            y_odd = ec.p - y_even
            # in this case neither or both y_Q are quadratic residues
            neither = y_odd not in hasRoot and y_even not in hasRoot
            both = y_odd in hasRoot and y_even in hasRoot
            assert neither or both
            if y_odd in hasRoot:  # both have roots
                root = mod_sqrt(y_odd, ec.p)
                assert y_odd == (root * root) % ec.p
                root = ec.p - root
                assert y_odd == (root * root) % ec.p
                root = mod_sqrt(y_even, ec.p)
                assert y_even == (root * root) % ec.p
                root = ec.p - root
                assert y_even == (root * root) % ec.p
            else:
                err_msg = "no root for "
                with pytest.raises(BTClibValueError, match=err_msg):
                    mod_sqrt(y_odd, ec.p)
                with pytest.raises(BTClibValueError, match=err_msg):
                    mod_sqrt(y_even, ec.p)

    with pytest.raises(BTClibValueError):
        secp256k1.y_even(INF[0])
    with pytest.raises(BTClibValueError):
        secp256k1.y_low(INF[0])
    with pytest.raises(BTClibValueError):
        secp256k1.y_quadratic_residue(INF[0])
예제 #13
0
 def y(self, x: int) -> int:
     if not 0 <= x < self._p:
         raise ValueError(f"x-coordinate {hex(x)} not in [0, p-1]")
     y2 = self._y2(x)
     # mod_sqrt will raise a ValueError if root does not exist
     return mod_sqrt(y2, self._p)
예제 #14
0
 maxordera = -1
 maxorderb = -1
 maxorderlessthanprime = 0
 maxorderlessthanprimea = -1
 maxorderlessthanprimeb = -1
 for a in range(200):
     for b in range(200):
         order = 0
         for x in range(prime):
             y2 = ((x * x + a) * x + b) % prime
             if y2 == 0:
                 order += 1
                 # print("#", order+1, " ", x, ", ", 0, "  #####", sep="")
                 continue
             try:
                 y = mod_sqrt(y2, prime)
                 assert (y * y) % prime == y2
                 # print("#", order+1, " ", x, ",", y, sep="")
                 # print("#", order+2, " ", x, ",", prime-y, sep="")
                 order += 2
             except Exception:
                 continue
         order += 1
         if isprime(order):
             # print(a, b, prime, "gen", order)
             if order > maxorder:
                 maxorder = order
                 maxordera = a
                 maxorderb = b
             if order > maxorderlessthanprime and order < prime:
                 maxorderlessthanprime = order