NaccacheSternKeyPairGenerator.cs 7.2 KB

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