NaccacheSternKeyPairGenerator.cs 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using System.Collections.Generic;
  5. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
  6. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math;
  7. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Security;
  8. namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Generators
  9. {
  10. /**
  11. * Key generation parameters for NaccacheStern cipher. For details on this cipher, please see
  12. *
  13. * http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf
  14. */
  15. public class NaccacheSternKeyPairGenerator
  16. : IAsymmetricCipherKeyPairGenerator
  17. {
  18. private static readonly int[] smallPrimes =
  19. {
  20. 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67,
  21. 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149,
  22. 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233,
  23. 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331,
  24. 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431,
  25. 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523,
  26. 541, 547, 557
  27. };
  28. private NaccacheSternKeyGenerationParameters param;
  29. /*
  30. * (non-Javadoc)
  31. *
  32. * @see org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator#init(org.bouncycastle.crypto.KeyGenerationParameters)
  33. */
  34. public void Init(KeyGenerationParameters parameters)
  35. {
  36. this.param = (NaccacheSternKeyGenerationParameters)parameters;
  37. }
  38. /*
  39. * (non-Javadoc)
  40. *
  41. * @see org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator#generateKeyPair()
  42. */
  43. public AsymmetricCipherKeyPair GenerateKeyPair()
  44. {
  45. int strength = param.Strength;
  46. SecureRandom rand = param.Random;
  47. int certainty = param.Certainty;
  48. var smallPrimes = FindFirstPrimes(param.CountSmallPrimes);
  49. smallPrimes = PermuteList(smallPrimes, rand);
  50. BigInteger u = BigInteger.One;
  51. BigInteger v = BigInteger.One;
  52. for (int i = 0; i < smallPrimes.Count / 2; i++)
  53. {
  54. u = u.Multiply((BigInteger)smallPrimes[i]);
  55. }
  56. for (int i = smallPrimes.Count / 2; i < smallPrimes.Count; i++)
  57. {
  58. v = v.Multiply((BigInteger)smallPrimes[i]);
  59. }
  60. BigInteger sigma = u.Multiply(v);
  61. // n = (2 a u _p + 1 ) ( 2 b v _q + 1)
  62. // -> |n| = strength
  63. // |2| = 1 in bits
  64. // -> |a| * |b| = |n| - |u| - |v| - |_p| - |_q| - |2| -|2|
  65. // remainingStrength = strength - sigma.bitLength() - _p.bitLength() -
  66. // _q.bitLength() - 1 -1
  67. int remainingStrength = strength - sigma.BitLength - 48;
  68. BigInteger a = GeneratePrime(remainingStrength / 2 + 1, certainty, rand);
  69. BigInteger b = GeneratePrime(remainingStrength / 2 + 1, certainty, rand);
  70. BigInteger _p;
  71. BigInteger _q;
  72. BigInteger p;
  73. BigInteger q;
  74. long tries = 0;
  75. BigInteger _2au = a.Multiply(u).ShiftLeft(1);
  76. BigInteger _2bv = b.Multiply(v).ShiftLeft(1);
  77. for (;;)
  78. {
  79. tries++;
  80. _p = GeneratePrime(24, certainty, rand);
  81. p = _p.Multiply(_2au).Add(BigInteger.One);
  82. if (!p.IsProbablePrime(certainty, true))
  83. continue;
  84. for (;;)
  85. {
  86. _q = GeneratePrime(24, certainty, rand);
  87. if (_p.Equals(_q))
  88. continue;
  89. q = _q.Multiply(_2bv).Add(BigInteger.One);
  90. if (q.IsProbablePrime(certainty, true))
  91. break;
  92. }
  93. if (!sigma.Gcd(_p.Multiply(_q)).Equals(BigInteger.One))
  94. {
  95. //Console.WriteLine("sigma.gcd(_p.mult(_q)) != 1!\n _p: " + _p +"\n _q: "+ _q );
  96. continue;
  97. }
  98. if (p.Multiply(q).BitLength < strength)
  99. {
  100. continue;
  101. }
  102. break;
  103. }
  104. BigInteger n = p.Multiply(q);
  105. BigInteger phi_n = p.Subtract(BigInteger.One).Multiply(q.Subtract(BigInteger.One));
  106. BigInteger g;
  107. tries = 0;
  108. for (;;)
  109. {
  110. // TODO After the first loop, just regenerate one randomly-selected gPart each time?
  111. var gParts = new List<BigInteger>();
  112. for (int ind = 0; ind != smallPrimes.Count; ind++)
  113. {
  114. BigInteger i = smallPrimes[ind];
  115. BigInteger e = phi_n.Divide(i);
  116. for (;;)
  117. {
  118. tries++;
  119. g = GeneratePrime(strength, certainty, rand);
  120. if (!g.ModPow(e, n).Equals(BigInteger.One))
  121. {
  122. gParts.Add(g);
  123. break;
  124. }
  125. }
  126. }
  127. g = BigInteger.One;
  128. for (int i = 0; i < smallPrimes.Count; i++)
  129. {
  130. BigInteger gPart = (BigInteger) gParts[i];
  131. BigInteger smallPrime = (BigInteger) smallPrimes[i];
  132. g = g.Multiply(gPart.ModPow(sigma.Divide(smallPrime), n)).Mod(n);
  133. }
  134. // make sure that g is not divisible by p_i or q_i
  135. bool divisible = false;
  136. for (int i = 0; i < smallPrimes.Count; i++)
  137. {
  138. if (g.ModPow(phi_n.Divide((BigInteger)smallPrimes[i]), n).Equals(BigInteger.One))
  139. {
  140. divisible = true;
  141. break;
  142. }
  143. }
  144. if (divisible)
  145. {
  146. continue;
  147. }
  148. // make sure that g has order > phi_n/4
  149. //if (g.ModPow(phi_n.Divide(BigInteger.ValueOf(4)), n).Equals(BigInteger.One))
  150. if (g.ModPow(phi_n.ShiftRight(2), n).Equals(BigInteger.One))
  151. {
  152. continue;
  153. }
  154. if (g.ModPow(phi_n.Divide(_p), n).Equals(BigInteger.One))
  155. {
  156. continue;
  157. }
  158. if (g.ModPow(phi_n.Divide(_q), n).Equals(BigInteger.One))
  159. {
  160. continue;
  161. }
  162. if (g.ModPow(phi_n.Divide(a), n).Equals(BigInteger.One))
  163. {
  164. continue;
  165. }
  166. if (g.ModPow(phi_n.Divide(b), n).Equals(BigInteger.One))
  167. {
  168. continue;
  169. }
  170. break;
  171. }
  172. return new AsymmetricCipherKeyPair(new NaccacheSternKeyParameters(false, g, n, sigma.BitLength),
  173. new NaccacheSternPrivateKeyParameters(g, n, sigma.BitLength, smallPrimes, phi_n));
  174. }
  175. private static BigInteger GeneratePrime(int bitLength, int certainty, SecureRandom rand)
  176. {
  177. return new BigInteger(bitLength, certainty, rand);
  178. }
  179. /**
  180. * Generates a permuted ArrayList from the original one. The original List
  181. * is not modified
  182. *
  183. * @param arr
  184. * the ArrayList to be permuted
  185. * @param rand
  186. * the source of Randomness for permutation
  187. * @return a new IList with the permuted elements.
  188. */
  189. private static IList<T> PermuteList<T>(IList<T> arr, SecureRandom rand)
  190. {
  191. // TODO Create a utility method for generating permutation of first 'n' integers
  192. var retval = new List<T>(arr.Count);
  193. foreach (var element in arr)
  194. {
  195. int index = rand.Next(retval.Count + 1);
  196. retval.Insert(index, element);
  197. }
  198. return retval;
  199. }
  200. /**
  201. * Finds the first 'count' primes starting with 3
  202. *
  203. * @param count
  204. * the number of primes to find
  205. * @return a vector containing the found primes as Integer
  206. */
  207. private static IList<BigInteger> FindFirstPrimes(int count)
  208. {
  209. var primes = new List<BigInteger>(count);
  210. for (int i = 0; i != count; i++)
  211. {
  212. primes.Add(BigInteger.ValueOf(smallPrimes[i]));
  213. }
  214. return primes;
  215. }
  216. }
  217. }
  218. #pragma warning restore
  219. #endif