RsaKeyPairGenerator.cs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. using System;
  3. using Org.BouncyCastle.Crypto;
  4. using Org.BouncyCastle.Crypto.Parameters;
  5. using Org.BouncyCastle.Math;
  6. using Org.BouncyCastle.Math.EC.Multiplier;
  7. using Org.BouncyCastle.Utilities;
  8. namespace Org.BouncyCastle.Crypto.Generators
  9. {
  10. /**
  11. * an RSA key pair generator.
  12. */
  13. public class RsaKeyPairGenerator
  14. : IAsymmetricCipherKeyPairGenerator
  15. {
  16. private static readonly int[] SPECIAL_E_VALUES = new int[]{ 3, 5, 17, 257, 65537 };
  17. private static readonly int SPECIAL_E_HIGHEST = SPECIAL_E_VALUES[SPECIAL_E_VALUES.Length - 1];
  18. private static readonly int SPECIAL_E_BITS = BigInteger.ValueOf(SPECIAL_E_HIGHEST).BitLength;
  19. protected static readonly BigInteger One = BigInteger.One;
  20. protected static readonly BigInteger DefaultPublicExponent = BigInteger.ValueOf(0x10001);
  21. protected const int DefaultTests = 100;
  22. protected RsaKeyGenerationParameters parameters;
  23. public virtual void Init(
  24. KeyGenerationParameters parameters)
  25. {
  26. if (parameters is RsaKeyGenerationParameters)
  27. {
  28. this.parameters = (RsaKeyGenerationParameters)parameters;
  29. }
  30. else
  31. {
  32. this.parameters = new RsaKeyGenerationParameters(
  33. DefaultPublicExponent, parameters.Random, parameters.Strength, DefaultTests);
  34. }
  35. }
  36. public virtual AsymmetricCipherKeyPair GenerateKeyPair()
  37. {
  38. for (;;)
  39. {
  40. //
  41. // p and q values should have a length of half the strength in bits
  42. //
  43. int strength = parameters.Strength;
  44. int pBitlength = (strength + 1) / 2;
  45. int qBitlength = strength - pBitlength;
  46. int mindiffbits = strength / 3;
  47. int minWeight = strength >> 2;
  48. BigInteger e = parameters.PublicExponent;
  49. // TODO Consider generating safe primes for p, q (see DHParametersHelper.generateSafePrimes)
  50. // (then p-1 and q-1 will not consist of only small factors - see "Pollard's algorithm")
  51. BigInteger p = ChooseRandomPrime(pBitlength, e);
  52. BigInteger q, n;
  53. //
  54. // generate a modulus of the required length
  55. //
  56. for (;;)
  57. {
  58. q = ChooseRandomPrime(qBitlength, e);
  59. // p and q should not be too close together (or equal!)
  60. BigInteger diff = q.Subtract(p).Abs();
  61. if (diff.BitLength < mindiffbits)
  62. continue;
  63. //
  64. // calculate the modulus
  65. //
  66. n = p.Multiply(q);
  67. if (n.BitLength != strength)
  68. {
  69. //
  70. // if we get here our primes aren't big enough, make the largest
  71. // of the two p and try again
  72. //
  73. p = p.Max(q);
  74. continue;
  75. }
  76. /*
  77. * Require a minimum weight of the NAF representation, since low-weight composites may
  78. * be weak against a version of the number-field-sieve for factoring.
  79. *
  80. * See "The number field sieve for integers of low weight", Oliver Schirokauer.
  81. */
  82. if (WNafUtilities.GetNafWeight(n) < minWeight)
  83. {
  84. p = ChooseRandomPrime(pBitlength, e);
  85. continue;
  86. }
  87. break;
  88. }
  89. if (p.CompareTo(q) < 0)
  90. {
  91. BigInteger tmp = p;
  92. p = q;
  93. q = tmp;
  94. }
  95. BigInteger pSub1 = p.Subtract(One);
  96. BigInteger qSub1 = q.Subtract(One);
  97. //BigInteger phi = pSub1.Multiply(qSub1);
  98. BigInteger gcd = pSub1.Gcd(qSub1);
  99. BigInteger lcm = pSub1.Divide(gcd).Multiply(qSub1);
  100. //
  101. // calculate the private exponent
  102. //
  103. BigInteger d = e.ModInverse(lcm);
  104. if (d.BitLength <= qBitlength)
  105. continue;
  106. //
  107. // calculate the CRT factors
  108. //
  109. BigInteger dP = d.Remainder(pSub1);
  110. BigInteger dQ = d.Remainder(qSub1);
  111. BigInteger qInv = q.ModInverse(p);
  112. return new AsymmetricCipherKeyPair(
  113. new RsaKeyParameters(false, n, e),
  114. new RsaPrivateCrtKeyParameters(n, e, d, p, q, dP, dQ, qInv));
  115. }
  116. }
  117. /// <summary>Choose a random prime value for use with RSA</summary>
  118. /// <param name="bitlength">the bit-length of the returned prime</param>
  119. /// <param name="e">the RSA public exponent</param>
  120. /// <returns>a prime p, with (p-1) relatively prime to e</returns>
  121. protected virtual BigInteger ChooseRandomPrime(int bitlength, BigInteger e)
  122. {
  123. bool eIsKnownOddPrime = (e.BitLength <= SPECIAL_E_BITS) && Arrays.Contains(SPECIAL_E_VALUES, e.IntValue);
  124. for (;;)
  125. {
  126. BigInteger p = new BigInteger(bitlength, 1, parameters.Random);
  127. if (p.Mod(e).Equals(One))
  128. continue;
  129. if (!p.IsProbablePrime(parameters.Certainty, true))
  130. continue;
  131. if (!eIsKnownOddPrime && !e.Gcd(p.Subtract(One)).Equals(One))
  132. continue;
  133. return p;
  134. }
  135. }
  136. }
  137. }
  138. #endif