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