ECFieldElement.cs 29 KB

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