public static unsafe void SquarePositive( BigInteger bi, ref uint[] wkSpace ) { uint[] t = wkSpace; wkSpace = bi.data; uint[] d = bi.data; uint dl = bi.length; bi.data = t; fixed ( uint* dd = d, tt = t ) { uint* ttE = tt + t.Length; // Clear the dest for ( uint* ttt = tt; ttt < ttE; ttt++ ) *ttt = 0; uint* dP = dd, tP = tt; for ( uint i = 0; i < dl; i++, dP++ ) { if ( *dP == 0 ) continue; ulong mcarry = 0; uint bi1val = *dP; uint* dP2 = dP + 1, tP2 = tP + 2 * i + 1; for ( uint j = i + 1; j < dl; j++, tP2++, dP2++ ) { // j = i + k mcarry += ( ( ulong )bi1val * ( ulong )*dP2 ) + *tP2; *tP2 = ( uint )mcarry; mcarry >>= 32; } if ( mcarry != 0 ) *tP2 = ( uint )mcarry; } // Double thread. Inlined for speed. tP = tt; uint x, carry = 0; while ( tP < ttE ) { x = *tP; *tP = ( x << 1 ) | carry; carry = x >> ( 32 - 1 ); tP++; } if ( carry != 0 ) *tP = carry; // Add in the diagnals dP = dd; tP = tt; for ( uint* dE = dP + dl; ( dP < dE ); dP++, tP++ ) { ulong val = ( ulong )*dP * ( ulong )*dP + *tP; *tP = ( uint )val; val >>= 32; *( ++tP ) += ( uint )val; if ( *tP < ( uint )val ) { uint* tP3 = tP; // Account for the first carry ( *++tP3 )++; // Keep adding until no carry while ( ( *tP3++ ) == 0 ) ( *tP3 )++; } } bi.length <<= 1; // Normalize capacity while ( tt[bi.length - 1] == 0 && bi.length > 1 ) bi.length--; } }
public static BigInteger Divid( BigInteger bi1, BigInteger bi2 ) { return ( bi1 / bi2 ); }
public static BigInteger Multiply( BigInteger bi, int i ) { return ( bi * i ); }
public static int Modulus( BigInteger bi, int i ) { return ( bi % i ); }
public static BigInteger Modulus( BigInteger bi1, BigInteger bi2 ) { return ( bi1 % bi2 ); }
/* This is the BigInteger.Parse method I use. This method works because BigInteger.ToString returns the input I gave to Parse. */ public static BigInteger Parse( string number ) { if ( number == null ) throw new ArgumentNullException("number"); int i = 0, len = number.Length; char c; bool digits_seen = false; BigInteger val = new BigInteger(0); if ( number[i] == '+' ) { i++; } else if ( number[i] == '-' ) { throw new FormatException(WouldReturnNegVal); } for ( ; i < len; i++ ) { c = number[i]; if ( c == '\0' ) { i = len; continue; } if ( c >= '0' && c <= '9' ) { val = val * 10 + ( c - '0' ); digits_seen = true; } else { if ( Char.IsWhiteSpace(c) ) { for ( i++; i < len; i++ ) { if ( !Char.IsWhiteSpace(number[i]) ) throw new FormatException(); } break; } else throw new FormatException(); } } if ( !digits_seen ) throw new FormatException(); return val; }
// with names suggested by FxCop 1.30 public static BigInteger Add( BigInteger bi1, BigInteger bi2 ) { return ( bi1 + bi2 ); }
/// <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; }
public static bool SmallPrimeSppTest( 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; BigInteger.ModulusRing mr = new BigInteger.ModulusRing(bi); for ( int round = 0; round < Rounds; round++ ) { BigInteger b = mr.Pow(BigInteger.smallPrimes[round], 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 == false ) return false; } return true; }
protected override BigInteger GenerateSearchBase( int bits, object Context ) { if ( Context == null ) throw new ArgumentNullException("Context"); BigInteger ret = new BigInteger(( BigInteger )Context); ret.SetBit(0); return ret; }
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"); } }
public static BigInteger modInverse( BigInteger bi, BigInteger modulus ) { if ( modulus.length == 1 ) return modInverse(bi, modulus.data[0]); BigInteger[] p = { 0, 1 }; BigInteger[] q = new BigInteger[2]; // quotients BigInteger[] r = { 0, 0 }; // remainders int step = 0; BigInteger a = modulus; BigInteger b = bi; ModulusRing mr = new ModulusRing(modulus); while ( b != 0 ) { if ( step > 1 ) { BigInteger pval = mr.Difference(p[0], p[1] * q[0]); p[0] = p[1]; p[1] = pval; } BigInteger[] divret = multiByteDivide(a, b); q[0] = q[1]; q[1] = divret[0]; r[0] = r[1]; r[1] = divret[1]; a = b; b = divret[1]; step++; } if ( r[0] != 1 ) throw ( new ArithmeticException("No inverse!") ); return mr.Difference(p[0], p[1] * q[0]); }
public static uint modInverse( BigInteger bi, uint modulus ) { uint a = modulus, b = bi % modulus; uint p0 = 0, p1 = 1; while ( b != 0 ) { if ( b == 1 ) return p1; p0 += ( a / b ) * p1; a %= b; if ( a == 0 ) break; if ( a == 1 ) return modulus - p0; p1 += ( b / a ) * p0; b %= a; } return 0; }
/* * Never called in BigInteger (and part of a private class) * public static bool Double (uint [] u, int k) { uint x, carry = 0; uint i = 0; while (i < k) { x = u [i]; u [i] = (x << 1) | carry; carry = x >> (32 - 1); i++; } if (carry != 0) u [k] = carry; return carry != 0; }*/ #endregion #region Number Theory public static BigInteger gcd( BigInteger a, BigInteger b ) { BigInteger x = a; BigInteger y = b; BigInteger g = y; while ( x.length > 1 ) { g = x; x = y % x; y = g; } if ( x == 0 ) return g; // TODO: should we have something here if we can convert to long? // // Now we can just do it with single precision. I am using the binary gcd method, // as it should be faster. // uint yy = x.data[0]; uint xx = y % yy; int t = 0; while ( ( ( xx | yy ) & 1 ) == 0 ) { xx >>= 1; yy >>= 1; t++; } while ( xx != 0 ) { while ( ( xx & 1 ) == 0 ) xx >>= 1; while ( ( yy & 1 ) == 0 ) yy >>= 1; if ( xx >= yy ) xx = ( xx - yy ) >> 1; else yy = ( yy - xx ) >> 1; } return yy << t; }
/// <summary> /// Create new instance of BihInteger /// </summary> /// <param name="bi"></param> public BigInteger( BigInteger bi ) { this.data = ( uint[] )bi.data.Clone(); this.length = bi.length; }
/// <summary> /// Performs primality tests on bi, assumes trial division has been done. /// </summary> /// <param name="bi">A BigInteger that has been subjected to and passed trial division</param> /// <returns>False if bi is composite, true if it may be prime.</returns> /// <remarks>The speed of this method is dependent on Confidence</remarks> protected bool PostTrialDivisionTests( BigInteger bi ) { return PrimalityTest(bi, this.Confidence); }
// [CLSCompliant (false)] #endif /// <summary> /// Create new instance of BihInteger /// </summary> /// <param name="bi"></param> /// <param name="len"></param> public BigInteger( BigInteger bi, uint len ) { this.data = new uint[len]; for ( uint i = 0; i < bi.length; i++ ) this.data[i] = bi.data[i]; this.length = bi.length; }
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); }
public static BigInteger operator *( BigInteger bi1, BigInteger bi2 ) { if ( bi1 == 0 || bi2 == 0 ) return 0; // // Validate pointers // if ( bi1.data.Length < bi1.length ) throw new IndexOutOfRangeException("bi1 out of range"); if ( bi2.data.Length < bi2.length ) throw new IndexOutOfRangeException("bi2 out of range"); BigInteger ret = new BigInteger(Sign.Positive, bi1.length + bi2.length); Kernel.Multiply(bi1.data, 0, bi1.length, bi2.data, 0, bi2.length, ret.data, 0); ret.Normalize(); return ret; }
public override byte[] DecryptValue( byte[] rgb ) { if ( m_disposed ) throw new ObjectDisposedException("private key"); // decrypt operation is used for signature if ( !keypairGenerated ) GenerateKeyPair(); BigInteger input = new BigInteger(rgb); BigInteger r = null; // we use key blinding (by default) against timing attacks if ( keyBlinding ) { // x = (r^e * g) mod n // *new* random number (so it's timing is also random) r = BigInteger.GenerateRandom(n.BitCount()); input = r.ModPow(e, n) * input % n; } BigInteger output; // decrypt (which uses the private key) can be // optimized by using CRT (Chinese Remainder Theorem) if ( isCRTpossible ) { // m1 = c^dp mod p BigInteger m1 = input.ModPow(dp, p); // m2 = c^dq mod q BigInteger m2 = input.ModPow(dq, q); BigInteger h; if ( m2 > m1 ) { // thanks to benm! h = p - ( ( m2 - m1 ) * qInv % p ); output = m2 + q * h; } else { // h = (m1 - m2) * qInv mod p h = ( m1 - m2 ) * qInv % p; // m = m2 + q * h; output = m2 + q * h; } } else { // m = c^i mod n output = input.ModPow(d, n); } if ( keyBlinding ) { // Complete blinding // x^e / r mod n output = output * r.ModInverse(n) % n; r.Clear(); } byte[] result = output.GetBytes(); // zeroize values input.Clear(); output.Clear(); return result; }
public static BigInteger Subtract( BigInteger bi1, BigInteger bi2 ) { return ( bi1 - bi2 ); }
public override byte[] EncryptValue( byte[] rgb ) { if ( m_disposed ) throw new ObjectDisposedException("public key"); if ( !keypairGenerated ) GenerateKeyPair(); BigInteger input = new BigInteger(rgb); BigInteger output = input.ModPow(e, n); byte[] result = output.GetBytes(); // zeroize value input.Clear(); output.Clear(); return result; }
// [CLSCompliant (false)] #endif public static uint Modulus( BigInteger bi, uint ui ) { return ( bi % ui ); }
public override void ImportParameters( RSAParameters parameters ) { if ( m_disposed ) throw new ObjectDisposedException(""); // if missing "mandatory" parameters if ( parameters.Exponent == null ) throw new CryptographicException("Missing Exponent"); if ( parameters.Modulus == null ) throw new CryptographicException("Missing Modulus"); e = new BigInteger(parameters.Exponent); n = new BigInteger(parameters.Modulus); // only if the private key is present if ( parameters.D != null ) d = new BigInteger(parameters.D); if ( parameters.DP != null ) dp = new BigInteger(parameters.DP); if ( parameters.DQ != null ) dq = new BigInteger(parameters.DQ); if ( parameters.InverseQ != null ) qInv = new BigInteger(parameters.InverseQ); if ( parameters.P != null ) p = new BigInteger(parameters.P); if ( parameters.Q != null ) q = new BigInteger(parameters.Q); // we now have a keypair keypairGenerated = true; isCRTpossible = ( ( p != null ) && ( q != null ) && ( dp != null ) && ( dq != null ) && ( qInv != null ) ); }
public static BigInteger Divid( BigInteger bi, int i ) { return ( bi / i ); }
protected override void Dispose( bool disposing ) { if ( !m_disposed ) { // Always zeroize private key if ( d != null ) { d.Clear(); d = null; } if ( p != null ) { p.Clear(); p = null; } if ( q != null ) { q.Clear(); q = null; } if ( dp != null ) { dp.Clear(); dp = null; } if ( dq != null ) { dq.Clear(); dq = null; } if ( qInv != null ) { qInv.Clear(); qInv = null; } if ( disposing ) { // clear public key if ( e != null ) { e.Clear(); e = null; } if ( n != null ) { n.Clear(); n = null; } } } // call base class // no need as they all are abstract before us m_disposed = true; }
public static BigInteger Multiply( BigInteger bi1, BigInteger bi2 ) { return ( bi1 * bi2 ); }
protected virtual bool IsPrimeAcceptable( BigInteger bi, object context ) { return true; }
/// <summary> /// Generates a new, random BigInteger of the specified capacity. /// </summary> /// <param name="bits">The number of bits for the new number.</param> /// <param name="rng">A random number generator to use to obtain the bits.</param> /// <returns>A random number of the specified capacity.</returns> public static BigInteger GenerateRandom( int bits, RandomNumberGenerator rng ) { int dwords = bits >> 5; int remBits = bits & 0x1F; if ( remBits != 0 ) dwords++; BigInteger ret = new BigInteger(Sign.Positive, ( uint )dwords + 1); byte[] random = new byte[dwords << 2]; rng.GetBytes(random); Buffer.BlockCopy(random, 0, ret.data, 0, ( int )dwords << 2); if ( remBits != 0 ) { uint mask = ( uint )( 0x01 << ( remBits - 1 ) ); ret.data[dwords - 1] |= mask; mask = ( uint )( 0xFFFFFFFF >> ( 32 - remBits ) ); ret.data[dwords - 1] &= mask; } else ret.data[dwords - 1] |= 0x80000000; ret.Normalize(); return ret; }
public static BigInteger MultiplyByDword( BigInteger n, uint f ) { BigInteger ret = new BigInteger(Sign.Positive, n.length + 1); uint i = 0; ulong c = 0; do { c += ( ulong )n.data[i] * ( ulong )f; ret.data[i] = ( uint )c; c >>= 32; } while ( ++i < n.length ); ret.data[i] = ( uint )c; ret.Normalize(); return ret; }