예제 #1
0
		//***********************************************************************
		// Probabilistic prime test based on Rabin-Miller's
		//
		// for any p > 0 with p - 1 = 2^s * t
		//
		// p is probably prime (strong pseudoprime) if for any a < p,
		// 1) a^t mod p = 1 or
		// 2) a^((2^j)*t) mod p = p-1 for some 0 <= j <= s-1
		//
		// Otherwise, p is composite.
		//
		// Returns
		// -------
		// True if "this" is a strong pseudoprime to randomly chosen
		// bases.  The number of chosen bases is given by the "confidence"
		// parameter.
		//
		// False if "this" is definitely NOT prime.
		//
		//***********************************************************************

		internal bool RabinMillerTest(int confidence)
		{
			BigInteger thisVal;
			if ((this.data[maxLength - 1] & 0x80000000) != 0)        // negative
				thisVal = -this;
			else
				thisVal = this;

			if (thisVal.dataLength == 1)
			{
				// test small numbers
				if (thisVal.data[0] == 0 || thisVal.data[0] == 1)
					return false;
				else if (thisVal.data[0] == 2 || thisVal.data[0] == 3)
					return true;
			}

			if ((thisVal.data[0] & 0x1) == 0)     // even numbers
				return false;


			// calculate values of s and t
			BigInteger p_sub1 = thisVal - (new BigInteger(1));
			int s = 0;

			for (int index = 0; index < p_sub1.dataLength; index++)
			{
				uint mask = 0x01;

				for (int i = 0; i < 32; i++)
				{
					if ((p_sub1.data[index] & mask) != 0)
					{
						index = p_sub1.dataLength;      // to break the outer loop
						break;
					}
					mask <<= 1;
					s++;
				}
			}

			BigInteger t = p_sub1 >> s;

			int bits = thisVal.bitCount();
			BigInteger a = new BigInteger();
			Random rand = new Random();

			for (int round = 0; round < confidence; round++)
			{
				bool done = false;

				while (!done)		// generate a < n
				{
					int testBits = 0;

					// make sure "a" has at least 2 bits
					while (testBits < 2)
						testBits = (int)(rand.NextDouble() * bits);

					a.genRandomBits(testBits, rand);

					int byteLen = a.dataLength;

					// make sure "a" is not 0
					if (byteLen > 1 || (byteLen == 1 && a.data[0] != 1))
						done = true;
				}

				// check whether a factor exists (fix for version 1.03)
				BigInteger gcdTest = a.gcd(thisVal);
				if (gcdTest.dataLength == 1 && gcdTest.data[0] != 1)
					return false;

				BigInteger b = a.modPow(t, thisVal);

				bool result = false;

				if (b.dataLength == 1 && b.data[0] == 1)         // a^t mod p = 1
					result = true;

				for (int j = 0; result == false && j < s; j++)
				{
					if (b == p_sub1)         // a^((2^j)*t) mod p = p-1 for some 0 <= j <= s-1
					{
						result = true;
						break;
					}

					b = (b * b) % thisVal;
				}

				if (result == false)
					return false;
			}
			return true;
		}
예제 #2
0
		//***********************************************************************
		// Probabilistic prime test based on Solovay-Strassen (Euler Criterion)
		//
		// p is probably prime if for any a < p (a is not multiple of p),
		// a^((p-1)/2) mod p = J(a, p)
		//
		// where J is the Jacobi symbol.
		//
		// Otherwise, p is composite.
		//
		// Returns
		// -------
		// True if "this" is a Euler pseudoprime to randomly chosen
		// bases.  The number of chosen bases is given by the "confidence"
		// parameter.
		//
		// False if "this" is definitely NOT prime.
		//
		//***********************************************************************

		internal bool SolovayStrassenTest(int confidence)
		{
			BigInteger thisVal;
			if ((this.data[maxLength - 1] & 0x80000000) != 0)        // negative
				thisVal = -this;
			else
				thisVal = this;

			if (thisVal.dataLength == 1)
			{
				// test small numbers
				if (thisVal.data[0] == 0 || thisVal.data[0] == 1)
					return false;
				else if (thisVal.data[0] == 2 || thisVal.data[0] == 3)
					return true;
			}

			if ((thisVal.data[0] & 0x1) == 0)     // even numbers
				return false;


			int bits = thisVal.bitCount();
			BigInteger a = new BigInteger();
			BigInteger p_sub1 = thisVal - 1;
			BigInteger p_sub1_shift = p_sub1 >> 1;

			Random rand = new Random();

			for (int round = 0; round < confidence; round++)
			{
				bool done = false;

				while (!done)		// generate a < n
				{
					int testBits = 0;

					// make sure "a" has at least 2 bits
					while (testBits < 2)
						testBits = (int)(rand.NextDouble() * bits);

					a.genRandomBits(testBits, rand);

					int byteLen = a.dataLength;

					// make sure "a" is not 0
					if (byteLen > 1 || (byteLen == 1 && a.data[0] != 1))
						done = true;
				}

				// check whether a factor exists (fix for version 1.03)
				BigInteger gcdTest = a.gcd(thisVal);
				if (gcdTest.dataLength == 1 && gcdTest.data[0] != 1)
					return false;

				// calculate a^((p-1)/2) mod p

				BigInteger expResult = a.modPow(p_sub1_shift, thisVal);
				if (expResult == p_sub1)
					expResult = -1;

				// calculate Jacobi symbol
				BigInteger jacob = Jacobi(a, thisVal);

				// if they are different then it is not prime
				if (expResult != jacob)
					return false;
			}

			return true;
		}
예제 #3
0
		//***********************************************************************
		// Probabilistic prime test based on Fermat's little theorem
		//
		// for any a < p (p does not divide a) if
		//      a^(p-1) mod p != 1 then p is not prime.
		//
		// Otherwise, p is probably prime (pseudoprime to the chosen base).
		//
		// Returns
		// -------
		// True if "this" is a pseudoprime to randomly chosen
		// bases.  The number of chosen bases is given by the "confidence"
		// parameter.
		//
		// False if "this" is definitely NOT prime.
		//
		// Note - this method is fast but fails for Carmichael numbers except
		// when the randomly chosen base is a factor of the number.
		//
		//***********************************************************************

		internal bool FermatLittleTest(int confidence)
		{
			BigInteger thisVal;
			if ((this.data[maxLength - 1] & 0x80000000) != 0)        // negative
				thisVal = -this;
			else
				thisVal = this;

			if (thisVal.dataLength == 1)
			{
				// test small numbers
				if (thisVal.data[0] == 0 || thisVal.data[0] == 1)
					return false;
				else if (thisVal.data[0] == 2 || thisVal.data[0] == 3)
					return true;
			}

			if ((thisVal.data[0] & 0x1) == 0)     // even numbers
				return false;

			int bits = thisVal.bitCount();
			BigInteger a = new BigInteger();
			BigInteger p_sub1 = thisVal - (new BigInteger(1));
			Random rand = new Random();

			for (int round = 0; round < confidence; round++)
			{
				bool done = false;

				while (!done)		// generate a < n
				{
					int testBits = 0;

					// make sure "a" has at least 2 bits
					while (testBits < 2)
						testBits = (int)(rand.NextDouble() * bits);

					a.genRandomBits(testBits, rand);

					int byteLen = a.dataLength;

					// make sure "a" is not 0
					if (byteLen > 1 || (byteLen == 1 && a.data[0] != 1))
						done = true;
				}

				// check whether a factor exists (fix for version 1.03)
				BigInteger gcdTest = a.gcd(thisVal);
				if (gcdTest.dataLength == 1 && gcdTest.data[0] != 1)
					return false;

				// calculate a^(p-1) mod p
				BigInteger expResult = a.modPow(p_sub1, thisVal);

				int resultLen = expResult.dataLength;

				// is NOT prime is a^(p-1) mod p != 1

				if (resultLen > 1 || (resultLen == 1 && expResult.data[0] != 1))
				{
					return false;
				}
			}

			return true;
		}