예제 #1
0
        /// <summary>
        /// Finds modular square root r such that r^2≡a (mod p) for a &#60; p and p is the secp256k1 prime (p%4 = 3).
        /// Return value indicates success.
        /// </summary>
        /// <param name="a"></param>
        /// <param name="p">Secp256k1 prime</param>
        /// <param name="result">Result if square root exists</param>
        /// <returns>True if the square root exists; false if otherwise.</returns>
        public static bool TryFind(BigInteger a, BigInteger p, out BigInteger result)
        {
            if (Legendre.Symbol(a, p) != 1)
            {
                return(false);
            }

            result = BigInteger.ModPow(a, (p + 1) / 4, p);
            return(true);
        }
예제 #2
0
        private static BigInteger TonelliShanks(BigInteger a, BigInteger p)
        {
            if (a >= p)
            {
                throw new ArithmeticException("The residue, 'a' cannot be greater than the modulus 'p'!");
            }
            if (Legendre.Symbol(a, p) != 1) // a^(p-1 / 2) % p == p-1
            {
                throw new ArithmeticException($"Parameter 'a' is not a quadratic residue, mod 'p'");
            }
            // This will be true for secp256k1 curve prime
            if (p % 4 == 3)
            {
                return(BigInteger.ModPow(a, (p + 1) / 4, p));
            }

            //Initialize
            BigInteger s = p - 1;
            BigInteger e = 0;

            while (s % 2 == 0)
            {
                s /= 2;
                e += 1;
            }

            BigInteger n = FindGenerator(p);

            BigInteger x = BigInteger.ModPow(a, (s + 1) / 2, p);
            BigInteger b = BigInteger.ModPow(a, s, p);
            BigInteger g = BigInteger.ModPow(n, s, p);
            BigInteger r = e;
            BigInteger m = Order(b, p);

            if (m == 0)
            {
                return(x);
            }

            while (m > 0)
            {
                x = (x * BigInteger.ModPow(g, TwoExp(r - m - 1), p)) % p;
                b = (b * BigInteger.ModPow(g, TwoExp(r - m), p)) % p;
                g = BigInteger.ModPow(g, TwoExp(r - m), p);
                r = m;
                m = Order(b, p);
            }

            return(x);
        }