Primes.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto;
  5. using BestHTTP.SecureProtocol.Org.BouncyCastle.Security;
  6. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  7. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Math
  8. {
  9. /**
  10. * Utility methods for generating primes and testing for primality.
  11. */
  12. public abstract class Primes
  13. {
  14. public static readonly int SmallFactorLimit = 211;
  15. private static readonly BigInteger One = BigInteger.One;
  16. private static readonly BigInteger Two = BigInteger.Two;
  17. private static readonly BigInteger Three = BigInteger.Three;
  18. /**
  19. * Used to return the output from the
  20. * {@linkplain Primes#enhancedMRProbablePrimeTest(BigInteger, SecureRandom, int) Enhanced
  21. * Miller-Rabin Probabilistic Primality Test}
  22. */
  23. public class MROutput
  24. {
  25. internal static MROutput ProbablyPrime()
  26. {
  27. return new MROutput(false, null);
  28. }
  29. internal static MROutput ProvablyCompositeWithFactor(BigInteger factor)
  30. {
  31. return new MROutput(true, factor);
  32. }
  33. internal static MROutput ProvablyCompositeNotPrimePower()
  34. {
  35. return new MROutput(true, null);
  36. }
  37. private readonly bool mProvablyComposite;
  38. private readonly BigInteger mFactor;
  39. private MROutput(bool provablyComposite, BigInteger factor)
  40. {
  41. this.mProvablyComposite = provablyComposite;
  42. this.mFactor = factor;
  43. }
  44. public BigInteger Factor
  45. {
  46. get { return mFactor; }
  47. }
  48. public bool IsProvablyComposite
  49. {
  50. get { return mProvablyComposite; }
  51. }
  52. public bool IsNotPrimePower
  53. {
  54. get { return mProvablyComposite && mFactor == null; }
  55. }
  56. }
  57. /**
  58. * Used to return the output from the {@linkplain Primes#generateSTRandomPrime(Digest, int, byte[]) Shawe-Taylor Random_Prime Routine}
  59. */
  60. public class STOutput
  61. {
  62. private readonly BigInteger mPrime;
  63. private readonly byte[] mPrimeSeed;
  64. private readonly int mPrimeGenCounter;
  65. internal STOutput(BigInteger prime, byte[] primeSeed, int primeGenCounter)
  66. {
  67. this.mPrime = prime;
  68. this.mPrimeSeed = primeSeed;
  69. this.mPrimeGenCounter = primeGenCounter;
  70. }
  71. public BigInteger Prime
  72. {
  73. get { return mPrime; }
  74. }
  75. public byte[] PrimeSeed
  76. {
  77. get { return mPrimeSeed; }
  78. }
  79. public int PrimeGenCounter
  80. {
  81. get { return mPrimeGenCounter; }
  82. }
  83. }
  84. /**
  85. * FIPS 186-4 C.6 Shawe-Taylor Random_Prime Routine
  86. *
  87. * Construct a provable prime number using a hash function.
  88. *
  89. * @param hash
  90. * the {@link Digest} instance to use (as "Hash()"). Cannot be null.
  91. * @param length
  92. * the length (in bits) of the prime to be generated. Must be at least 2.
  93. * @param inputSeed
  94. * the seed to be used for the generation of the requested prime. Cannot be null or
  95. * empty.
  96. * @return an {@link STOutput} instance containing the requested prime.
  97. */
  98. public static STOutput GenerateSTRandomPrime(IDigest hash, int length, byte[] inputSeed)
  99. {
  100. if (hash == null)
  101. throw new ArgumentNullException("hash");
  102. if (length < 2)
  103. throw new ArgumentException("must be >= 2", "length");
  104. if (inputSeed == null)
  105. throw new ArgumentNullException("inputSeed");
  106. if (inputSeed.Length == 0)
  107. throw new ArgumentException("cannot be empty", "inputSeed");
  108. return ImplSTRandomPrime(hash, length, Arrays.Clone(inputSeed));
  109. }
  110. /**
  111. * FIPS 186-4 C.3.2 Enhanced Miller-Rabin Probabilistic Primality Test
  112. *
  113. * Run several iterations of the Miller-Rabin algorithm with randomly-chosen bases. This is an
  114. * alternative to {@link #isMRProbablePrime(BigInteger, SecureRandom, int)} that provides more
  115. * information about a composite candidate, which may be useful when generating or validating
  116. * RSA moduli.
  117. *
  118. * @param candidate
  119. * the {@link BigInteger} instance to test for primality.
  120. * @param random
  121. * the source of randomness to use to choose bases.
  122. * @param iterations
  123. * the number of randomly-chosen bases to perform the test for.
  124. * @return an {@link MROutput} instance that can be further queried for details.
  125. */
  126. public static MROutput EnhancedMRProbablePrimeTest(BigInteger candidate, SecureRandom random, int iterations)
  127. {
  128. CheckCandidate(candidate, "candidate");
  129. if (random == null)
  130. throw new ArgumentNullException("random");
  131. if (iterations < 1)
  132. throw new ArgumentException("must be > 0", "iterations");
  133. if (candidate.BitLength == 2)
  134. return MROutput.ProbablyPrime();
  135. if (!candidate.TestBit(0))
  136. return MROutput.ProvablyCompositeWithFactor(Two);
  137. BigInteger w = candidate;
  138. BigInteger wSubOne = candidate.Subtract(One);
  139. BigInteger wSubTwo = candidate.Subtract(Two);
  140. int a = wSubOne.GetLowestSetBit();
  141. BigInteger m = wSubOne.ShiftRight(a);
  142. for (int i = 0; i < iterations; ++i)
  143. {
  144. BigInteger b = BigIntegers.CreateRandomInRange(Two, wSubTwo, random);
  145. BigInteger g = b.Gcd(w);
  146. if (g.CompareTo(One) > 0)
  147. return MROutput.ProvablyCompositeWithFactor(g);
  148. BigInteger z = b.ModPow(m, w);
  149. if (z.Equals(One) || z.Equals(wSubOne))
  150. continue;
  151. bool primeToBase = false;
  152. BigInteger x = z;
  153. for (int j = 1; j < a; ++j)
  154. {
  155. z = z.ModPow(Two, w);
  156. if (z.Equals(wSubOne))
  157. {
  158. primeToBase = true;
  159. break;
  160. }
  161. if (z.Equals(One))
  162. break;
  163. x = z;
  164. }
  165. if (!primeToBase)
  166. {
  167. if (!z.Equals(One))
  168. {
  169. x = z;
  170. z = z.ModPow(Two, w);
  171. if (!z.Equals(One))
  172. {
  173. x = z;
  174. }
  175. }
  176. g = x.Subtract(One).Gcd(w);
  177. if (g.CompareTo(One) > 0)
  178. return MROutput.ProvablyCompositeWithFactor(g);
  179. return MROutput.ProvablyCompositeNotPrimePower();
  180. }
  181. }
  182. return MROutput.ProbablyPrime();
  183. }
  184. /**
  185. * A fast check for small divisors, up to some implementation-specific limit.
  186. *
  187. * @param candidate
  188. * the {@link BigInteger} instance to test for division by small factors.
  189. *
  190. * @return <code>true</code> if the candidate is found to have any small factors,
  191. * <code>false</code> otherwise.
  192. */
  193. public static bool HasAnySmallFactors(BigInteger candidate)
  194. {
  195. CheckCandidate(candidate, "candidate");
  196. return ImplHasAnySmallFactors(candidate);
  197. }
  198. /**
  199. * FIPS 186-4 C.3.1 Miller-Rabin Probabilistic Primality Test
  200. *
  201. * Run several iterations of the Miller-Rabin algorithm with randomly-chosen bases.
  202. *
  203. * @param candidate
  204. * the {@link BigInteger} instance to test for primality.
  205. * @param random
  206. * the source of randomness to use to choose bases.
  207. * @param iterations
  208. * the number of randomly-chosen bases to perform the test for.
  209. * @return <code>false</code> if any witness to compositeness is found amongst the chosen bases
  210. * (so <code>candidate</code> is definitely NOT prime), or else <code>true</code>
  211. * (indicating primality with some probability dependent on the number of iterations
  212. * that were performed).
  213. */
  214. public static bool IsMRProbablePrime(BigInteger candidate, SecureRandom random, int iterations)
  215. {
  216. CheckCandidate(candidate, "candidate");
  217. if (random == null)
  218. throw new ArgumentException("cannot be null", "random");
  219. if (iterations < 1)
  220. throw new ArgumentException("must be > 0", "iterations");
  221. if (candidate.BitLength == 2)
  222. return true;
  223. if (!candidate.TestBit(0))
  224. return false;
  225. BigInteger w = candidate;
  226. BigInteger wSubOne = candidate.Subtract(One);
  227. BigInteger wSubTwo = candidate.Subtract(Two);
  228. int a = wSubOne.GetLowestSetBit();
  229. BigInteger m = wSubOne.ShiftRight(a);
  230. for (int i = 0; i < iterations; ++i)
  231. {
  232. BigInteger b = BigIntegers.CreateRandomInRange(Two, wSubTwo, random);
  233. if (!ImplMRProbablePrimeToBase(w, wSubOne, m, a, b))
  234. return false;
  235. }
  236. return true;
  237. }
  238. /**
  239. * FIPS 186-4 C.3.1 Miller-Rabin Probabilistic Primality Test (to a fixed base).
  240. *
  241. * Run a single iteration of the Miller-Rabin algorithm against the specified base.
  242. *
  243. * @param candidate
  244. * the {@link BigInteger} instance to test for primality.
  245. * @param baseValue
  246. * the base value to use for this iteration.
  247. * @return <code>false</code> if the specified base is a witness to compositeness (so
  248. * <code>candidate</code> is definitely NOT prime), or else <code>true</code>.
  249. */
  250. public static bool IsMRProbablePrimeToBase(BigInteger candidate, BigInteger baseValue)
  251. {
  252. CheckCandidate(candidate, "candidate");
  253. CheckCandidate(baseValue, "baseValue");
  254. if (baseValue.CompareTo(candidate.Subtract(One)) >= 0)
  255. throw new ArgumentException("must be < ('candidate' - 1)", "baseValue");
  256. if (candidate.BitLength == 2)
  257. return true;
  258. BigInteger w = candidate;
  259. BigInteger wSubOne = candidate.Subtract(One);
  260. int a = wSubOne.GetLowestSetBit();
  261. BigInteger m = wSubOne.ShiftRight(a);
  262. return ImplMRProbablePrimeToBase(w, wSubOne, m, a, baseValue);
  263. }
  264. private static void CheckCandidate(BigInteger n, string name)
  265. {
  266. if (n == null || n.SignValue < 1 || n.BitLength < 2)
  267. throw new ArgumentException("must be non-null and >= 2", name);
  268. }
  269. private static bool ImplHasAnySmallFactors(BigInteger x)
  270. {
  271. /*
  272. * Bundle trial divisors into ~32-bit moduli then use fast tests on the ~32-bit remainders.
  273. */
  274. int m = 2 * 3 * 5 * 7 * 11 * 13 * 17 * 19 * 23;
  275. int r = x.Mod(BigInteger.ValueOf(m)).IntValue;
  276. if ((r % 2) == 0 || (r % 3) == 0 || (r % 5) == 0 || (r % 7) == 0 || (r % 11) == 0 || (r % 13) == 0
  277. || (r % 17) == 0 || (r % 19) == 0 || (r % 23) == 0)
  278. {
  279. return true;
  280. }
  281. m = 29 * 31 * 37 * 41 * 43;
  282. r = x.Mod(BigInteger.ValueOf(m)).IntValue;
  283. if ((r % 29) == 0 || (r % 31) == 0 || (r % 37) == 0 || (r % 41) == 0 || (r % 43) == 0)
  284. {
  285. return true;
  286. }
  287. m = 47 * 53 * 59 * 61 * 67;
  288. r = x.Mod(BigInteger.ValueOf(m)).IntValue;
  289. if ((r % 47) == 0 || (r % 53) == 0 || (r % 59) == 0 || (r % 61) == 0 || (r % 67) == 0)
  290. {
  291. return true;
  292. }
  293. m = 71 * 73 * 79 * 83;
  294. r = x.Mod(BigInteger.ValueOf(m)).IntValue;
  295. if ((r % 71) == 0 || (r % 73) == 0 || (r % 79) == 0 || (r % 83) == 0)
  296. {
  297. return true;
  298. }
  299. m = 89 * 97 * 101 * 103;
  300. r = x.Mod(BigInteger.ValueOf(m)).IntValue;
  301. if ((r % 89) == 0 || (r % 97) == 0 || (r % 101) == 0 || (r % 103) == 0)
  302. {
  303. return true;
  304. }
  305. m = 107 * 109 * 113 * 127;
  306. r = x.Mod(BigInteger.ValueOf(m)).IntValue;
  307. if ((r % 107) == 0 || (r % 109) == 0 || (r % 113) == 0 || (r % 127) == 0)
  308. {
  309. return true;
  310. }
  311. m = 131 * 137 * 139 * 149;
  312. r = x.Mod(BigInteger.ValueOf(m)).IntValue;
  313. if ((r % 131) == 0 || (r % 137) == 0 || (r % 139) == 0 || (r % 149) == 0)
  314. {
  315. return true;
  316. }
  317. m = 151 * 157 * 163 * 167;
  318. r = x.Mod(BigInteger.ValueOf(m)).IntValue;
  319. if ((r % 151) == 0 || (r % 157) == 0 || (r % 163) == 0 || (r % 167) == 0)
  320. {
  321. return true;
  322. }
  323. m = 173 * 179 * 181 * 191;
  324. r = x.Mod(BigInteger.ValueOf(m)).IntValue;
  325. if ((r % 173) == 0 || (r % 179) == 0 || (r % 181) == 0 || (r % 191) == 0)
  326. {
  327. return true;
  328. }
  329. m = 193 * 197 * 199 * 211;
  330. r = x.Mod(BigInteger.ValueOf(m)).IntValue;
  331. if ((r % 193) == 0 || (r % 197) == 0 || (r % 199) == 0 || (r % 211) == 0)
  332. {
  333. return true;
  334. }
  335. /*
  336. * NOTE: Unit tests depend on SMALL_FACTOR_LIMIT matching the
  337. * highest small factor tested here.
  338. */
  339. return false;
  340. }
  341. private static bool ImplMRProbablePrimeToBase(BigInteger w, BigInteger wSubOne, BigInteger m, int a, BigInteger b)
  342. {
  343. BigInteger z = b.ModPow(m, w);
  344. if (z.Equals(One) || z.Equals(wSubOne))
  345. return true;
  346. bool result = false;
  347. for (int j = 1; j < a; ++j)
  348. {
  349. z = z.ModPow(Two, w);
  350. if (z.Equals(wSubOne))
  351. {
  352. result = true;
  353. break;
  354. }
  355. if (z.Equals(One))
  356. return false;
  357. }
  358. return result;
  359. }
  360. private static STOutput ImplSTRandomPrime(IDigest d, int length, byte[] primeSeed)
  361. {
  362. int dLen = d.GetDigestSize();
  363. if (length < 33)
  364. {
  365. int primeGenCounter = 0;
  366. byte[] c0 = new byte[dLen];
  367. byte[] c1 = new byte[dLen];
  368. for (;;)
  369. {
  370. Hash(d, primeSeed, c0, 0);
  371. Inc(primeSeed, 1);
  372. Hash(d, primeSeed, c1, 0);
  373. Inc(primeSeed, 1);
  374. uint c = Extract32(c0) ^ Extract32(c1);
  375. c &= (uint.MaxValue >> (32 - length));
  376. c |= (1U << (length - 1)) | 1U;
  377. ++primeGenCounter;
  378. if (IsPrime32(c))
  379. {
  380. return new STOutput(BigInteger.ValueOf((long)c), primeSeed, primeGenCounter);
  381. }
  382. if (primeGenCounter > (4 * length))
  383. {
  384. throw new InvalidOperationException("Too many iterations in Shawe-Taylor Random_Prime Routine");
  385. }
  386. }
  387. }
  388. STOutput rec = ImplSTRandomPrime(d, (length + 3)/2, primeSeed);
  389. {
  390. BigInteger c0 = rec.Prime;
  391. primeSeed = rec.PrimeSeed;
  392. int primeGenCounter = rec.PrimeGenCounter;
  393. int outlen = 8 * dLen;
  394. int iterations = (length - 1)/outlen;
  395. int oldCounter = primeGenCounter;
  396. BigInteger x = HashGen(d, primeSeed, iterations + 1);
  397. x = x.Mod(One.ShiftLeft(length - 1)).SetBit(length - 1);
  398. BigInteger c0x2 = c0.ShiftLeft(1);
  399. BigInteger tx2 = x.Subtract(One).Divide(c0x2).Add(One).ShiftLeft(1);
  400. int dt = 0;
  401. BigInteger c = tx2.Multiply(c0).Add(One);
  402. /*
  403. * TODO Since the candidate primes are generated by constant steps ('c0x2'),
  404. * sieving could be used here in place of the 'HasAnySmallFactors' approach.
  405. */
  406. for (;;)
  407. {
  408. if (c.BitLength > length)
  409. {
  410. tx2 = One.ShiftLeft(length - 1).Subtract(One).Divide(c0x2).Add(One).ShiftLeft(1);
  411. c = tx2.Multiply(c0).Add(One);
  412. }
  413. ++primeGenCounter;
  414. /*
  415. * This is an optimization of the original algorithm, using trial division to screen out
  416. * many non-primes quickly.
  417. *
  418. * NOTE: 'primeSeed' is still incremented as if we performed the full check!
  419. */
  420. if (!ImplHasAnySmallFactors(c))
  421. {
  422. BigInteger a = HashGen(d, primeSeed, iterations + 1);
  423. a = a.Mod(c.Subtract(Three)).Add(Two);
  424. tx2 = tx2.Add(BigInteger.ValueOf(dt));
  425. dt = 0;
  426. BigInteger z = a.ModPow(tx2, c);
  427. if (c.Gcd(z.Subtract(One)).Equals(One) && z.ModPow(c0, c).Equals(One))
  428. {
  429. return new STOutput(c, primeSeed, primeGenCounter);
  430. }
  431. }
  432. else
  433. {
  434. Inc(primeSeed, iterations + 1);
  435. }
  436. if (primeGenCounter >= ((4 * length) + oldCounter))
  437. {
  438. throw new InvalidOperationException("Too many iterations in Shawe-Taylor Random_Prime Routine");
  439. }
  440. dt += 2;
  441. c = c.Add(c0x2);
  442. }
  443. }
  444. }
  445. private static uint Extract32(byte[] bs)
  446. {
  447. uint result = 0;
  448. int count = System.Math.Min(4, bs.Length);
  449. for (int i = 0; i < count; ++i)
  450. {
  451. uint b = bs[bs.Length - (i + 1)];
  452. result |= (b << (8 * i));
  453. }
  454. return result;
  455. }
  456. private static void Hash(IDigest d, byte[] input, byte[] output, int outPos)
  457. {
  458. d.BlockUpdate(input, 0, input.Length);
  459. d.DoFinal(output, outPos);
  460. }
  461. private static BigInteger HashGen(IDigest d, byte[] seed, int count)
  462. {
  463. int dLen = d.GetDigestSize();
  464. int pos = count * dLen;
  465. byte[] buf = new byte[pos];
  466. for (int i = 0; i < count; ++i)
  467. {
  468. pos -= dLen;
  469. Hash(d, seed, buf, pos);
  470. Inc(seed, 1);
  471. }
  472. return new BigInteger(1, buf);
  473. }
  474. private static void Inc(byte[] seed, int c)
  475. {
  476. int pos = seed.Length;
  477. while (c > 0 && --pos >= 0)
  478. {
  479. c += seed[pos];
  480. seed[pos] = (byte)c;
  481. c >>= 8;
  482. }
  483. }
  484. private static bool IsPrime32(uint x)
  485. {
  486. /*
  487. * Use wheel factorization with 2, 3, 5 to select trial divisors.
  488. */
  489. if (x <= 5)
  490. {
  491. return x == 2 || x == 3 || x == 5;
  492. }
  493. if ((x & 1) == 0 || (x % 3) == 0 || (x % 5) == 0)
  494. {
  495. return false;
  496. }
  497. uint[] ds = new uint[]{ 1, 7, 11, 13, 17, 19, 23, 29 };
  498. uint b = 0;
  499. for (int pos = 1; ; pos = 0)
  500. {
  501. /*
  502. * Trial division by wheel-selected divisors
  503. */
  504. while (pos < ds.Length)
  505. {
  506. uint d = b + ds[pos];
  507. if (x % d == 0)
  508. {
  509. return x < 30;
  510. }
  511. ++pos;
  512. }
  513. b += 30;
  514. if ((b >> 16 != 0) || (b * b >= x))
  515. {
  516. return true;
  517. }
  518. }
  519. }
  520. }
  521. }
  522. #pragma warning restore
  523. #endif