summaryrefslogtreecommitdiff
path: root/bcprov/src/test/java/org/bouncycastle/math/test/PrimesTest.java
diff options
context:
space:
mode:
Diffstat (limited to 'bcprov/src/test/java/org/bouncycastle/math/test/PrimesTest.java')
-rw-r--r--bcprov/src/test/java/org/bouncycastle/math/test/PrimesTest.java183
1 files changed, 183 insertions, 0 deletions
diff --git a/bcprov/src/test/java/org/bouncycastle/math/test/PrimesTest.java b/bcprov/src/test/java/org/bouncycastle/math/test/PrimesTest.java
new file mode 100644
index 00000000..13af4cac
--- /dev/null
+++ b/bcprov/src/test/java/org/bouncycastle/math/test/PrimesTest.java
@@ -0,0 +1,183 @@
+package org.bouncycastle.math.test;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.bouncycastle.crypto.Digest;
+import org.bouncycastle.crypto.digests.SHA1Digest;
+import org.bouncycastle.crypto.digests.SHA256Digest;
+import org.bouncycastle.math.Primes;
+import org.bouncycastle.math.Primes.MROutput;
+import org.bouncycastle.math.Primes.STOutput;
+import org.bouncycastle.util.Arrays;
+import org.bouncycastle.util.BigIntegers;
+
+public class PrimesTest extends TestCase
+{
+ private static final int ITERATIONS = 10;
+ private static final int PRIME_BITS = 256;
+ private static final int PRIME_CERTAINTY = 100;
+
+ private static final BigInteger TWO = BigInteger.valueOf(2);
+
+ private static final SecureRandom R = new SecureRandom();
+
+ public void testHasAnySmallFactors()
+ {
+ for (int iterations = 0; iterations < ITERATIONS; ++iterations)
+ {
+ BigInteger prime = randomPrime();
+ assertFalse(Primes.hasAnySmallFactors(prime));
+
+ // NOTE: Loop through ALL small values to be sure no small primes are missing
+ for (int smallFactor = 2; smallFactor <= Primes.SMALL_FACTOR_LIMIT; ++smallFactor)
+ {
+ BigInteger nonPrimeWithSmallFactor = BigInteger.valueOf(smallFactor).multiply(prime);
+ assertTrue(Primes.hasAnySmallFactors(nonPrimeWithSmallFactor));
+ }
+ }
+ }
+
+ public void testEnhancedMRProbablePrime()
+ {
+ int mrIterations = (PRIME_CERTAINTY + 1) / 2;
+ for (int iterations = 0; iterations < ITERATIONS; ++iterations)
+ {
+ BigInteger prime = randomPrime();
+ MROutput mr = Primes.enhancedMRProbablePrimeTest(prime, R, mrIterations);
+ assertFalse(mr.isProvablyComposite());
+ assertFalse(mr.isNotPrimePower());
+ assertNull(mr.getFactor());
+
+ BigInteger primePower = prime;
+ for (int i = 0; i <= (iterations % 8); ++i)
+ {
+ primePower = primePower.multiply(prime);
+ }
+
+ MROutput mr2 = Primes.enhancedMRProbablePrimeTest(primePower, R, mrIterations);
+ assertTrue(mr2.isProvablyComposite());
+ assertFalse(mr2.isNotPrimePower());
+ assertEquals(mr2.getFactor(), prime);
+
+ BigInteger nonPrimePower = randomPrime().multiply(prime);
+ MROutput mr3 = Primes.enhancedMRProbablePrimeTest(nonPrimePower, R, mrIterations);
+ assertTrue(mr3.isProvablyComposite());
+ assertTrue(mr3.isNotPrimePower());
+ assertNull(mr.getFactor());
+ }
+ }
+
+ public void testMRProbablePrime()
+ {
+ int mrIterations = (PRIME_CERTAINTY + 1) / 2;
+ for (int iterations = 0; iterations < ITERATIONS; ++iterations)
+ {
+ BigInteger prime = randomPrime();
+ assertTrue(Primes.isMRProbablePrime(prime, R, mrIterations));
+
+ BigInteger nonPrime = randomPrime().multiply(prime);
+ assertFalse(Primes.isMRProbablePrime(nonPrime, R, mrIterations));
+ }
+ }
+
+ public void testMRProbablePrimeToBase()
+ {
+ int mrIterations = (PRIME_CERTAINTY + 1) / 2;
+ for (int iterations = 0; iterations < ITERATIONS; ++iterations)
+ {
+ BigInteger prime = randomPrime();
+ assertTrue(referenceIsMRProbablePrime(prime, mrIterations));
+
+ BigInteger nonPrime = randomPrime().multiply(prime);
+ assertFalse(referenceIsMRProbablePrime(nonPrime, mrIterations));
+ }
+ }
+
+ public void testSTRandomPrime()
+ {
+ Digest[] digests = new Digest[]{ new SHA1Digest(), new SHA256Digest() };
+ for (int digestIndex = 0; digestIndex < digests.length; ++digestIndex)
+ {
+ int coincidenceCount = 0;
+
+ Digest digest = digests[digestIndex];
+ for (int iterations = 0; iterations < ITERATIONS; ++iterations)
+ {
+ try
+ {
+ byte[] inputSeed = new byte[16];
+ R.nextBytes(inputSeed);
+
+ STOutput st = Primes.generateSTRandomPrime(digest, PRIME_BITS, inputSeed);
+ assertTrue(isPrime(st.getPrime()));
+
+ STOutput st2 = Primes.generateSTRandomPrime(digest, PRIME_BITS, inputSeed);
+ assertEquals(st.getPrime(), st2.getPrime());
+ assertEquals(st.getPrimeGenCounter(), st2.getPrimeGenCounter());
+ assertTrue(Arrays.areEqual(st.getPrimeSeed(), st2.getPrimeSeed()));
+
+ for (int i = 0; i < inputSeed.length; ++i)
+ {
+ inputSeed[i] ^= 0xFF;
+ }
+
+ STOutput st3 = Primes.generateSTRandomPrime(digest, PRIME_BITS, inputSeed);
+ assertTrue(!st.getPrime().equals(st3.getPrime()));
+ assertFalse(Arrays.areEqual(st.getPrimeSeed(), st3.getPrimeSeed()));
+
+ if (st.getPrimeGenCounter() == st3.getPrimeGenCounter())
+ {
+ ++coincidenceCount;
+ }
+ }
+ catch (IllegalStateException e)
+ {
+ if (e.getMessage().startsWith("Too many iterations"))
+ {
+ --iterations;
+ continue;
+ }
+
+ throw e;
+ }
+ }
+
+ assertTrue(coincidenceCount * coincidenceCount < ITERATIONS);
+ }
+ }
+
+ public static Test suite()
+ {
+ return new TestSuite(PrimesTest.class);
+ }
+
+ private static boolean referenceIsMRProbablePrime(BigInteger x, int numBases)
+ {
+ BigInteger xSubTwo = x.subtract(TWO);
+
+ for (int i = 0; i < numBases; ++i)
+ {
+ BigInteger b = BigIntegers.createRandomInRange(TWO, xSubTwo, R);
+ if (!Primes.isMRProbablePrimeToBase(x, b))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private static boolean isPrime(BigInteger x)
+ {
+ return x.isProbablePrime(PRIME_CERTAINTY);
+ }
+
+ private static BigInteger randomPrime()
+ {
+ return BigIntegers.createRandomPrime(PRIME_BITS, PRIME_CERTAINTY, R);
+ }
+}