예제 #1
0
        /*
         * Test an integer for primality. This function runs up to 50
         * Miller-Rabin rounds, which is a lot of overkill but ensures
         * that non-primes will be reliably detected (with overwhelming
         * probability) even with maliciously crafted inputs. "Normal"
         * non-primes will be detected most of the time at the first
         * iteration.
         *
         * This function is not constant-time.
         */
        public static bool IsPrime(byte[] x)
        {
            x = NormalizeBE(x);

            /*
             * Handle easy cases:
             *   0 is not prime
             *   small primes (one byte) are known in a constant bit-field
             *   even numbers (larger than one byte) are non-primes
             */
            if (x.Length == 0)
            {
                return(false);
            }
            if (x.Length == 1)
            {
                return(IsSmallPrime(x[0]));
            }
            if ((x[x.Length - 1] & 0x01) == 0)
            {
                return(false);
            }

            /*
             * Perform some trial divisions by small primes.
             */
            for (int sp = 3; sp < 256; sp += 2)
            {
                if (!IsSmallPrime(sp))
                {
                    continue;
                }
                int z = 0;
                foreach (byte b in x)
                {
                    z = ((z << 8) + b) % sp;
                }
                if (z == 0)
                {
                    return(false);
                }
            }

            /*
             * Run some Miller-Rabin rounds. We use as basis random
             * integers that are one byte smaller than the modulus.
             */
            ModInt xm1 = new ModInt(x);
            ModInt y   = xm1.Dup();

            y.Set(1);
            xm1.Sub(y);
            byte[] e = xm1.Encode();
            ModInt a = new ModInt(x);

            byte[] buf = new byte[x.Length - 1];
            for (int i = 0; i < 50; i++)
            {
                RNG.GetBytes(buf);
                a.Decode(buf);
                a.Pow(e);
                if (!a.IsOne)
                {
                    return(false);
                }
            }
            return(true);
        }