/* * 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); }