All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bouncycastle.tls.crypto.impl.jcajce.Primes Maven / Gradle / Ivy

Go to download

The Bouncy Castle Java APIs for the TLS, including a JSSE provider. The APIs are designed primarily to be used in conjunction with the BC FIPS provider. The APIs may also be used with other providers although if being used in a FIPS context it is the responsibility of the user to ensure that any other providers used are FIPS certified and used appropriately.

There is a newer version: 2.0.19
Show newest version
package org.bouncycastle.tls.crypto.impl.jcajce;

import java.math.BigInteger;
import java.security.SecureRandom;

import org.bouncycastle.util.BigIntegers;

/**
 * Utility methods for generating primes and testing for primality.
 */
abstract class Primes
{
    private static final BigInteger ONE = BigInteger.valueOf(1);
    private static final BigInteger TWO = BigInteger.valueOf(2);

    /**
     * A fast check for small divisors, up to some implementation-specific limit.
     *
     * @param candidate
     *            the {@link BigInteger} instance to test for division by small factors.
     *
     * @return true if the candidate is found to have any small factors,
     *         false otherwise.
     */
    public static boolean hasAnySmallFactors(BigInteger candidate)
    {
        checkCandidate(candidate, "candidate");

        return implHasAnySmallFactors(candidate);
    }

    /**
     * FIPS 186-4 C.3.1 Miller-Rabin Probabilistic Primality Test
     *
     * Run several iterations of the Miller-Rabin algorithm with randomly-chosen bases.
     *
     * @param candidate
     *            the {@link BigInteger} instance to test for primality.
     * @param random
     *            the source of randomness to use to choose bases.
     * @param iterations
     *            the number of randomly-chosen bases to perform the test for.
     * @return false if any witness to compositeness is found amongst the chosen bases
     *         (so candidate is definitely NOT prime), or else true
     *         (indicating primality with some probability dependent on the number of iterations
     *         that were performed).
     */
    public static boolean isMRProbablePrime(BigInteger candidate, SecureRandom random, int iterations)
    {
        checkCandidate(candidate, "candidate");

        if (random == null)
        {
            throw new IllegalArgumentException("'random' cannot be null");
        }
        if (iterations < 1)
        {
            throw new IllegalArgumentException("'iterations' must be > 0");
        }

        if (candidate.bitLength() == 2)
        {
            return true;
        }
        if (!candidate.testBit(0))
        {
            return false;
        }

        BigInteger wSubOne = candidate.subtract(ONE);
        BigInteger wSubTwo = candidate.subtract(TWO);

        int a = wSubOne.getLowestSetBit();
        BigInteger m = wSubOne.shiftRight(a);

        for (int i = 0; i < iterations; ++i)
        {
            BigInteger b = BigIntegers.createRandomInRange(TWO, wSubTwo, random);

            if (!implMRProbablePrimeToBase(candidate, wSubOne, m, a, b))
            {
                return false;
            }
        }

        return true;
    }

    private static void checkCandidate(BigInteger n, String name)
    {
        if (n == null || n.signum() < 1 || n.bitLength() < 2)
        {
            throw new IllegalArgumentException("'" + name + "' must be non-null and >= 2");
        }
    }

    private static boolean implHasAnySmallFactors(BigInteger x)
    {
        /*
         * Bundle trial divisors into ~32-bit moduli then use fast tests on the ~32-bit remainders.
         */
        int m = 2 * 3 * 5 * 7 * 11 * 13 * 17 * 19 * 23;
        int r = x.mod(BigInteger.valueOf(m)).intValue();
        if ((r % 2) == 0 || (r % 3) == 0 || (r % 5) == 0 || (r % 7) == 0 || (r % 11) == 0 || (r % 13) == 0
            || (r % 17) == 0 || (r % 19) == 0 || (r % 23) == 0)
        {
            return true;
        }

        m = 29 * 31 * 37 * 41 * 43;
        r = x.mod(BigInteger.valueOf(m)).intValue();
        if ((r % 29) == 0 || (r % 31) == 0 || (r % 37) == 0 || (r % 41) == 0 || (r % 43) == 0)
        {
            return true;
        }

        m = 47 * 53 * 59 * 61 * 67;
        r = x.mod(BigInteger.valueOf(m)).intValue();
        if ((r % 47) == 0 || (r % 53) == 0 || (r % 59) == 0 || (r % 61) == 0 || (r % 67) == 0)
        {
            return true;
        }

        m = 71 * 73 * 79 * 83;
        r = x.mod(BigInteger.valueOf(m)).intValue();
        if ((r % 71) == 0 || (r % 73) == 0 || (r % 79) == 0 || (r % 83) == 0)
        {
            return true;
        }

        m = 89 * 97 * 101 * 103;
        r = x.mod(BigInteger.valueOf(m)).intValue();
        if ((r % 89) == 0 || (r % 97) == 0 || (r % 101) == 0 || (r % 103) == 0)
        {
            return true;
        }

        m = 107 * 109 * 113 * 127;
        r = x.mod(BigInteger.valueOf(m)).intValue();
        if ((r % 107) == 0 || (r % 109) == 0 || (r % 113) == 0 || (r % 127) == 0)
        {
            return true;
        }

        m = 131 * 137 * 139 * 149;
        r = x.mod(BigInteger.valueOf(m)).intValue();
        if ((r % 131) == 0 || (r % 137) == 0 || (r % 139) == 0 || (r % 149) == 0)
        {
            return true;
        }

        m = 151 * 157 * 163 * 167;
        r = x.mod(BigInteger.valueOf(m)).intValue();
        if ((r % 151) == 0 || (r % 157) == 0 || (r % 163) == 0 || (r % 167) == 0)
        {
            return true;
        }

        m = 173 * 179 * 181 * 191;
        r = x.mod(BigInteger.valueOf(m)).intValue();
        if ((r % 173) == 0 || (r % 179) == 0 || (r % 181) == 0 || (r % 191) == 0)
        {
            return true;
        }

        m = 193 * 197 * 199 * 211;
        r = x.mod(BigInteger.valueOf(m)).intValue();
        if ((r % 193) == 0 || (r % 197) == 0 || (r % 199) == 0 || (r % 211) == 0)
        {
            return true;
        }

        /*
         * NOTE: Unit tests depend on SMALL_FACTOR_LIMIT matching the
         * highest small factor tested here.
         */
        return false;
    }

    private static boolean implMRProbablePrimeToBase(BigInteger w, BigInteger wSubOne, BigInteger m, int a, BigInteger b)
    {
        BigInteger z = b.modPow(m, w);

        if (z.equals(ONE) || z.equals(wSubOne))
        {
            return true;
        }

        boolean result = false;

        for (int j = 1; j < a; ++j)
        {
            z = z.modPow(TWO, w);

            if (z.equals(wSubOne))
            {
                result = true;
                break;
            }

            if (z.equals(ONE))
            {
                return false;
            }
        }

        return result;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy