RsaKeyPairGenerator.cs 6.0 KB

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