コード例 #1
0
ファイル: PrimalityTests.cs プロジェクト: Fedorm/core-master
        private static int GetSPPRounds(BigInteger bi, ConfidenceFactor confidence)
        {
            int bc = bi.BitCount();

            int Rounds;

            // Data from HAC, 4.49
            if (bc <= 100) Rounds = 27;
            else if (bc <= 150) Rounds = 18;
            else if (bc <= 200) Rounds = 15;
            else if (bc <= 250) Rounds = 12;
            else if (bc <= 300) Rounds = 9;
            else if (bc <= 350) Rounds = 8;
            else if (bc <= 400) Rounds = 7;
            else if (bc <= 500) Rounds = 6;
            else if (bc <= 600) Rounds = 5;
            else if (bc <= 800) Rounds = 4;
            else if (bc <= 1250) Rounds = 3;
            else Rounds = 2;

            switch (confidence)
            {
                case ConfidenceFactor.ExtraLow:
                    Rounds >>= 2;
                    return Rounds != 0 ? Rounds : 1;
                case ConfidenceFactor.Low:
                    Rounds >>= 1;
                    return Rounds != 0 ? Rounds : 1;
                case ConfidenceFactor.Medium:
                    return Rounds;
                case ConfidenceFactor.High:
                    return Rounds << 1;
                case ConfidenceFactor.ExtraHigh:
                    return Rounds << 2;
                case ConfidenceFactor.Provable:
                    throw new Exception(
                        "The Rabin-Miller test can not be executed in a way such that its results are provable");
                default:
                    throw new ArgumentOutOfRangeException("confidence");
            }
        }
コード例 #2
0
ファイル: BigInteger.cs プロジェクト: Fedorm/core-master
			private unsafe BigInteger OddModTwoPow (BigInteger exp)
			{

				uint [] wkspace = new uint [mod.length << 1 + 1];

				BigInteger resultNum = Montgomery.ToMont ((BigInteger)2, this.mod);
				resultNum = new BigInteger (resultNum, mod.length << 1 +1);

				uint mPrime = Montgomery.Inverse (mod.data [0]);

				//
				// TODO: eat small bits, the ones we can do with no modular reduction
				//
				uint pos = (uint)exp.BitCount () - 2;

				do {
					Kernel.SquarePositive (resultNum, ref wkspace);
					resultNum = Montgomery.Reduce (resultNum, mod, mPrime);

					if (exp.TestBit (pos)) {
						//
						// resultNum = (resultNum * 2) % mod
						//

						fixed (uint* u = resultNum.data) {
							//
							// Double
							//
							uint* uu = u;
							uint* uuE = u + resultNum.length;
							uint x, carry = 0;
							while (uu < uuE) {
								x = *uu;
								*uu = (x << 1) | carry;
								carry = x >> (32 - 1);
								uu++;
							}

							// subtraction inlined because we know it is square
							if (carry != 0 || resultNum >= mod) {
								fixed (uint* s = mod.data) {
									uu = u;
									uint c = 0;
									uint* ss = s;
									do {
										uint a = *ss++;
										if (((a += c) < c) | ((* (uu++) -= a) > ~a))
											c = 1;
										else
											c = 0;
									} while (uu < uuE);
								}
							}
						}
					}
				} while (pos-- > 0);

				resultNum = Montgomery.Reduce (resultNum, mod, mPrime);
				return resultNum;
			}
コード例 #3
0
ファイル: BigInteger.cs プロジェクト: Fedorm/core-master
			private unsafe BigInteger EvenPow (uint b, BigInteger exp)
			{
				exp.Normalize ();
				uint [] wkspace = new uint [mod.length << 1 + 1];
				BigInteger resultNum = new BigInteger ((BigInteger)b, mod.length << 1 + 1);

				uint pos = (uint)exp.BitCount () - 2;

				//
				// We know that the first itr will make the val b
				//

				do {
					//
					// r = r ^ 2 % m
					//
					Kernel.SquarePositive (resultNum, ref wkspace);
					if (!(resultNum.length < mod.length))
						BarrettReduction (resultNum);

					if (exp.TestBit (pos)) {

						//
						// r = r * b % m
						//

						// TODO: Is Unsafe really speeding things up?
						fixed (uint* u = resultNum.data) {

							uint i = 0;
							ulong mc = 0;

							do {
								mc += (ulong)u [i] * (ulong)b;
								u [i] = (uint)mc;
								mc >>= 32;
							} while (++i < resultNum.length);

							if (resultNum.length < mod.length) {
								if (mc != 0) {
									u [i] = (uint)mc;
									resultNum.length++;
									while (resultNum >= mod)
										Kernel.MinusEq (resultNum, mod);
								}
							} else if (mc != 0) {

								//
								// First, we estimate the quotient by dividing
								// the first part of each of the numbers. Then
								// we correct this, if necessary, with a subtraction.
								//

								uint cc = (uint)mc;

								// We would rather have this estimate overshoot,
								// so we add one to the divisor
								uint divEstimate = (uint) ((((ulong)cc << 32) | (ulong) u [i -1]) /
									(mod.data [mod.length-1] + 1));

								uint t;

								i = 0;
								mc = 0;
								do {
									mc += (ulong)mod.data [i] * (ulong)divEstimate;
									t = u [i];
									u [i] -= (uint)mc;
									mc >>= 32;
									if (u [i] > t) mc++;
									i++;
								} while (i < resultNum.length);
								cc -= (uint)mc;

								if (cc != 0) {

									uint sc = 0, j = 0;
									uint [] s = mod.data;
									do {
										uint a = s [j];
										if (((a += sc) < sc) | ((u [j] -= a) > ~a)) sc = 1;
										else sc = 0;
										j++;
									} while (j < resultNum.length);
									cc -= sc;
								}
								while (resultNum >= mod)
									Kernel.MinusEq (resultNum, mod);
							} else {
								while (resultNum >= mod)
									Kernel.MinusEq (resultNum, mod);
							}
						}
					}
				} while (pos-- > 0);

				return resultNum;
			}
コード例 #4
0
ファイル: BigInteger.cs プロジェクト: Fedorm/core-master
			private BigInteger OddPow (BigInteger b, BigInteger exp)
			{
				BigInteger resultNum = new BigInteger (Montgomery.ToMont (1, mod), mod.length << 1);
				BigInteger tempNum = new BigInteger (Montgomery.ToMont (b, mod), mod.length << 1);  // ensures (tempNum * tempNum) < b^ (2k)
				uint mPrime = Montgomery.Inverse (mod.data [0]);
				uint totalBits = (uint)exp.BitCount ();

				uint [] wkspace = new uint [mod.length << 1];

				// perform squaring and multiply exponentiation
				for (uint pos = 0; pos < totalBits; pos++) {
					if (exp.TestBit (pos)) {

						Array.Clear (wkspace, 0, wkspace.Length);
						Kernel.Multiply (resultNum.data, 0, resultNum.length, tempNum.data, 0, tempNum.length, wkspace, 0);
						resultNum.length += tempNum.length;
						uint [] t = wkspace;
						wkspace = resultNum.data;
						resultNum.data = t;

						Montgomery.Reduce (resultNum, mod, mPrime);
					}

					// the value of tempNum is required in the last loop
					if (pos < totalBits - 1) {
						Kernel.SquarePositive (tempNum, ref wkspace);
						Montgomery.Reduce (tempNum, mod, mPrime);
					}
				}

				Montgomery.Reduce (resultNum, mod, mPrime);
				return resultNum;
			}
コード例 #5
0
ファイル: BigInteger.cs プロジェクト: Fedorm/core-master
			public BigInteger EvenPow (BigInteger b, BigInteger exp)
			{
				BigInteger resultNum = new BigInteger ((BigInteger)1, mod.length << 1);
				BigInteger tempNum = new BigInteger (b % mod, mod.length << 1);  // ensures (tempNum * tempNum) < b^ (2k)

				uint totalBits = (uint)exp.BitCount ();

				uint [] wkspace = new uint [mod.length << 1];

				// perform squaring and multiply exponentiation
				for (uint pos = 0; pos < totalBits; pos++) {
					if (exp.TestBit (pos)) {

						Array.Clear (wkspace, 0, wkspace.Length);
						Kernel.Multiply (resultNum.data, 0, resultNum.length, tempNum.data, 0, tempNum.length, wkspace, 0);
						resultNum.length += tempNum.length;
						uint [] t = wkspace;
						wkspace = resultNum.data;
						resultNum.data = t;

						BarrettReduction (resultNum);
					}

					Kernel.SquarePositive (tempNum, ref wkspace);
					BarrettReduction (tempNum);

					if (tempNum == 1) {
						return resultNum;
					}
				}

				return resultNum;
			}
コード例 #6
0
ファイル: BigInteger.cs プロジェクト: Fedorm/core-master
            public BigInteger Pow(BigInteger a, BigInteger k)
            {
                var b = new BigInteger(1);
                if (k == 0)
                    return b;

                BigInteger A = a;
                if (k.TestBit(0))
                    b = a;

                for (int i = 1; i < k.BitCount(); i++)
                {
                    A = Multiply(A, A);
                    if (k.TestBit(i))
                        b = Multiply(A, b);
                }
                return b;
            }
コード例 #7
0
ファイル: PrimalityTests.cs プロジェクト: Fedorm/core-master
 public static bool Test(BigInteger n, ConfidenceFactor confidence)
 {
     // Rabin-Miller fails with smaller primes (at least with our BigInteger code)
     if (n.BitCount() < 33)
         return SmallPrimeSppTest(n, confidence);
     return RabinMillerTest(n, confidence);
 }
コード例 #8
0
ファイル: PrimalityTests.cs プロジェクト: Fedorm/core-master
        /// <summary>
        ///     Probabilistic prime test based on Rabin-Miller's test
        /// </summary>
        /// <param name="n" type="BigInteger.BigInteger">
        ///     <para>
        ///         The number to test.
        ///     </para>
        /// </param>
        /// <param name="confidence" type="int">
        ///     <para>
        ///         The number of chosen bases. The test has at least a
        ///         1/4^confidence chance of falsely returning True.
        ///     </para>
        /// </param>
        /// <returns>
        ///     <para>
        ///         True if "this" is a strong pseudoprime to randomly chosen bases.
        ///     </para>
        ///     <para>
        ///         False if "this" is definitely NOT prime.
        ///     </para>
        /// </returns>
        public static bool RabinMillerTest(BigInteger n, ConfidenceFactor confidence)
        {
            int bits = n.BitCount();
            int t = GetSPPRounds(bits, confidence);

            // n - 1 == 2^s * r, r is odd
            BigInteger n_minus_1 = n - 1;
            int s = n_minus_1.LowestSetBit();
            BigInteger r = n_minus_1 >> s;

            var mr = new BigInteger.ModulusRing(n);

            // Applying optimization from HAC section 4.50 (base == 2)
            // not a really random base but an interesting (and speedy) one
            BigInteger y = null;
            // FIXME - optimization disable for small primes due to bug #81857
            if (n.BitCount() > 100)
                y = mr.Pow(2, r);

            // still here ? start at round 1 (round 0 was a == 2)
            for (int round = 0; round < t; round++)
            {
                if ((round > 0) || (y == null))
                {
                    BigInteger a = null;

                    // check for 2 <= a <= n - 2
                    // ...but we already did a == 2 previously as an optimization
                    do
                    {
                        a = BigInteger.GenerateRandom(bits);
                    } while ((a <= 2) && (a >= n_minus_1));

                    y = mr.Pow(a, r);
                }

                if (y == 1)
                    continue;

                for (int j = 0; ((j < s) && (y != n_minus_1)); j++)
                {
                    y = mr.Pow(y, 2);
                    if (y == 1)
                        return false;
                }

                if (y != n_minus_1)
                    return false;
            }
            return true;
        }
コード例 #9
0
 // initializes the private variables (throws CryptographicException)
 private void Initialize(BigInteger p, BigInteger g, BigInteger x, int secretLen, bool checkInput)
 {
     if (!p.IsProbablePrime() || g <= 0 || g >= p || (x != null && (x <= 0 || x > p - 2)))
         throw new CryptographicException();
     // default is to generate a number as large as the prime this
     // is usually overkill, but it's the most secure thing we can
     // do if the user doesn't specify a desired secret length ...
     if (secretLen == 0)
         secretLen = p.BitCount();
     m_P = p;
     m_G = g;
     if (x == null)
     {
         BigInteger pm1 = m_P - 1;
         for (m_X = BigInteger.GenerateRandom(secretLen);
             m_X >= pm1 || m_X == 0;
             m_X = BigInteger.GenerateRandom(secretLen))
         {
         }
     }
     else
     {
         m_X = x;
     }
 }