summary refs log tree commit diff
path: root/crypto/src/math/BigInteger.cs
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/src/math/BigInteger.cs')
-rw-r--r--crypto/src/math/BigInteger.cs71
1 files changed, 46 insertions, 25 deletions
diff --git a/crypto/src/math/BigInteger.cs b/crypto/src/math/BigInteger.cs

index ebeb78788..b35701fb3 100644 --- a/crypto/src/math/BigInteger.cs +++ b/crypto/src/math/BigInteger.cs
@@ -681,6 +681,7 @@ namespace Org.BouncyCastle.Math int xBits = BitsPerByte * nBytes - bitLength; byte mask = (byte)(255U >> xBits); + byte lead = (byte)(1 << (7 - xBits)); for (;;) { @@ -690,7 +691,7 @@ namespace Org.BouncyCastle.Math b[0] &= mask; // ensure the leading bit is 1 (to meet the strength requirement) - b[0] |= (byte)(1 << (7 - xBits)); + b[0] |= lead; // ensure the trailing bit is 1 (i.e. must be odd) b[nBytes - 1] |= 1; @@ -702,21 +703,15 @@ namespace Org.BouncyCastle.Math if (certainty < 1) break; - if (CheckProbablePrime(certainty, random)) + if (CheckProbablePrime(certainty, random, true)) break; - if (bitLength > 32) + for (int j = 1; j < (magnitude.Length - 1); ++j) { - for (int rep = 0; rep < 10000; ++rep) - { - int n = 33 + random.Next(bitLength - 2); - this.magnitude[this.magnitude.Length - (n >> 5)] ^= (1 << (n & 31)); - this.magnitude[this.magnitude.Length - 1] ^= ((random.Next() + 1) << 1); - this.mQuote = 0; + this.magnitude[j] ^= random.Next(); - if (CheckProbablePrime(certainty, random)) - return; - } + if (CheckProbablePrime(certainty, random, true)) + return; } } } @@ -968,7 +963,7 @@ namespace Org.BouncyCastle.Math // // BitLen(value) is the number of bits in value. // - private static int BitLen(int w) + internal static int BitLen(int w) { uint v = (uint)w; uint t = v >> 24; @@ -1340,8 +1335,12 @@ namespace Org.BouncyCastle.Math * probability of 1 - (1/2)**certainty. * <p>From Knuth Vol 2, pg 395.</p> */ - public bool IsProbablePrime( - int certainty) + public bool IsProbablePrime(int certainty) + { + return IsProbablePrime(certainty, false); + } + + internal bool IsProbablePrime(int certainty, bool randomlySelected) { if (certainty <= 0) return true; @@ -1354,12 +1353,10 @@ namespace Org.BouncyCastle.Math if (n.Equals(One)) return false; - return n.CheckProbablePrime(certainty, RandomSource); + return n.CheckProbablePrime(certainty, RandomSource, randomlySelected); } - private bool CheckProbablePrime( - int certainty, - Random random) + private bool CheckProbablePrime(int certainty, Random random, bool randomlySelected) { Debug.Assert(certainty > 0); Debug.Assert(CompareTo(Two) > 0); @@ -1395,7 +1392,7 @@ namespace Org.BouncyCastle.Math // TODO Is it worth trying to create a hybrid of these two? - return RabinMillerTest(certainty, random); + return RabinMillerTest(certainty, random, randomlySelected); // return SolovayStrassenTest(certainty, random); // bool rbTest = RabinMillerTest(certainty, random); @@ -1408,10 +1405,36 @@ namespace Org.BouncyCastle.Math public bool RabinMillerTest(int certainty, Random random) { + return RabinMillerTest(certainty, random, false); + } + + internal bool RabinMillerTest(int certainty, Random random, bool randomlySelected) + { + int bits = BitLength; + Debug.Assert(certainty > 0); - Debug.Assert(BitLength > 2); + Debug.Assert(bits > 2); Debug.Assert(TestBit(0)); + int iterations = ((certainty - 1) / 2) + 1; + if (randomlySelected) + { + int itersFor100Cert = bits >= 1024 ? 4 + : bits >= 512 ? 8 + : bits >= 256 ? 16 + : 50; + + if (certainty < 100) + { + iterations = System.Math.Min(itersFor100Cert, iterations); + } + else + { + iterations -= 50; + iterations += itersFor100Cert; + } + } + // let n = 1 + d . 2^s BigInteger n = this; int s = n.GetLowestSetBitMaskFirst(-1 << 1); @@ -1449,10 +1472,8 @@ namespace Org.BouncyCastle.Math return false; } } - - certainty -= 2; // composites pass for only 1/4 possible 'a' } - while (certainty > 0); + while (--iterations > 0); return true; } @@ -2494,7 +2515,7 @@ namespace Org.BouncyCastle.Math BigInteger n = Inc().SetBit(0); - while (!n.CheckProbablePrime(100, RandomSource)) + while (!n.CheckProbablePrime(100, RandomSource, false)) { n = n.Add(Two); }