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);
}
|