ECFieldElement.cs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using System.Diagnostics;
  5. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  6. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Math.EC
  7. {
  8. public abstract class ECFieldElement
  9. {
  10. public abstract BigInteger ToBigInteger();
  11. public abstract string FieldName { get; }
  12. public abstract int FieldSize { get; }
  13. public abstract ECFieldElement Add(ECFieldElement b);
  14. public abstract ECFieldElement AddOne();
  15. public abstract ECFieldElement Subtract(ECFieldElement b);
  16. public abstract ECFieldElement Multiply(ECFieldElement b);
  17. public abstract ECFieldElement Divide(ECFieldElement b);
  18. public abstract ECFieldElement Negate();
  19. public abstract ECFieldElement Square();
  20. public abstract ECFieldElement Invert();
  21. public abstract ECFieldElement Sqrt();
  22. public virtual int BitLength
  23. {
  24. get { return ToBigInteger().BitLength; }
  25. }
  26. public virtual bool IsOne
  27. {
  28. get { return BitLength == 1; }
  29. }
  30. public virtual bool IsZero
  31. {
  32. get { return 0 == ToBigInteger().SignValue; }
  33. }
  34. public virtual ECFieldElement MultiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
  35. {
  36. return Multiply(b).Subtract(x.Multiply(y));
  37. }
  38. public virtual ECFieldElement MultiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
  39. {
  40. return Multiply(b).Add(x.Multiply(y));
  41. }
  42. public virtual ECFieldElement SquareMinusProduct(ECFieldElement x, ECFieldElement y)
  43. {
  44. return Square().Subtract(x.Multiply(y));
  45. }
  46. public virtual ECFieldElement SquarePlusProduct(ECFieldElement x, ECFieldElement y)
  47. {
  48. return Square().Add(x.Multiply(y));
  49. }
  50. public virtual ECFieldElement SquarePow(int pow)
  51. {
  52. ECFieldElement r = this;
  53. for (int i = 0; i < pow; ++i)
  54. {
  55. r = r.Square();
  56. }
  57. return r;
  58. }
  59. public virtual bool TestBitZero()
  60. {
  61. return ToBigInteger().TestBit(0);
  62. }
  63. public override bool Equals(object obj)
  64. {
  65. return Equals(obj as ECFieldElement);
  66. }
  67. public virtual bool Equals(ECFieldElement other)
  68. {
  69. if (this == other)
  70. return true;
  71. if (null == other)
  72. return false;
  73. return ToBigInteger().Equals(other.ToBigInteger());
  74. }
  75. public override int GetHashCode()
  76. {
  77. return ToBigInteger().GetHashCode();
  78. }
  79. public override string ToString()
  80. {
  81. return this.ToBigInteger().ToString(16);
  82. }
  83. public virtual byte[] GetEncoded()
  84. {
  85. return BigIntegers.AsUnsignedByteArray((FieldSize + 7) / 8, ToBigInteger());
  86. }
  87. }
  88. public abstract class AbstractFpFieldElement
  89. : ECFieldElement
  90. {
  91. }
  92. public class FpFieldElement
  93. : AbstractFpFieldElement
  94. {
  95. private readonly BigInteger q, r, x;
  96. internal static BigInteger CalculateResidue(BigInteger p)
  97. {
  98. int bitLength = p.BitLength;
  99. if (bitLength >= 96)
  100. {
  101. BigInteger firstWord = p.ShiftRight(bitLength - 64);
  102. if (firstWord.LongValue == -1L)
  103. {
  104. return BigInteger.One.ShiftLeft(bitLength).Subtract(p);
  105. }
  106. if ((bitLength & 7) == 0)
  107. {
  108. return BigInteger.One.ShiftLeft(bitLength << 1).Divide(p).Negate();
  109. }
  110. }
  111. return null;
  112. }
  113. public FpFieldElement(BigInteger q, BigInteger x)
  114. : this(q, CalculateResidue(q), x)
  115. {
  116. }
  117. internal FpFieldElement(BigInteger q, BigInteger r, BigInteger x)
  118. {
  119. if (x == null || x.SignValue < 0 || x.CompareTo(q) >= 0)
  120. throw new ArgumentException("value invalid in Fp field element", "x");
  121. this.q = q;
  122. this.r = r;
  123. this.x = x;
  124. }
  125. public override BigInteger ToBigInteger()
  126. {
  127. return x;
  128. }
  129. /**
  130. * return the field name for this field.
  131. *
  132. * @return the string "Fp".
  133. */
  134. public override string FieldName
  135. {
  136. get { return "Fp"; }
  137. }
  138. public override int FieldSize
  139. {
  140. get { return q.BitLength; }
  141. }
  142. public BigInteger Q
  143. {
  144. get { return q; }
  145. }
  146. public override ECFieldElement Add(
  147. ECFieldElement b)
  148. {
  149. return new FpFieldElement(q, r, ModAdd(x, b.ToBigInteger()));
  150. }
  151. public override ECFieldElement AddOne()
  152. {
  153. BigInteger x2 = x.Add(BigInteger.One);
  154. if (x2.CompareTo(q) == 0)
  155. {
  156. x2 = BigInteger.Zero;
  157. }
  158. return new FpFieldElement(q, r, x2);
  159. }
  160. public override ECFieldElement Subtract(
  161. ECFieldElement b)
  162. {
  163. return new FpFieldElement(q, r, ModSubtract(x, b.ToBigInteger()));
  164. }
  165. public override ECFieldElement Multiply(
  166. ECFieldElement b)
  167. {
  168. return new FpFieldElement(q, r, ModMult(x, b.ToBigInteger()));
  169. }
  170. public override ECFieldElement MultiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
  171. {
  172. BigInteger ax = this.x, bx = b.ToBigInteger(), xx = x.ToBigInteger(), yx = y.ToBigInteger();
  173. BigInteger ab = ax.Multiply(bx);
  174. BigInteger xy = xx.Multiply(yx);
  175. return new FpFieldElement(q, r, ModReduce(ab.Subtract(xy)));
  176. }
  177. public override ECFieldElement MultiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
  178. {
  179. BigInteger ax = this.x, bx = b.ToBigInteger(), xx = x.ToBigInteger(), yx = y.ToBigInteger();
  180. BigInteger ab = ax.Multiply(bx);
  181. BigInteger xy = xx.Multiply(yx);
  182. BigInteger sum = ab.Add(xy);
  183. if (r != null && r.SignValue < 0 && sum.BitLength > (q.BitLength << 1))
  184. {
  185. sum = sum.Subtract(q.ShiftLeft(q.BitLength));
  186. }
  187. return new FpFieldElement(q, r, ModReduce(sum));
  188. }
  189. public override ECFieldElement Divide(
  190. ECFieldElement b)
  191. {
  192. return new FpFieldElement(q, r, ModMult(x, ModInverse(b.ToBigInteger())));
  193. }
  194. public override ECFieldElement Negate()
  195. {
  196. return x.SignValue == 0 ? this : new FpFieldElement(q, r, q.Subtract(x));
  197. }
  198. public override ECFieldElement Square()
  199. {
  200. return new FpFieldElement(q, r, ModMult(x, x));
  201. }
  202. public override ECFieldElement SquareMinusProduct(ECFieldElement x, ECFieldElement y)
  203. {
  204. BigInteger ax = this.x, xx = x.ToBigInteger(), yx = y.ToBigInteger();
  205. BigInteger aa = ax.Multiply(ax);
  206. BigInteger xy = xx.Multiply(yx);
  207. return new FpFieldElement(q, r, ModReduce(aa.Subtract(xy)));
  208. }
  209. public override ECFieldElement SquarePlusProduct(ECFieldElement x, ECFieldElement y)
  210. {
  211. BigInteger ax = this.x, xx = x.ToBigInteger(), yx = y.ToBigInteger();
  212. BigInteger aa = ax.Multiply(ax);
  213. BigInteger xy = xx.Multiply(yx);
  214. BigInteger sum = aa.Add(xy);
  215. if (r != null && r.SignValue < 0 && sum.BitLength > (q.BitLength << 1))
  216. {
  217. sum = sum.Subtract(q.ShiftLeft(q.BitLength));
  218. }
  219. return new FpFieldElement(q, r, ModReduce(sum));
  220. }
  221. public override ECFieldElement Invert()
  222. {
  223. // TODO Modular inversion can be faster for a (Generalized) Mersenne Prime.
  224. return new FpFieldElement(q, r, ModInverse(x));
  225. }
  226. /**
  227. * return a sqrt root - the routine verifies that the calculation
  228. * returns the right value - if none exists it returns null.
  229. */
  230. public override ECFieldElement Sqrt()
  231. {
  232. if (IsZero || IsOne)
  233. return this;
  234. if (!q.TestBit(0))
  235. throw BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateNotImplementedException("even value of q");
  236. if (q.TestBit(1)) // q == 4m + 3
  237. {
  238. BigInteger e = q.ShiftRight(2).Add(BigInteger.One);
  239. return CheckSqrt(new FpFieldElement(q, r, x.ModPow(e, q)));
  240. }
  241. if (q.TestBit(2)) // q == 8m + 5
  242. {
  243. BigInteger t1 = x.ModPow(q.ShiftRight(3), q);
  244. BigInteger t2 = ModMult(t1, x);
  245. BigInteger t3 = ModMult(t2, t1);
  246. if (t3.Equals(BigInteger.One))
  247. {
  248. return CheckSqrt(new FpFieldElement(q, r, t2));
  249. }
  250. // TODO This is constant and could be precomputed
  251. BigInteger t4 = BigInteger.Two.ModPow(q.ShiftRight(2), q);
  252. BigInteger y = ModMult(t2, t4);
  253. return CheckSqrt(new FpFieldElement(q, r, y));
  254. }
  255. // q == 8m + 1
  256. BigInteger legendreExponent = q.ShiftRight(1);
  257. if (!(x.ModPow(legendreExponent, q).Equals(BigInteger.One)))
  258. return null;
  259. BigInteger X = this.x;
  260. BigInteger fourX = ModDouble(ModDouble(X)); ;
  261. BigInteger k = legendreExponent.Add(BigInteger.One), qMinusOne = q.Subtract(BigInteger.One);
  262. BigInteger U, V;
  263. do
  264. {
  265. BigInteger P;
  266. do
  267. {
  268. P = BigInteger.Arbitrary(q.BitLength);
  269. }
  270. while (P.CompareTo(q) >= 0
  271. || !ModReduce(P.Multiply(P).Subtract(fourX)).ModPow(legendreExponent, q).Equals(qMinusOne));
  272. BigInteger[] result = LucasSequence(P, X, k);
  273. U = result[0];
  274. V = result[1];
  275. if (ModMult(V, V).Equals(fourX))
  276. {
  277. return new FpFieldElement(q, r, ModHalfAbs(V));
  278. }
  279. }
  280. while (U.Equals(BigInteger.One) || U.Equals(qMinusOne));
  281. return null;
  282. }
  283. private ECFieldElement CheckSqrt(ECFieldElement z)
  284. {
  285. return z.Square().Equals(this) ? z : null;
  286. }
  287. private BigInteger[] LucasSequence(
  288. BigInteger P,
  289. BigInteger Q,
  290. BigInteger k)
  291. {
  292. // TODO Research and apply "common-multiplicand multiplication here"
  293. int n = k.BitLength;
  294. int s = k.GetLowestSetBit();
  295. Debug.Assert(k.TestBit(s));
  296. BigInteger Uh = BigInteger.One;
  297. BigInteger Vl = BigInteger.Two;
  298. BigInteger Vh = P;
  299. BigInteger Ql = BigInteger.One;
  300. BigInteger Qh = BigInteger.One;
  301. for (int j = n - 1; j >= s + 1; --j)
  302. {
  303. Ql = ModMult(Ql, Qh);
  304. if (k.TestBit(j))
  305. {
  306. Qh = ModMult(Ql, Q);
  307. Uh = ModMult(Uh, Vh);
  308. Vl = ModReduce(Vh.Multiply(Vl).Subtract(P.Multiply(Ql)));
  309. Vh = ModReduce(Vh.Multiply(Vh).Subtract(Qh.ShiftLeft(1)));
  310. }
  311. else
  312. {
  313. Qh = Ql;
  314. Uh = ModReduce(Uh.Multiply(Vl).Subtract(Ql));
  315. Vh = ModReduce(Vh.Multiply(Vl).Subtract(P.Multiply(Ql)));
  316. Vl = ModReduce(Vl.Multiply(Vl).Subtract(Ql.ShiftLeft(1)));
  317. }
  318. }
  319. Ql = ModMult(Ql, Qh);
  320. Qh = ModMult(Ql, Q);
  321. Uh = ModReduce(Uh.Multiply(Vl).Subtract(Ql));
  322. Vl = ModReduce(Vh.Multiply(Vl).Subtract(P.Multiply(Ql)));
  323. Ql = ModMult(Ql, Qh);
  324. for (int j = 1; j <= s; ++j)
  325. {
  326. Uh = ModMult(Uh, Vl);
  327. Vl = ModReduce(Vl.Multiply(Vl).Subtract(Ql.ShiftLeft(1)));
  328. Ql = ModMult(Ql, Ql);
  329. }
  330. return new BigInteger[] { Uh, Vl };
  331. }
  332. protected virtual BigInteger ModAdd(BigInteger x1, BigInteger x2)
  333. {
  334. BigInteger x3 = x1.Add(x2);
  335. if (x3.CompareTo(q) >= 0)
  336. {
  337. x3 = x3.Subtract(q);
  338. }
  339. return x3;
  340. }
  341. protected virtual BigInteger ModDouble(BigInteger x)
  342. {
  343. BigInteger _2x = x.ShiftLeft(1);
  344. if (_2x.CompareTo(q) >= 0)
  345. {
  346. _2x = _2x.Subtract(q);
  347. }
  348. return _2x;
  349. }
  350. protected virtual BigInteger ModHalf(BigInteger x)
  351. {
  352. if (x.TestBit(0))
  353. {
  354. x = q.Add(x);
  355. }
  356. return x.ShiftRight(1);
  357. }
  358. protected virtual BigInteger ModHalfAbs(BigInteger x)
  359. {
  360. if (x.TestBit(0))
  361. {
  362. x = q.Subtract(x);
  363. }
  364. return x.ShiftRight(1);
  365. }
  366. protected virtual BigInteger ModInverse(BigInteger x)
  367. {
  368. return BigIntegers.ModOddInverse(q, x);
  369. }
  370. protected virtual BigInteger ModMult(BigInteger x1, BigInteger x2)
  371. {
  372. return ModReduce(x1.Multiply(x2));
  373. }
  374. protected virtual BigInteger ModReduce(BigInteger x)
  375. {
  376. if (r == null)
  377. {
  378. x = x.Mod(q);
  379. }
  380. else
  381. {
  382. bool negative = x.SignValue < 0;
  383. if (negative)
  384. {
  385. x = x.Abs();
  386. }
  387. int qLen = q.BitLength;
  388. if (r.SignValue > 0)
  389. {
  390. BigInteger qMod = BigInteger.One.ShiftLeft(qLen);
  391. bool rIsOne = r.Equals(BigInteger.One);
  392. while (x.BitLength > (qLen + 1))
  393. {
  394. BigInteger u = x.ShiftRight(qLen);
  395. BigInteger v = x.Remainder(qMod);
  396. if (!rIsOne)
  397. {
  398. u = u.Multiply(r);
  399. }
  400. x = u.Add(v);
  401. }
  402. }
  403. else
  404. {
  405. int d = ((qLen - 1) & 31) + 1;
  406. BigInteger mu = r.Negate();
  407. BigInteger u = mu.Multiply(x.ShiftRight(qLen - d));
  408. BigInteger quot = u.ShiftRight(qLen + d);
  409. BigInteger v = quot.Multiply(q);
  410. BigInteger bk1 = BigInteger.One.ShiftLeft(qLen + d);
  411. v = v.Remainder(bk1);
  412. x = x.Remainder(bk1);
  413. x = x.Subtract(v);
  414. if (x.SignValue < 0)
  415. {
  416. x = x.Add(bk1);
  417. }
  418. }
  419. while (x.CompareTo(q) >= 0)
  420. {
  421. x = x.Subtract(q);
  422. }
  423. if (negative && x.SignValue != 0)
  424. {
  425. x = q.Subtract(x);
  426. }
  427. }
  428. return x;
  429. }
  430. protected virtual BigInteger ModSubtract(BigInteger x1, BigInteger x2)
  431. {
  432. BigInteger x3 = x1.Subtract(x2);
  433. if (x3.SignValue < 0)
  434. {
  435. x3 = x3.Add(q);
  436. }
  437. return x3;
  438. }
  439. public override bool Equals(
  440. object obj)
  441. {
  442. if (obj == this)
  443. return true;
  444. FpFieldElement other = obj as FpFieldElement;
  445. if (other == null)
  446. return false;
  447. return Equals(other);
  448. }
  449. public virtual bool Equals(
  450. FpFieldElement other)
  451. {
  452. return q.Equals(other.q) && base.Equals(other);
  453. }
  454. public override int GetHashCode()
  455. {
  456. return q.GetHashCode() ^ base.GetHashCode();
  457. }
  458. }
  459. public abstract class AbstractF2mFieldElement
  460. : ECFieldElement
  461. {
  462. public virtual ECFieldElement HalfTrace()
  463. {
  464. int m = FieldSize;
  465. if ((m & 1) == 0)
  466. throw new InvalidOperationException("Half-trace only defined for odd m");
  467. //ECFieldElement ht = this;
  468. //for (int i = 1; i < m; i += 2)
  469. //{
  470. // ht = ht.SquarePow(2).Add(this);
  471. //}
  472. int n = (m + 1) >> 1;
  473. int k = 31 - Integers.NumberOfLeadingZeros(n);
  474. int nk = 1;
  475. ECFieldElement ht = this;
  476. while (k > 0)
  477. {
  478. ht = ht.SquarePow(nk << 1).Add(ht);
  479. nk = n >> --k;
  480. if (0 != (nk & 1))
  481. {
  482. ht = ht.SquarePow(2).Add(this);
  483. }
  484. }
  485. return ht;
  486. }
  487. public virtual bool HasFastTrace
  488. {
  489. get { return false; }
  490. }
  491. public virtual int Trace()
  492. {
  493. int m = FieldSize;
  494. //ECFieldElement tr = this;
  495. //for (int i = 1; i < m; ++i)
  496. //{
  497. // tr = tr.Square().Add(this);
  498. //}
  499. int k = 31 - Integers.NumberOfLeadingZeros(m);
  500. int mk = 1;
  501. ECFieldElement tr = this;
  502. while (k > 0)
  503. {
  504. tr = tr.SquarePow(mk).Add(tr);
  505. mk = m >> --k;
  506. if (0 != (mk & 1))
  507. {
  508. tr = tr.Square().Add(this);
  509. }
  510. }
  511. if (tr.IsZero)
  512. return 0;
  513. if (tr.IsOne)
  514. return 1;
  515. throw new InvalidOperationException("Internal error in trace calculation");
  516. }
  517. }
  518. /**
  519. * Class representing the Elements of the finite field
  520. * <code>F<sub>2<sup>m</sup></sub></code> in polynomial basis (PB)
  521. * representation. Both trinomial (Tpb) and pentanomial (Ppb) polynomial
  522. * basis representations are supported. Gaussian normal basis (GNB)
  523. * representation is not supported.
  524. */
  525. public class F2mFieldElement
  526. : AbstractF2mFieldElement
  527. {
  528. /**
  529. * Indicates gaussian normal basis representation (GNB). Number chosen
  530. * according to X9.62. GNB is not implemented at present.
  531. */
  532. public const int Gnb = 1;
  533. /**
  534. * Indicates trinomial basis representation (Tpb). Number chosen
  535. * according to X9.62.
  536. */
  537. public const int Tpb = 2;
  538. /**
  539. * Indicates pentanomial basis representation (Ppb). Number chosen
  540. * according to X9.62.
  541. */
  542. public const int Ppb = 3;
  543. /**
  544. * Tpb or Ppb.
  545. */
  546. private int representation;
  547. /**
  548. * The exponent <code>m</code> of <code>F<sub>2<sup>m</sup></sub></code>.
  549. */
  550. private int m;
  551. private int[] ks;
  552. /**
  553. * The <code>LongArray</code> holding the bits.
  554. */
  555. internal LongArray x;
  556. /**
  557. * Constructor for Ppb.
  558. * @param m The exponent <code>m</code> of
  559. * <code>F<sub>2<sup>m</sup></sub></code>.
  560. * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
  561. * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
  562. * represents the reduction polynomial <code>f(z)</code>.
  563. * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
  564. * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
  565. * represents the reduction polynomial <code>f(z)</code>.
  566. * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
  567. * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
  568. * represents the reduction polynomial <code>f(z)</code>.
  569. * @param x The BigInteger representing the value of the field element.
  570. */
  571. public F2mFieldElement(
  572. int m,
  573. int k1,
  574. int k2,
  575. int k3,
  576. BigInteger x)
  577. {
  578. if (x == null || x.SignValue < 0 || x.BitLength > m)
  579. throw new ArgumentException("value invalid in F2m field element", "x");
  580. if ((k2 == 0) && (k3 == 0))
  581. {
  582. this.representation = Tpb;
  583. this.ks = new int[] { k1 };
  584. }
  585. else
  586. {
  587. if (k2 >= k3)
  588. throw new ArgumentException("k2 must be smaller than k3");
  589. if (k2 <= 0)
  590. throw new ArgumentException("k2 must be larger than 0");
  591. this.representation = Ppb;
  592. this.ks = new int[] { k1, k2, k3 };
  593. }
  594. this.m = m;
  595. this.x = new LongArray(x);
  596. }
  597. /**
  598. * Constructor for Tpb.
  599. * @param m The exponent <code>m</code> of
  600. * <code>F<sub>2<sup>m</sup></sub></code>.
  601. * @param k The integer <code>k</code> where <code>x<sup>m</sup> +
  602. * x<sup>k</sup> + 1</code> represents the reduction
  603. * polynomial <code>f(z)</code>.
  604. * @param x The BigInteger representing the value of the field element.
  605. */
  606. public F2mFieldElement(
  607. int m,
  608. int k,
  609. BigInteger x)
  610. : this(m, k, 0, 0, x)
  611. {
  612. // Set k1 to k, and set k2 and k3 to 0
  613. }
  614. internal F2mFieldElement(int m, int[] ks, LongArray x)
  615. {
  616. this.m = m;
  617. this.representation = (ks.Length == 1) ? Tpb : Ppb;
  618. this.ks = ks;
  619. this.x = x;
  620. }
  621. public override int BitLength
  622. {
  623. get { return x.Degree(); }
  624. }
  625. public override bool IsOne
  626. {
  627. get { return x.IsOne(); }
  628. }
  629. public override bool IsZero
  630. {
  631. get { return x.IsZero(); }
  632. }
  633. public override bool TestBitZero()
  634. {
  635. return x.TestBitZero();
  636. }
  637. public override BigInteger ToBigInteger()
  638. {
  639. return x.ToBigInteger();
  640. }
  641. public override string FieldName
  642. {
  643. get { return "F2m"; }
  644. }
  645. public override int FieldSize
  646. {
  647. get { return m; }
  648. }
  649. /**
  650. * Checks, if the ECFieldElements <code>a</code> and <code>b</code>
  651. * are elements of the same field <code>F<sub>2<sup>m</sup></sub></code>
  652. * (having the same representation).
  653. * @param a field element.
  654. * @param b field element to be compared.
  655. * @throws ArgumentException if <code>a</code> and <code>b</code>
  656. * are not elements of the same field
  657. * <code>F<sub>2<sup>m</sup></sub></code> (having the same
  658. * representation).
  659. */
  660. public static void CheckFieldElements(
  661. ECFieldElement a,
  662. ECFieldElement b)
  663. {
  664. if (!(a is F2mFieldElement) || !(b is F2mFieldElement))
  665. {
  666. throw new ArgumentException("Field elements are not "
  667. + "both instances of F2mFieldElement");
  668. }
  669. F2mFieldElement aF2m = (F2mFieldElement)a;
  670. F2mFieldElement bF2m = (F2mFieldElement)b;
  671. if (aF2m.representation != bF2m.representation)
  672. {
  673. // Should never occur
  674. throw new ArgumentException("One of the F2m field elements has incorrect representation");
  675. }
  676. if ((aF2m.m != bF2m.m) || !Arrays.AreEqual(aF2m.ks, bF2m.ks))
  677. {
  678. throw new ArgumentException("Field elements are not elements of the same field F2m");
  679. }
  680. }
  681. public override ECFieldElement Add(
  682. ECFieldElement b)
  683. {
  684. // No check performed here for performance reasons. Instead the
  685. // elements involved are checked in ECPoint.F2m
  686. // checkFieldElements(this, b);
  687. LongArray iarrClone = this.x.Copy();
  688. F2mFieldElement bF2m = (F2mFieldElement)b;
  689. iarrClone.AddShiftedByWords(bF2m.x, 0);
  690. return new F2mFieldElement(m, ks, iarrClone);
  691. }
  692. public override ECFieldElement AddOne()
  693. {
  694. return new F2mFieldElement(m, ks, x.AddOne());
  695. }
  696. public override ECFieldElement Subtract(
  697. ECFieldElement b)
  698. {
  699. // Addition and subtraction are the same in F2m
  700. return Add(b);
  701. }
  702. public override ECFieldElement Multiply(
  703. ECFieldElement b)
  704. {
  705. // Right-to-left comb multiplication in the LongArray
  706. // Input: Binary polynomials a(z) and b(z) of degree at most m-1
  707. // Output: c(z) = a(z) * b(z) mod f(z)
  708. // No check performed here for performance reasons. Instead the
  709. // elements involved are checked in ECPoint.F2m
  710. // checkFieldElements(this, b);
  711. return new F2mFieldElement(m, ks, x.ModMultiply(((F2mFieldElement)b).x, m, ks));
  712. }
  713. public override ECFieldElement MultiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
  714. {
  715. return MultiplyPlusProduct(b, x, y);
  716. }
  717. public override ECFieldElement MultiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
  718. {
  719. LongArray ax = this.x, bx = ((F2mFieldElement)b).x, xx = ((F2mFieldElement)x).x, yx = ((F2mFieldElement)y).x;
  720. LongArray ab = ax.Multiply(bx, m, ks);
  721. LongArray xy = xx.Multiply(yx, m, ks);
  722. if (ab == ax || ab == bx)
  723. {
  724. ab = (LongArray)ab.Copy();
  725. }
  726. ab.AddShiftedByWords(xy, 0);
  727. ab.Reduce(m, ks);
  728. return new F2mFieldElement(m, ks, ab);
  729. }
  730. public override ECFieldElement Divide(
  731. ECFieldElement b)
  732. {
  733. // There may be more efficient implementations
  734. ECFieldElement bInv = b.Invert();
  735. return Multiply(bInv);
  736. }
  737. public override ECFieldElement Negate()
  738. {
  739. // -x == x holds for all x in F2m
  740. return this;
  741. }
  742. public override ECFieldElement Square()
  743. {
  744. return new F2mFieldElement(m, ks, x.ModSquare(m, ks));
  745. }
  746. public override ECFieldElement SquareMinusProduct(ECFieldElement x, ECFieldElement y)
  747. {
  748. return SquarePlusProduct(x, y);
  749. }
  750. public override ECFieldElement SquarePlusProduct(ECFieldElement x, ECFieldElement y)
  751. {
  752. LongArray ax = this.x, xx = ((F2mFieldElement)x).x, yx = ((F2mFieldElement)y).x;
  753. LongArray aa = ax.Square(m, ks);
  754. LongArray xy = xx.Multiply(yx, m, ks);
  755. if (aa == ax)
  756. {
  757. aa = (LongArray)aa.Copy();
  758. }
  759. aa.AddShiftedByWords(xy, 0);
  760. aa.Reduce(m, ks);
  761. return new F2mFieldElement(m, ks, aa);
  762. }
  763. public override ECFieldElement SquarePow(int pow)
  764. {
  765. return pow < 1 ? this : new F2mFieldElement(m, ks, x.ModSquareN(pow, m, ks));
  766. }
  767. public override ECFieldElement Invert()
  768. {
  769. return new F2mFieldElement(this.m, this.ks, this.x.ModInverse(m, ks));
  770. }
  771. public override ECFieldElement Sqrt()
  772. {
  773. return (x.IsZero() || x.IsOne()) ? this : SquarePow(m - 1);
  774. }
  775. /**
  776. * @return the representation of the field
  777. * <code>F<sub>2<sup>m</sup></sub></code>, either of
  778. * {@link F2mFieldElement.Tpb} (trinomial
  779. * basis representation) or
  780. * {@link F2mFieldElement.Ppb} (pentanomial
  781. * basis representation).
  782. */
  783. public int Representation
  784. {
  785. get { return this.representation; }
  786. }
  787. /**
  788. * @return the degree <code>m</code> of the reduction polynomial
  789. * <code>f(z)</code>.
  790. */
  791. public int M
  792. {
  793. get { return this.m; }
  794. }
  795. /**
  796. * @return Tpb: The integer <code>k</code> where <code>x<sup>m</sup> +
  797. * x<sup>k</sup> + 1</code> represents the reduction polynomial
  798. * <code>f(z)</code>.<br/>
  799. * Ppb: The integer <code>k1</code> where <code>x<sup>m</sup> +
  800. * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
  801. * represents the reduction polynomial <code>f(z)</code>.<br/>
  802. */
  803. public int K1
  804. {
  805. get { return this.ks[0]; }
  806. }
  807. /**
  808. * @return Tpb: Always returns <code>0</code><br/>
  809. * Ppb: The integer <code>k2</code> where <code>x<sup>m</sup> +
  810. * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
  811. * represents the reduction polynomial <code>f(z)</code>.<br/>
  812. */
  813. public int K2
  814. {
  815. get { return this.ks.Length >= 2 ? this.ks[1] : 0; }
  816. }
  817. /**
  818. * @return Tpb: Always set to <code>0</code><br/>
  819. * Ppb: The integer <code>k3</code> where <code>x<sup>m</sup> +
  820. * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
  821. * represents the reduction polynomial <code>f(z)</code>.<br/>
  822. */
  823. public int K3
  824. {
  825. get { return this.ks.Length >= 3 ? this.ks[2] : 0; }
  826. }
  827. public override bool Equals(
  828. object obj)
  829. {
  830. if (obj == this)
  831. return true;
  832. F2mFieldElement other = obj as F2mFieldElement;
  833. if (other == null)
  834. return false;
  835. return Equals(other);
  836. }
  837. public virtual bool Equals(
  838. F2mFieldElement other)
  839. {
  840. return ((this.m == other.m)
  841. && (this.representation == other.representation)
  842. && Arrays.AreEqual(this.ks, other.ks)
  843. && (this.x.Equals(other.x)));
  844. }
  845. public override int GetHashCode()
  846. {
  847. return x.GetHashCode() ^ m ^ Arrays.GetHashCode(ks);
  848. }
  849. }
  850. }
  851. #pragma warning restore
  852. #endif