ECFieldElement.cs 28 KB

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