GOST3410ParametersGenerator.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
  5. using BestHTTP.SecureProtocol.Org.BouncyCastle.Math;
  6. using BestHTTP.SecureProtocol.Org.BouncyCastle.Security;
  7. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Generators
  8. {
  9. /**
  10. * generate suitable parameters for GOST3410.
  11. */
  12. public class Gost3410ParametersGenerator
  13. {
  14. private int size;
  15. private int typeproc;
  16. private SecureRandom init_random;
  17. /**
  18. * initialise the key generator.
  19. *
  20. * @param size size of the key
  21. * @param typeProcedure type procedure A,B = 1; A',B' - else
  22. * @param random random byte source.
  23. */
  24. public void Init(
  25. int size,
  26. int typeProcedure,
  27. SecureRandom random)
  28. {
  29. this.size = size;
  30. this.typeproc = typeProcedure;
  31. this.init_random = random;
  32. }
  33. //Procedure A
  34. private int procedure_A(int x0, int c, BigInteger[] pq, int size)
  35. {
  36. //Verify and perform condition: 0<x<2^16; 0<c<2^16; c - odd.
  37. while(x0<0 || x0>65536)
  38. {
  39. x0 = init_random.NextInt()/32768;
  40. }
  41. while((c<0 || c>65536) || (c/2==0))
  42. {
  43. c = init_random.NextInt()/32768 + 1;
  44. }
  45. BigInteger C = BigInteger.ValueOf(c);
  46. BigInteger constA16 = BigInteger.ValueOf(19381);
  47. //step1
  48. BigInteger[] y = new BigInteger[1]; // begin length = 1
  49. y[0] = BigInteger.ValueOf(x0);
  50. //step 2
  51. int[] t = new int[1]; // t - orders; begin length = 1
  52. t[0] = size;
  53. int s = 0;
  54. for (int i=0; t[i]>=17; i++)
  55. {
  56. // extension array t
  57. int[] tmp_t = new int[t.Length + 1]; ///////////////
  58. Array.Copy(t,0,tmp_t,0,t.Length); // extension
  59. t = new int[tmp_t.Length]; // array t
  60. Array.Copy(tmp_t, 0, t, 0, tmp_t.Length); ///////////////
  61. t[i+1] = t[i]/2;
  62. s = i+1;
  63. }
  64. //step3
  65. BigInteger[] p = new BigInteger[s+1];
  66. p[s] = new BigInteger("8003",16); //set min prime number length 16 bit
  67. int m = s-1; //step4
  68. for (int i=0; i<s; i++)
  69. {
  70. int rm = t[m]/16; //step5
  71. step6: for(;;)
  72. {
  73. //step 6
  74. BigInteger[] tmp_y = new BigInteger[y.Length]; ////////////////
  75. Array.Copy(y,0,tmp_y,0,y.Length); // extension
  76. y = new BigInteger[rm+1]; // array y
  77. Array.Copy(tmp_y,0,y,0,tmp_y.Length); ////////////////
  78. for (int j=0; j<rm; j++)
  79. {
  80. y[j+1] = (y[j].Multiply(constA16).Add(C)).Mod(BigInteger.Two.Pow(16));
  81. }
  82. //step 7
  83. BigInteger Ym = BigInteger.Zero;
  84. for (int j=0; j<rm; j++)
  85. {
  86. Ym = Ym.Add(y[j].ShiftLeft(16*j));
  87. }
  88. y[0] = y[rm]; //step 8
  89. //step 9
  90. BigInteger N = BigInteger.One.ShiftLeft(t[m]-1).Divide(p[m+1]).Add(
  91. Ym.ShiftLeft(t[m]-1).Divide(p[m+1].ShiftLeft(16*rm)));
  92. if (N.TestBit(0))
  93. {
  94. N = N.Add(BigInteger.One);
  95. }
  96. //step 10
  97. for(;;)
  98. {
  99. //step 11
  100. BigInteger NByLastP = N.Multiply(p[m+1]);
  101. if (NByLastP.BitLength > t[m])
  102. {
  103. goto step6; //step 12
  104. }
  105. p[m] = NByLastP.Add(BigInteger.One);
  106. //step13
  107. if (BigInteger.Two.ModPow(NByLastP, p[m]).CompareTo(BigInteger.One) == 0
  108. && BigInteger.Two.ModPow(N, p[m]).CompareTo(BigInteger.One) != 0)
  109. {
  110. break;
  111. }
  112. N = N.Add(BigInteger.Two);
  113. }
  114. if (--m < 0)
  115. {
  116. pq[0] = p[0];
  117. pq[1] = p[1];
  118. return y[0].IntValue; //return for procedure B step 2
  119. }
  120. break; //step 14
  121. }
  122. }
  123. return y[0].IntValue;
  124. }
  125. //Procedure A'
  126. private long procedure_Aa(long x0, long c, BigInteger[] pq, int size)
  127. {
  128. //Verify and perform condition: 0<x<2^32; 0<c<2^32; c - odd.
  129. while(x0<0 || x0>4294967296L)
  130. {
  131. x0 = init_random.NextInt()*2;
  132. }
  133. while((c<0 || c>4294967296L) || (c/2==0))
  134. {
  135. c = init_random.NextInt()*2+1;
  136. }
  137. BigInteger C = BigInteger.ValueOf(c);
  138. BigInteger constA32 = BigInteger.ValueOf(97781173);
  139. //step1
  140. BigInteger[] y = new BigInteger[1]; // begin length = 1
  141. y[0] = BigInteger.ValueOf(x0);
  142. //step 2
  143. int[] t = new int[1]; // t - orders; begin length = 1
  144. t[0] = size;
  145. int s = 0;
  146. for (int i=0; t[i]>=33; i++)
  147. {
  148. // extension array t
  149. int[] tmp_t = new int[t.Length + 1]; ///////////////
  150. Array.Copy(t,0,tmp_t,0,t.Length); // extension
  151. t = new int[tmp_t.Length]; // array t
  152. Array.Copy(tmp_t, 0, t, 0, tmp_t.Length); ///////////////
  153. t[i+1] = t[i]/2;
  154. s = i+1;
  155. }
  156. //step3
  157. BigInteger[] p = new BigInteger[s+1];
  158. p[s] = new BigInteger("8000000B",16); //set min prime number length 32 bit
  159. int m = s-1; //step4
  160. for (int i=0; i<s; i++)
  161. {
  162. int rm = t[m]/32; //step5
  163. step6: for(;;)
  164. {
  165. //step 6
  166. BigInteger[] tmp_y = new BigInteger[y.Length]; ////////////////
  167. Array.Copy(y,0,tmp_y,0,y.Length); // extension
  168. y = new BigInteger[rm+1]; // array y
  169. Array.Copy(tmp_y,0,y,0,tmp_y.Length); ////////////////
  170. for (int j=0; j<rm; j++)
  171. {
  172. y[j+1] = (y[j].Multiply(constA32).Add(C)).Mod(BigInteger.Two.Pow(32));
  173. }
  174. //step 7
  175. BigInteger Ym = BigInteger.Zero;
  176. for (int j=0; j<rm; j++)
  177. {
  178. Ym = Ym.Add(y[j].ShiftLeft(32*j));
  179. }
  180. y[0] = y[rm]; //step 8
  181. //step 9
  182. BigInteger N = BigInteger.One.ShiftLeft(t[m]-1).Divide(p[m+1]).Add(
  183. Ym.ShiftLeft(t[m]-1).Divide(p[m+1].ShiftLeft(32*rm)));
  184. if (N.TestBit(0))
  185. {
  186. N = N.Add(BigInteger.One);
  187. }
  188. //step 10
  189. for(;;)
  190. {
  191. //step 11
  192. BigInteger NByLastP = N.Multiply(p[m+1]);
  193. if (NByLastP.BitLength > t[m])
  194. {
  195. goto step6; //step 12
  196. }
  197. p[m] = NByLastP.Add(BigInteger.One);
  198. //step13
  199. if (BigInteger.Two.ModPow(NByLastP, p[m]).CompareTo(BigInteger.One) == 0
  200. && BigInteger.Two.ModPow(N, p[m]).CompareTo(BigInteger.One) != 0)
  201. {
  202. break;
  203. }
  204. N = N.Add(BigInteger.Two);
  205. }
  206. if (--m < 0)
  207. {
  208. pq[0] = p[0];
  209. pq[1] = p[1];
  210. return y[0].LongValue; //return for procedure B' step 2
  211. }
  212. break; //step 14
  213. }
  214. }
  215. return y[0].LongValue;
  216. }
  217. //Procedure B
  218. private void procedure_B(int x0, int c, BigInteger[] pq)
  219. {
  220. //Verify and perform condition: 0<x<2^16; 0<c<2^16; c - odd.
  221. while(x0<0 || x0>65536)
  222. {
  223. x0 = init_random.NextInt()/32768;
  224. }
  225. while((c<0 || c>65536) || (c/2==0))
  226. {
  227. c = init_random.NextInt()/32768 + 1;
  228. }
  229. BigInteger [] qp = new BigInteger[2];
  230. BigInteger q = null, Q = null, p = null;
  231. BigInteger C = BigInteger.ValueOf(c);
  232. BigInteger constA16 = BigInteger.ValueOf(19381);
  233. //step1
  234. x0 = procedure_A(x0, c, qp, 256);
  235. q = qp[0];
  236. //step2
  237. x0 = procedure_A(x0, c, qp, 512);
  238. Q = qp[0];
  239. BigInteger[] y = new BigInteger[65];
  240. y[0] = BigInteger.ValueOf(x0);
  241. const int tp = 1024;
  242. BigInteger qQ = q.Multiply(Q);
  243. step3:
  244. for(;;)
  245. {
  246. //step 3
  247. for (int j=0; j<64; j++)
  248. {
  249. y[j+1] = (y[j].Multiply(constA16).Add(C)).Mod(BigInteger.Two.Pow(16));
  250. }
  251. //step 4
  252. BigInteger Y = BigInteger.Zero;
  253. for (int j=0; j<64; j++)
  254. {
  255. Y = Y.Add(y[j].ShiftLeft(16*j));
  256. }
  257. y[0] = y[64]; //step 5
  258. //step 6
  259. BigInteger N = BigInteger.One.ShiftLeft(tp-1).Divide(qQ).Add(
  260. Y.ShiftLeft(tp-1).Divide(qQ.ShiftLeft(1024)));
  261. if (N.TestBit(0))
  262. {
  263. N = N.Add(BigInteger.One);
  264. }
  265. //step 7
  266. for(;;)
  267. {
  268. //step 11
  269. BigInteger qQN = qQ.Multiply(N);
  270. if (qQN.BitLength > tp)
  271. {
  272. goto step3; //step 9
  273. }
  274. p = qQN.Add(BigInteger.One);
  275. //step10
  276. if (BigInteger.Two.ModPow(qQN, p).CompareTo(BigInteger.One) == 0
  277. && BigInteger.Two.ModPow(q.Multiply(N), p).CompareTo(BigInteger.One) != 0)
  278. {
  279. pq[0] = p;
  280. pq[1] = q;
  281. return;
  282. }
  283. N = N.Add(BigInteger.Two);
  284. }
  285. }
  286. }
  287. //Procedure B'
  288. private void procedure_Bb(long x0, long c, BigInteger[] pq)
  289. {
  290. //Verify and perform condition: 0<x<2^32; 0<c<2^32; c - odd.
  291. while(x0<0 || x0>4294967296L)
  292. {
  293. x0 = init_random.NextInt()*2;
  294. }
  295. while((c<0 || c>4294967296L) || (c/2==0))
  296. {
  297. c = init_random.NextInt()*2+1;
  298. }
  299. BigInteger [] qp = new BigInteger[2];
  300. BigInteger q = null, Q = null, p = null;
  301. BigInteger C = BigInteger.ValueOf(c);
  302. BigInteger constA32 = BigInteger.ValueOf(97781173);
  303. //step1
  304. x0 = procedure_Aa(x0, c, qp, 256);
  305. q = qp[0];
  306. //step2
  307. x0 = procedure_Aa(x0, c, qp, 512);
  308. Q = qp[0];
  309. BigInteger[] y = new BigInteger[33];
  310. y[0] = BigInteger.ValueOf(x0);
  311. const int tp = 1024;
  312. BigInteger qQ = q.Multiply(Q);
  313. step3:
  314. for(;;)
  315. {
  316. //step 3
  317. for (int j=0; j<32; j++)
  318. {
  319. y[j+1] = (y[j].Multiply(constA32).Add(C)).Mod(BigInteger.Two.Pow(32));
  320. }
  321. //step 4
  322. BigInteger Y = BigInteger.Zero;
  323. for (int j=0; j<32; j++)
  324. {
  325. Y = Y.Add(y[j].ShiftLeft(32*j));
  326. }
  327. y[0] = y[32]; //step 5
  328. //step 6
  329. BigInteger N = BigInteger.One.ShiftLeft(tp-1).Divide(qQ).Add(
  330. Y.ShiftLeft(tp-1).Divide(qQ.ShiftLeft(1024)));
  331. if (N.TestBit(0))
  332. {
  333. N = N.Add(BigInteger.One);
  334. }
  335. //step 7
  336. for(;;)
  337. {
  338. //step 11
  339. BigInteger qQN = qQ.Multiply(N);
  340. if (qQN.BitLength > tp)
  341. {
  342. goto step3; //step 9
  343. }
  344. p = qQN.Add(BigInteger.One);
  345. //step10
  346. if (BigInteger.Two.ModPow(qQN, p).CompareTo(BigInteger.One) == 0
  347. && BigInteger.Two.ModPow(q.Multiply(N), p).CompareTo(BigInteger.One) != 0)
  348. {
  349. pq[0] = p;
  350. pq[1] = q;
  351. return;
  352. }
  353. N = N.Add(BigInteger.Two);
  354. }
  355. }
  356. }
  357. /**
  358. * Procedure C
  359. * procedure generates the a value from the given p,q,
  360. * returning the a value.
  361. */
  362. private BigInteger procedure_C(BigInteger p, BigInteger q)
  363. {
  364. BigInteger pSub1 = p.Subtract(BigInteger.One);
  365. BigInteger pSub1Divq = pSub1.Divide(q);
  366. for(;;)
  367. {
  368. BigInteger d = new BigInteger(p.BitLength, init_random);
  369. // 1 < d < p-1
  370. if (d.CompareTo(BigInteger.One) > 0 && d.CompareTo(pSub1) < 0)
  371. {
  372. BigInteger a = d.ModPow(pSub1Divq, p);
  373. if (a.CompareTo(BigInteger.One) != 0)
  374. {
  375. return a;
  376. }
  377. }
  378. }
  379. }
  380. /**
  381. * which generates the p , q and a values from the given parameters,
  382. * returning the Gost3410Parameters object.
  383. */
  384. public Gost3410Parameters GenerateParameters()
  385. {
  386. BigInteger [] pq = new BigInteger[2];
  387. BigInteger q = null, p = null, a = null;
  388. int x0, c;
  389. long x0L, cL;
  390. if (typeproc==1)
  391. {
  392. x0 = init_random.NextInt();
  393. c = init_random.NextInt();
  394. switch(size)
  395. {
  396. case 512:
  397. procedure_A(x0, c, pq, 512);
  398. break;
  399. case 1024:
  400. procedure_B(x0, c, pq);
  401. break;
  402. default:
  403. throw new ArgumentException("Ooops! key size 512 or 1024 bit.");
  404. }
  405. p = pq[0]; q = pq[1];
  406. a = procedure_C(p, q);
  407. //System.out.println("p:"+p.toString(16)+"\n"+"q:"+q.toString(16)+"\n"+"a:"+a.toString(16));
  408. //System.out.println("p:"+p+"\n"+"q:"+q+"\n"+"a:"+a);
  409. return new Gost3410Parameters(p, q, a, new Gost3410ValidationParameters(x0, c));
  410. }
  411. else
  412. {
  413. x0L = init_random.NextLong();
  414. cL = init_random.NextLong();
  415. switch(size)
  416. {
  417. case 512:
  418. procedure_Aa(x0L, cL, pq, 512);
  419. break;
  420. case 1024:
  421. procedure_Bb(x0L, cL, pq);
  422. break;
  423. default:
  424. throw new InvalidOperationException("Ooops! key size 512 or 1024 bit.");
  425. }
  426. p = pq[0]; q = pq[1];
  427. a = procedure_C(p, q);
  428. //System.out.println("p:"+p.toString(16)+"\n"+"q:"+q.toString(16)+"\n"+"a:"+a.toString(16));
  429. //System.out.println("p:"+p+"\n"+"q:"+q+"\n"+"a:"+a);
  430. return new Gost3410Parameters(p, q, a, new Gost3410ValidationParameters(x0L, cL));
  431. }
  432. }
  433. }
  434. }
  435. #pragma warning restore
  436. #endif