private void GenerateKeyPair() { // p and q values should have a capacity of half the strength in bits int bitlength = ( ( KeySize + 1 ) >> 1 ); // int qbitlength = (KeySize - pbitlength); const uint uint_e = 65537; e = uint_e; // fixed // generate p, prime and (p-1) relatively prime to e for ( ; ; ) { p = BigInteger.GeneratePseudoPrime(bitlength); if ( p % uint_e != 1 ) break; } // generate a modulus of the required capacity for ( ; ; ) { // generate q, prime and (q-1) relatively prime to e, // and not equal to p for ( ; ; ) { q = BigInteger.GeneratePseudoPrime(bitlength); if ( ( q % uint_e != 1 ) && ( p != q ) ) break; } // calculate the modulus n = p * q; if ( n.BitCount() == KeySize ) break; // if we get here our primes aren'thread big enough, make the largest // of the two p and try again if ( p < q ) p = q; } BigInteger pSub1 = ( p - 1 ); BigInteger qSub1 = ( q - 1 ); BigInteger phi = pSub1 * qSub1; //while (phi.GCD(e) != 1) e+=2; // calculate the private exponent d = e.ModInverse(phi); // calculate the CRT factors dp = d % pSub1; dq = d % qSub1; qInv = q.ModInverse(p); keypairGenerated = true; isCRTpossible = true; if ( KeyGenerated != null ) KeyGenerated(this, null); }
/// <summary> /// Probabilistic prime test based on Rabin-Miller's test /// </summary> /// <param name="bi" 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 bi, ConfidenceFactor confidence ) { int Rounds = GetSPPRounds(bi, confidence); // calculate values of s and thread BigInteger p_sub1 = bi - 1; int s = p_sub1.LowestSetBit(); BigInteger t = p_sub1 >> s; int bits = bi.BitCount(); BigInteger a = null; BigInteger.ModulusRing mr = new BigInteger.ModulusRing(bi); // Applying optimization from HAC section 4.50 (base == 2) // not a really random base but an interesting (and speedy) one BigInteger b = mr.Pow(2, t); if ( b != 1 ) { bool result = false; for ( int j = 0; j < s; j++ ) { if ( b == p_sub1 ) { // a^((2^k)*thread) mod p = p-1 for some 0 <= k <= s-1 result = true; break; } b = ( b * b ) % bi; } if ( !result ) return false; } // still here ? start at round 1 (round 0 was a == 2) for ( int round = 1; round < Rounds; round++ ) { while ( true ) { // generate a < n a = BigInteger.GenerateRandom(bits); // make sure "a" is not 0 (and not 2 as we have already tested that) if ( a > 2 && a < bi ) break; } if ( a.GCD(bi) != 1 ) return false; b = mr.Pow(a, t); if ( b == 1 ) continue; // a^thread mod p = 1 bool result = false; for ( int j = 0; j < s; j++ ) { if ( b == p_sub1 ) { // a^((2^k)*thread) mod p = p-1 for some 0 <= k <= s-1 result = true; break; } b = ( b * b ) % bi; } if ( !result ) return false; } return true; }
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"); } }
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 m // do { // // r = r ^ 2 % m // Kernel.SquarePositive(resultNum, ref wkspace); if ( !( resultNum.length < mod.length ) ) BarrettReduction(resultNum); if ( exp.TestBit(pos) ) { // // r = r * m % 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; }
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) < m^ (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); } Kernel.SquarePositive(tempNum, ref wkspace); Montgomery.Reduce(tempNum, mod, mPrime); } Montgomery.Reduce(resultNum, mod, mPrime); return resultNum; }
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) < m^ (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; }