Tnaf.cs 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. using System;
  3. namespace Org.BouncyCastle.Math.EC.Abc
  4. {
  5. /**
  6. * Class holding methods for point multiplication based on the window
  7. * τ-adic nonadjacent form (WTNAF). The algorithms are based on the
  8. * paper "Improved Algorithms for Arithmetic on Anomalous Binary Curves"
  9. * by Jerome A. Solinas. The paper first appeared in the Proceedings of
  10. * Crypto 1997.
  11. */
  12. internal class Tnaf
  13. {
  14. private static readonly BigInteger MinusOne = BigInteger.One.Negate();
  15. private static readonly BigInteger MinusTwo = BigInteger.Two.Negate();
  16. private static readonly BigInteger MinusThree = BigInteger.Three.Negate();
  17. private static readonly BigInteger Four = BigInteger.ValueOf(4);
  18. /**
  19. * The window width of WTNAF. The standard value of 4 is slightly less
  20. * than optimal for running time, but keeps space requirements for
  21. * precomputation low. For typical curves, a value of 5 or 6 results in
  22. * a better running time. When changing this value, the
  23. * <code>&#945;<sub>u</sub></code>'s must be computed differently, see
  24. * e.g. "Guide to Elliptic Curve Cryptography", Darrel Hankerson,
  25. * Alfred Menezes, Scott Vanstone, Springer-Verlag New York Inc., 2004,
  26. * p. 121-122
  27. */
  28. public const sbyte Width = 4;
  29. /**
  30. * 2<sup>4</sup>
  31. */
  32. public const sbyte Pow2Width = 16;
  33. /**
  34. * The <code>&#945;<sub>u</sub></code>'s for <code>a=0</code> as an array
  35. * of <code>ZTauElement</code>s.
  36. */
  37. public static readonly ZTauElement[] Alpha0 =
  38. {
  39. null,
  40. new ZTauElement(BigInteger.One, BigInteger.Zero), null,
  41. new ZTauElement(MinusThree, MinusOne), null,
  42. new ZTauElement(MinusOne, MinusOne), null,
  43. new ZTauElement(BigInteger.One, MinusOne), null
  44. };
  45. /**
  46. * The <code>&#945;<sub>u</sub></code>'s for <code>a=0</code> as an array
  47. * of TNAFs.
  48. */
  49. public static readonly sbyte[][] Alpha0Tnaf =
  50. {
  51. null, new sbyte[]{1}, null, new sbyte[]{-1, 0, 1}, null, new sbyte[]{1, 0, 1}, null, new sbyte[]{-1, 0, 0, 1}
  52. };
  53. /**
  54. * The <code>&#945;<sub>u</sub></code>'s for <code>a=1</code> as an array
  55. * of <code>ZTauElement</code>s.
  56. */
  57. public static readonly ZTauElement[] Alpha1 =
  58. {
  59. null,
  60. new ZTauElement(BigInteger.One, BigInteger.Zero), null,
  61. new ZTauElement(MinusThree, BigInteger.One), null,
  62. new ZTauElement(MinusOne, BigInteger.One), null,
  63. new ZTauElement(BigInteger.One, BigInteger.One), null
  64. };
  65. /**
  66. * The <code>&#945;<sub>u</sub></code>'s for <code>a=1</code> as an array
  67. * of TNAFs.
  68. */
  69. public static readonly sbyte[][] Alpha1Tnaf =
  70. {
  71. null, new sbyte[]{1}, null, new sbyte[]{-1, 0, 1}, null, new sbyte[]{1, 0, 1}, null, new sbyte[]{-1, 0, 0, -1}
  72. };
  73. /**
  74. * Computes the norm of an element <code>&#955;</code> of
  75. * <code><b>Z</b>[&#964;]</code>.
  76. * @param mu The parameter <code>&#956;</code> of the elliptic curve.
  77. * @param lambda The element <code>&#955;</code> of
  78. * <code><b>Z</b>[&#964;]</code>.
  79. * @return The norm of <code>&#955;</code>.
  80. */
  81. public static BigInteger Norm(sbyte mu, ZTauElement lambda)
  82. {
  83. BigInteger norm;
  84. // s1 = u^2
  85. BigInteger s1 = lambda.u.Multiply(lambda.u);
  86. // s2 = u * v
  87. BigInteger s2 = lambda.u.Multiply(lambda.v);
  88. // s3 = 2 * v^2
  89. BigInteger s3 = lambda.v.Multiply(lambda.v).ShiftLeft(1);
  90. if (mu == 1)
  91. {
  92. norm = s1.Add(s2).Add(s3);
  93. }
  94. else if (mu == -1)
  95. {
  96. norm = s1.Subtract(s2).Add(s3);
  97. }
  98. else
  99. {
  100. throw new ArgumentException("mu must be 1 or -1");
  101. }
  102. return norm;
  103. }
  104. /**
  105. * Computes the norm of an element <code>&#955;</code> of
  106. * <code><b>R</b>[&#964;]</code>, where <code>&#955; = u + v&#964;</code>
  107. * and <code>u</code> and <code>u</code> are real numbers (elements of
  108. * <code><b>R</b></code>).
  109. * @param mu The parameter <code>&#956;</code> of the elliptic curve.
  110. * @param u The real part of the element <code>&#955;</code> of
  111. * <code><b>R</b>[&#964;]</code>.
  112. * @param v The <code>&#964;</code>-adic part of the element
  113. * <code>&#955;</code> of <code><b>R</b>[&#964;]</code>.
  114. * @return The norm of <code>&#955;</code>.
  115. */
  116. public static SimpleBigDecimal Norm(sbyte mu, SimpleBigDecimal u, SimpleBigDecimal v)
  117. {
  118. SimpleBigDecimal norm;
  119. // s1 = u^2
  120. SimpleBigDecimal s1 = u.Multiply(u);
  121. // s2 = u * v
  122. SimpleBigDecimal s2 = u.Multiply(v);
  123. // s3 = 2 * v^2
  124. SimpleBigDecimal s3 = v.Multiply(v).ShiftLeft(1);
  125. if (mu == 1)
  126. {
  127. norm = s1.Add(s2).Add(s3);
  128. }
  129. else if (mu == -1)
  130. {
  131. norm = s1.Subtract(s2).Add(s3);
  132. }
  133. else
  134. {
  135. throw new ArgumentException("mu must be 1 or -1");
  136. }
  137. return norm;
  138. }
  139. /**
  140. * Rounds an element <code>&#955;</code> of <code><b>R</b>[&#964;]</code>
  141. * to an element of <code><b>Z</b>[&#964;]</code>, such that their difference
  142. * has minimal norm. <code>&#955;</code> is given as
  143. * <code>&#955; = &#955;<sub>0</sub> + &#955;<sub>1</sub>&#964;</code>.
  144. * @param lambda0 The component <code>&#955;<sub>0</sub></code>.
  145. * @param lambda1 The component <code>&#955;<sub>1</sub></code>.
  146. * @param mu The parameter <code>&#956;</code> of the elliptic curve. Must
  147. * equal 1 or -1.
  148. * @return The rounded element of <code><b>Z</b>[&#964;]</code>.
  149. * @throws ArgumentException if <code>lambda0</code> and
  150. * <code>lambda1</code> do not have same scale.
  151. */
  152. public static ZTauElement Round(SimpleBigDecimal lambda0,
  153. SimpleBigDecimal lambda1, sbyte mu)
  154. {
  155. int scale = lambda0.Scale;
  156. if (lambda1.Scale != scale)
  157. throw new ArgumentException("lambda0 and lambda1 do not have same scale");
  158. if (!((mu == 1) || (mu == -1)))
  159. throw new ArgumentException("mu must be 1 or -1");
  160. BigInteger f0 = lambda0.Round();
  161. BigInteger f1 = lambda1.Round();
  162. SimpleBigDecimal eta0 = lambda0.Subtract(f0);
  163. SimpleBigDecimal eta1 = lambda1.Subtract(f1);
  164. // eta = 2*eta0 + mu*eta1
  165. SimpleBigDecimal eta = eta0.Add(eta0);
  166. if (mu == 1)
  167. {
  168. eta = eta.Add(eta1);
  169. }
  170. else
  171. {
  172. // mu == -1
  173. eta = eta.Subtract(eta1);
  174. }
  175. // check1 = eta0 - 3*mu*eta1
  176. // check2 = eta0 + 4*mu*eta1
  177. SimpleBigDecimal threeEta1 = eta1.Add(eta1).Add(eta1);
  178. SimpleBigDecimal fourEta1 = threeEta1.Add(eta1);
  179. SimpleBigDecimal check1;
  180. SimpleBigDecimal check2;
  181. if (mu == 1)
  182. {
  183. check1 = eta0.Subtract(threeEta1);
  184. check2 = eta0.Add(fourEta1);
  185. }
  186. else
  187. {
  188. // mu == -1
  189. check1 = eta0.Add(threeEta1);
  190. check2 = eta0.Subtract(fourEta1);
  191. }
  192. sbyte h0 = 0;
  193. sbyte h1 = 0;
  194. // if eta >= 1
  195. if (eta.CompareTo(BigInteger.One) >= 0)
  196. {
  197. if (check1.CompareTo(MinusOne) < 0)
  198. {
  199. h1 = mu;
  200. }
  201. else
  202. {
  203. h0 = 1;
  204. }
  205. }
  206. else
  207. {
  208. // eta < 1
  209. if (check2.CompareTo(BigInteger.Two) >= 0)
  210. {
  211. h1 = mu;
  212. }
  213. }
  214. // if eta < -1
  215. if (eta.CompareTo(MinusOne) < 0)
  216. {
  217. if (check1.CompareTo(BigInteger.One) >= 0)
  218. {
  219. h1 = (sbyte)-mu;
  220. }
  221. else
  222. {
  223. h0 = -1;
  224. }
  225. }
  226. else
  227. {
  228. // eta >= -1
  229. if (check2.CompareTo(MinusTwo) < 0)
  230. {
  231. h1 = (sbyte)-mu;
  232. }
  233. }
  234. BigInteger q0 = f0.Add(BigInteger.ValueOf(h0));
  235. BigInteger q1 = f1.Add(BigInteger.ValueOf(h1));
  236. return new ZTauElement(q0, q1);
  237. }
  238. /**
  239. * Approximate division by <code>n</code>. For an integer
  240. * <code>k</code>, the value <code>&#955; = s k / n</code> is
  241. * computed to <code>c</code> bits of accuracy.
  242. * @param k The parameter <code>k</code>.
  243. * @param s The curve parameter <code>s<sub>0</sub></code> or
  244. * <code>s<sub>1</sub></code>.
  245. * @param vm The Lucas Sequence element <code>V<sub>m</sub></code>.
  246. * @param a The parameter <code>a</code> of the elliptic curve.
  247. * @param m The bit length of the finite field
  248. * <code><b>F</b><sub>m</sub></code>.
  249. * @param c The number of bits of accuracy, i.e. the scale of the returned
  250. * <code>SimpleBigDecimal</code>.
  251. * @return The value <code>&#955; = s k / n</code> computed to
  252. * <code>c</code> bits of accuracy.
  253. */
  254. public static SimpleBigDecimal ApproximateDivisionByN(BigInteger k,
  255. BigInteger s, BigInteger vm, sbyte a, int m, int c)
  256. {
  257. int _k = (m + 5)/2 + c;
  258. BigInteger ns = k.ShiftRight(m - _k - 2 + a);
  259. BigInteger gs = s.Multiply(ns);
  260. BigInteger hs = gs.ShiftRight(m);
  261. BigInteger js = vm.Multiply(hs);
  262. BigInteger gsPlusJs = gs.Add(js);
  263. BigInteger ls = gsPlusJs.ShiftRight(_k-c);
  264. if (gsPlusJs.TestBit(_k-c-1))
  265. {
  266. // round up
  267. ls = ls.Add(BigInteger.One);
  268. }
  269. return new SimpleBigDecimal(ls, c);
  270. }
  271. /**
  272. * Computes the <code>&#964;</code>-adic NAF (non-adjacent form) of an
  273. * element <code>&#955;</code> of <code><b>Z</b>[&#964;]</code>.
  274. * @param mu The parameter <code>&#956;</code> of the elliptic curve.
  275. * @param lambda The element <code>&#955;</code> of
  276. * <code><b>Z</b>[&#964;]</code>.
  277. * @return The <code>&#964;</code>-adic NAF of <code>&#955;</code>.
  278. */
  279. public static sbyte[] TauAdicNaf(sbyte mu, ZTauElement lambda)
  280. {
  281. if (!((mu == 1) || (mu == -1)))
  282. throw new ArgumentException("mu must be 1 or -1");
  283. BigInteger norm = Norm(mu, lambda);
  284. // Ceiling of log2 of the norm
  285. int log2Norm = norm.BitLength;
  286. // If length(TNAF) > 30, then length(TNAF) < log2Norm + 3.52
  287. int maxLength = log2Norm > 30 ? log2Norm + 4 : 34;
  288. // The array holding the TNAF
  289. sbyte[] u = new sbyte[maxLength];
  290. int i = 0;
  291. // The actual length of the TNAF
  292. int length = 0;
  293. BigInteger r0 = lambda.u;
  294. BigInteger r1 = lambda.v;
  295. while(!((r0.Equals(BigInteger.Zero)) && (r1.Equals(BigInteger.Zero))))
  296. {
  297. // If r0 is odd
  298. if (r0.TestBit(0))
  299. {
  300. u[i] = (sbyte) BigInteger.Two.Subtract((r0.Subtract(r1.ShiftLeft(1))).Mod(Four)).IntValue;
  301. // r0 = r0 - u[i]
  302. if (u[i] == 1)
  303. {
  304. r0 = r0.ClearBit(0);
  305. }
  306. else
  307. {
  308. // u[i] == -1
  309. r0 = r0.Add(BigInteger.One);
  310. }
  311. length = i;
  312. }
  313. else
  314. {
  315. u[i] = 0;
  316. }
  317. BigInteger t = r0;
  318. BigInteger s = r0.ShiftRight(1);
  319. if (mu == 1)
  320. {
  321. r0 = r1.Add(s);
  322. }
  323. else
  324. {
  325. // mu == -1
  326. r0 = r1.Subtract(s);
  327. }
  328. r1 = t.ShiftRight(1).Negate();
  329. i++;
  330. }
  331. length++;
  332. // Reduce the TNAF array to its actual length
  333. sbyte[] tnaf = new sbyte[length];
  334. Array.Copy(u, 0, tnaf, 0, length);
  335. return tnaf;
  336. }
  337. /**
  338. * Applies the operation <code>&#964;()</code> to an
  339. * <code>AbstractF2mPoint</code>.
  340. * @param p The AbstractF2mPoint to which <code>&#964;()</code> is applied.
  341. * @return <code>&#964;(p)</code>
  342. */
  343. public static AbstractF2mPoint Tau(AbstractF2mPoint p)
  344. {
  345. return p.Tau();
  346. }
  347. /**
  348. * Returns the parameter <code>&#956;</code> of the elliptic curve.
  349. * @param curve The elliptic curve from which to obtain <code>&#956;</code>.
  350. * The curve must be a Koblitz curve, i.e. <code>a</code> Equals
  351. * <code>0</code> or <code>1</code> and <code>b</code> Equals
  352. * <code>1</code>.
  353. * @return <code>&#956;</code> of the elliptic curve.
  354. * @throws ArgumentException if the given ECCurve is not a Koblitz
  355. * curve.
  356. */
  357. public static sbyte GetMu(AbstractF2mCurve curve)
  358. {
  359. BigInteger a = curve.A.ToBigInteger();
  360. sbyte mu;
  361. if (a.SignValue == 0)
  362. {
  363. mu = -1;
  364. }
  365. else if (a.Equals(BigInteger.One))
  366. {
  367. mu = 1;
  368. }
  369. else
  370. {
  371. throw new ArgumentException("No Koblitz curve (ABC), TNAF multiplication not possible");
  372. }
  373. return mu;
  374. }
  375. public static sbyte GetMu(ECFieldElement curveA)
  376. {
  377. return (sbyte)(curveA.IsZero ? -1 : 1);
  378. }
  379. public static sbyte GetMu(int curveA)
  380. {
  381. return (sbyte)(curveA == 0 ? -1 : 1);
  382. }
  383. /**
  384. * Calculates the Lucas Sequence elements <code>U<sub>k-1</sub></code> and
  385. * <code>U<sub>k</sub></code> or <code>V<sub>k-1</sub></code> and
  386. * <code>V<sub>k</sub></code>.
  387. * @param mu The parameter <code>&#956;</code> of the elliptic curve.
  388. * @param k The index of the second element of the Lucas Sequence to be
  389. * returned.
  390. * @param doV If set to true, computes <code>V<sub>k-1</sub></code> and
  391. * <code>V<sub>k</sub></code>, otherwise <code>U<sub>k-1</sub></code> and
  392. * <code>U<sub>k</sub></code>.
  393. * @return An array with 2 elements, containing <code>U<sub>k-1</sub></code>
  394. * and <code>U<sub>k</sub></code> or <code>V<sub>k-1</sub></code>
  395. * and <code>V<sub>k</sub></code>.
  396. */
  397. public static BigInteger[] GetLucas(sbyte mu, int k, bool doV)
  398. {
  399. if (!(mu == 1 || mu == -1))
  400. throw new ArgumentException("mu must be 1 or -1");
  401. BigInteger u0;
  402. BigInteger u1;
  403. BigInteger u2;
  404. if (doV)
  405. {
  406. u0 = BigInteger.Two;
  407. u1 = BigInteger.ValueOf(mu);
  408. }
  409. else
  410. {
  411. u0 = BigInteger.Zero;
  412. u1 = BigInteger.One;
  413. }
  414. for (int i = 1; i < k; i++)
  415. {
  416. // u2 = mu*u1 - 2*u0;
  417. BigInteger s = null;
  418. if (mu == 1)
  419. {
  420. s = u1;
  421. }
  422. else
  423. {
  424. // mu == -1
  425. s = u1.Negate();
  426. }
  427. u2 = s.Subtract(u0.ShiftLeft(1));
  428. u0 = u1;
  429. u1 = u2;
  430. // System.out.println(i + ": " + u2);
  431. // System.out.println();
  432. }
  433. BigInteger[] retVal = {u0, u1};
  434. return retVal;
  435. }
  436. /**
  437. * Computes the auxiliary value <code>t<sub>w</sub></code>. If the width is
  438. * 4, then for <code>mu = 1</code>, <code>t<sub>w</sub> = 6</code> and for
  439. * <code>mu = -1</code>, <code>t<sub>w</sub> = 10</code>
  440. * @param mu The parameter <code>&#956;</code> of the elliptic curve.
  441. * @param w The window width of the WTNAF.
  442. * @return the auxiliary value <code>t<sub>w</sub></code>
  443. */
  444. public static BigInteger GetTw(sbyte mu, int w)
  445. {
  446. if (w == 4)
  447. {
  448. if (mu == 1)
  449. {
  450. return BigInteger.ValueOf(6);
  451. }
  452. else
  453. {
  454. // mu == -1
  455. return BigInteger.ValueOf(10);
  456. }
  457. }
  458. else
  459. {
  460. // For w <> 4, the values must be computed
  461. BigInteger[] us = GetLucas(mu, w, false);
  462. BigInteger twoToW = BigInteger.Zero.SetBit(w);
  463. BigInteger u1invert = us[1].ModInverse(twoToW);
  464. BigInteger tw;
  465. tw = BigInteger.Two.Multiply(us[0]).Multiply(u1invert).Mod(twoToW);
  466. //System.out.println("mu = " + mu);
  467. //System.out.println("tw = " + tw);
  468. return tw;
  469. }
  470. }
  471. /**
  472. * Computes the auxiliary values <code>s<sub>0</sub></code> and
  473. * <code>s<sub>1</sub></code> used for partial modular reduction.
  474. * @param curve The elliptic curve for which to compute
  475. * <code>s<sub>0</sub></code> and <code>s<sub>1</sub></code>.
  476. * @throws ArgumentException if <code>curve</code> is not a
  477. * Koblitz curve (Anomalous Binary Curve, ABC).
  478. */
  479. public static BigInteger[] GetSi(AbstractF2mCurve curve)
  480. {
  481. if (!curve.IsKoblitz)
  482. throw new ArgumentException("si is defined for Koblitz curves only");
  483. int m = curve.FieldSize;
  484. int a = curve.A.ToBigInteger().IntValue;
  485. sbyte mu = GetMu(a);
  486. int shifts = GetShiftsForCofactor(curve.Cofactor);
  487. int index = m + 3 - a;
  488. BigInteger[] ui = GetLucas(mu, index, false);
  489. if (mu == 1)
  490. {
  491. ui[0] = ui[0].Negate();
  492. ui[1] = ui[1].Negate();
  493. }
  494. BigInteger dividend0 = BigInteger.One.Add(ui[1]).ShiftRight(shifts);
  495. BigInteger dividend1 = BigInteger.One.Add(ui[0]).ShiftRight(shifts).Negate();
  496. return new BigInteger[] { dividend0, dividend1 };
  497. }
  498. public static BigInteger[] GetSi(int fieldSize, int curveA, BigInteger cofactor)
  499. {
  500. sbyte mu = GetMu(curveA);
  501. int shifts = GetShiftsForCofactor(cofactor);
  502. int index = fieldSize + 3 - curveA;
  503. BigInteger[] ui = GetLucas(mu, index, false);
  504. if (mu == 1)
  505. {
  506. ui[0] = ui[0].Negate();
  507. ui[1] = ui[1].Negate();
  508. }
  509. BigInteger dividend0 = BigInteger.One.Add(ui[1]).ShiftRight(shifts);
  510. BigInteger dividend1 = BigInteger.One.Add(ui[0]).ShiftRight(shifts).Negate();
  511. return new BigInteger[] { dividend0, dividend1 };
  512. }
  513. protected static int GetShiftsForCofactor(BigInteger h)
  514. {
  515. if (h != null && h.BitLength < 4)
  516. {
  517. int hi = h.IntValue;
  518. if (hi == 2)
  519. return 1;
  520. if (hi == 4)
  521. return 2;
  522. }
  523. throw new ArgumentException("h (Cofactor) must be 2 or 4");
  524. }
  525. /**
  526. * Partial modular reduction modulo
  527. * <code>(&#964;<sup>m</sup> - 1)/(&#964; - 1)</code>.
  528. * @param k The integer to be reduced.
  529. * @param m The bitlength of the underlying finite field.
  530. * @param a The parameter <code>a</code> of the elliptic curve.
  531. * @param s The auxiliary values <code>s<sub>0</sub></code> and
  532. * <code>s<sub>1</sub></code>.
  533. * @param mu The parameter &#956; of the elliptic curve.
  534. * @param c The precision (number of bits of accuracy) of the partial
  535. * modular reduction.
  536. * @return <code>&#961; := k partmod (&#964;<sup>m</sup> - 1)/(&#964; - 1)</code>
  537. */
  538. public static ZTauElement PartModReduction(BigInteger k, int m, sbyte a,
  539. BigInteger[] s, sbyte mu, sbyte c)
  540. {
  541. // d0 = s[0] + mu*s[1]; mu is either 1 or -1
  542. BigInteger d0;
  543. if (mu == 1)
  544. {
  545. d0 = s[0].Add(s[1]);
  546. }
  547. else
  548. {
  549. d0 = s[0].Subtract(s[1]);
  550. }
  551. BigInteger[] v = GetLucas(mu, m, true);
  552. BigInteger vm = v[1];
  553. SimpleBigDecimal lambda0 = ApproximateDivisionByN(
  554. k, s[0], vm, a, m, c);
  555. SimpleBigDecimal lambda1 = ApproximateDivisionByN(
  556. k, s[1], vm, a, m, c);
  557. ZTauElement q = Round(lambda0, lambda1, mu);
  558. // r0 = n - d0*q0 - 2*s1*q1
  559. BigInteger r0 = k.Subtract(d0.Multiply(q.u)).Subtract(
  560. BigInteger.ValueOf(2).Multiply(s[1]).Multiply(q.v));
  561. // r1 = s1*q0 - s0*q1
  562. BigInteger r1 = s[1].Multiply(q.u).Subtract(s[0].Multiply(q.v));
  563. return new ZTauElement(r0, r1);
  564. }
  565. /**
  566. * Multiplies a {@link org.bouncycastle.math.ec.AbstractF2mPoint AbstractF2mPoint}
  567. * by a <code>BigInteger</code> using the reduced <code>&#964;</code>-adic
  568. * NAF (RTNAF) method.
  569. * @param p The AbstractF2mPoint to Multiply.
  570. * @param k The <code>BigInteger</code> by which to Multiply <code>p</code>.
  571. * @return <code>k * p</code>
  572. */
  573. public static AbstractF2mPoint MultiplyRTnaf(AbstractF2mPoint p, BigInteger k)
  574. {
  575. AbstractF2mCurve curve = (AbstractF2mCurve)p.Curve;
  576. int m = curve.FieldSize;
  577. int a = curve.A.ToBigInteger().IntValue;
  578. sbyte mu = GetMu(a);
  579. BigInteger[] s = curve.GetSi();
  580. ZTauElement rho = PartModReduction(k, m, (sbyte)a, s, mu, (sbyte)10);
  581. return MultiplyTnaf(p, rho);
  582. }
  583. /**
  584. * Multiplies a {@link org.bouncycastle.math.ec.AbstractF2mPoint AbstractF2mPoint}
  585. * by an element <code>&#955;</code> of <code><b>Z</b>[&#964;]</code>
  586. * using the <code>&#964;</code>-adic NAF (TNAF) method.
  587. * @param p The AbstractF2mPoint to Multiply.
  588. * @param lambda The element <code>&#955;</code> of
  589. * <code><b>Z</b>[&#964;]</code>.
  590. * @return <code>&#955; * p</code>
  591. */
  592. public static AbstractF2mPoint MultiplyTnaf(AbstractF2mPoint p, ZTauElement lambda)
  593. {
  594. AbstractF2mCurve curve = (AbstractF2mCurve)p.Curve;
  595. sbyte mu = GetMu(curve.A);
  596. sbyte[] u = TauAdicNaf(mu, lambda);
  597. AbstractF2mPoint q = MultiplyFromTnaf(p, u);
  598. return q;
  599. }
  600. /**
  601. * Multiplies a {@link org.bouncycastle.math.ec.AbstractF2mPoint AbstractF2mPoint}
  602. * by an element <code>&#955;</code> of <code><b>Z</b>[&#964;]</code>
  603. * using the <code>&#964;</code>-adic NAF (TNAF) method, given the TNAF
  604. * of <code>&#955;</code>.
  605. * @param p The AbstractF2mPoint to Multiply.
  606. * @param u The the TNAF of <code>&#955;</code>..
  607. * @return <code>&#955; * p</code>
  608. */
  609. public static AbstractF2mPoint MultiplyFromTnaf(AbstractF2mPoint p, sbyte[] u)
  610. {
  611. ECCurve curve = p.Curve;
  612. AbstractF2mPoint q = (AbstractF2mPoint)curve.Infinity;
  613. AbstractF2mPoint pNeg = (AbstractF2mPoint)p.Negate();
  614. int tauCount = 0;
  615. for (int i = u.Length - 1; i >= 0; i--)
  616. {
  617. ++tauCount;
  618. sbyte ui = u[i];
  619. if (ui != 0)
  620. {
  621. q = q.TauPow(tauCount);
  622. tauCount = 0;
  623. ECPoint x = ui > 0 ? p : pNeg;
  624. q = (AbstractF2mPoint)q.Add(x);
  625. }
  626. }
  627. if (tauCount > 0)
  628. {
  629. q = q.TauPow(tauCount);
  630. }
  631. return q;
  632. }
  633. /**
  634. * Computes the <code>[&#964;]</code>-adic window NAF of an element
  635. * <code>&#955;</code> of <code><b>Z</b>[&#964;]</code>.
  636. * @param mu The parameter &#956; of the elliptic curve.
  637. * @param lambda The element <code>&#955;</code> of
  638. * <code><b>Z</b>[&#964;]</code> of which to compute the
  639. * <code>[&#964;]</code>-adic NAF.
  640. * @param width The window width of the resulting WNAF.
  641. * @param pow2w 2<sup>width</sup>.
  642. * @param tw The auxiliary value <code>t<sub>w</sub></code>.
  643. * @param alpha The <code>&#945;<sub>u</sub></code>'s for the window width.
  644. * @return The <code>[&#964;]</code>-adic window NAF of
  645. * <code>&#955;</code>.
  646. */
  647. public static sbyte[] TauAdicWNaf(sbyte mu, ZTauElement lambda,
  648. sbyte width, BigInteger pow2w, BigInteger tw, ZTauElement[] alpha)
  649. {
  650. if (!((mu == 1) || (mu == -1)))
  651. throw new ArgumentException("mu must be 1 or -1");
  652. BigInteger norm = Norm(mu, lambda);
  653. // Ceiling of log2 of the norm
  654. int log2Norm = norm.BitLength;
  655. // If length(TNAF) > 30, then length(TNAF) < log2Norm + 3.52
  656. int maxLength = log2Norm > 30 ? log2Norm + 4 + width : 34 + width;
  657. // The array holding the TNAF
  658. sbyte[] u = new sbyte[maxLength];
  659. // 2^(width - 1)
  660. BigInteger pow2wMin1 = pow2w.ShiftRight(1);
  661. // Split lambda into two BigIntegers to simplify calculations
  662. BigInteger r0 = lambda.u;
  663. BigInteger r1 = lambda.v;
  664. int i = 0;
  665. // while lambda <> (0, 0)
  666. while (!((r0.Equals(BigInteger.Zero))&&(r1.Equals(BigInteger.Zero))))
  667. {
  668. // if r0 is odd
  669. if (r0.TestBit(0))
  670. {
  671. // uUnMod = r0 + r1*tw Mod 2^width
  672. BigInteger uUnMod
  673. = r0.Add(r1.Multiply(tw)).Mod(pow2w);
  674. sbyte uLocal;
  675. // if uUnMod >= 2^(width - 1)
  676. if (uUnMod.CompareTo(pow2wMin1) >= 0)
  677. {
  678. uLocal = (sbyte) uUnMod.Subtract(pow2w).IntValue;
  679. }
  680. else
  681. {
  682. uLocal = (sbyte) uUnMod.IntValue;
  683. }
  684. // uLocal is now in [-2^(width-1), 2^(width-1)-1]
  685. u[i] = uLocal;
  686. bool s = true;
  687. if (uLocal < 0)
  688. {
  689. s = false;
  690. uLocal = (sbyte)-uLocal;
  691. }
  692. // uLocal is now >= 0
  693. if (s)
  694. {
  695. r0 = r0.Subtract(alpha[uLocal].u);
  696. r1 = r1.Subtract(alpha[uLocal].v);
  697. }
  698. else
  699. {
  700. r0 = r0.Add(alpha[uLocal].u);
  701. r1 = r1.Add(alpha[uLocal].v);
  702. }
  703. }
  704. else
  705. {
  706. u[i] = 0;
  707. }
  708. BigInteger t = r0;
  709. if (mu == 1)
  710. {
  711. r0 = r1.Add(r0.ShiftRight(1));
  712. }
  713. else
  714. {
  715. // mu == -1
  716. r0 = r1.Subtract(r0.ShiftRight(1));
  717. }
  718. r1 = t.ShiftRight(1).Negate();
  719. i++;
  720. }
  721. return u;
  722. }
  723. /**
  724. * Does the precomputation for WTNAF multiplication.
  725. * @param p The <code>ECPoint</code> for which to do the precomputation.
  726. * @param a The parameter <code>a</code> of the elliptic curve.
  727. * @return The precomputation array for <code>p</code>.
  728. */
  729. public static AbstractF2mPoint[] GetPreComp(AbstractF2mPoint p, sbyte a)
  730. {
  731. sbyte[][] alphaTnaf = (a == 0) ? Tnaf.Alpha0Tnaf : Tnaf.Alpha1Tnaf;
  732. AbstractF2mPoint[] pu = new AbstractF2mPoint[(uint)(alphaTnaf.Length + 1) >> 1];
  733. pu[0] = p;
  734. uint precompLen = (uint)alphaTnaf.Length;
  735. for (uint i = 3; i < precompLen; i += 2)
  736. {
  737. pu[i >> 1] = Tnaf.MultiplyFromTnaf(p, alphaTnaf[i]);
  738. }
  739. p.Curve.NormalizeAll(pu);
  740. return pu;
  741. }
  742. }
  743. }
  744. #endif