1package org.bouncycastle.math.ec;
2
3import java.math.BigInteger;
4import java.util.Random;
5
6import org.bouncycastle.util.Arrays;
7import org.bouncycastle.util.BigIntegers;
8
9public abstract class ECFieldElement
10    implements ECConstants
11{
12    public abstract BigInteger     toBigInteger();
13    public abstract String         getFieldName();
14    public abstract int            getFieldSize();
15    public abstract ECFieldElement add(ECFieldElement b);
16    public abstract ECFieldElement addOne();
17    public abstract ECFieldElement subtract(ECFieldElement b);
18    public abstract ECFieldElement multiply(ECFieldElement b);
19    public abstract ECFieldElement divide(ECFieldElement b);
20    public abstract ECFieldElement negate();
21    public abstract ECFieldElement square();
22    public abstract ECFieldElement invert();
23    public abstract ECFieldElement sqrt();
24
25    public int bitLength()
26    {
27        return toBigInteger().bitLength();
28    }
29
30    public boolean isZero()
31    {
32        return 0 == toBigInteger().signum();
33    }
34
35    public boolean testBitZero()
36    {
37        return toBigInteger().testBit(0);
38    }
39
40    public String toString()
41    {
42        return this.toBigInteger().toString(16);
43    }
44
45    public byte[] getEncoded()
46    {
47        return BigIntegers.asUnsignedByteArray((getFieldSize() + 7) / 8, toBigInteger());
48    }
49
50    public static class Fp extends ECFieldElement
51    {
52        BigInteger q, r, x;
53
54//        static int[] calculateNaf(BigInteger p)
55//        {
56//            int[] naf = WNafUtil.generateCompactNaf(p);
57//
58//            int bit = 0;
59//            for (int i = 0; i < naf.length; ++i)
60//            {
61//                int ni = naf[i];
62//                int digit = ni >> 16, zeroes = ni & 0xFFFF;
63//
64//                bit += zeroes;
65//                naf[i] = digit < 0 ? ~bit : bit;
66//                ++bit;
67//            }
68//
69//            int last = naf.length - 1;
70//            if (last > 0 && last <= 16)
71//            {
72//                int top = naf[last], top2 = naf[last - 1];
73//                if (top2 < 0)
74//                {
75//                    top2 = ~top2;
76//                }
77//                if (top - top2 >= 64)
78//                {
79//                    return naf;
80//                }
81//            }
82//
83//            return null;
84//        }
85
86        static BigInteger calculateResidue(BigInteger p)
87        {
88            int bitLength = p.bitLength();
89            if (bitLength > 128)
90            {
91                BigInteger firstWord = p.shiftRight(bitLength - 64);
92                if (firstWord.longValue() == -1L)
93                {
94                    return ONE.shiftLeft(bitLength).subtract(p);
95                }
96            }
97            return null;
98        }
99
100        /**
101         * @deprecated Use ECCurve.fromBigInteger to construct field elements
102         */
103        public Fp(BigInteger q, BigInteger x)
104        {
105            this(q, calculateResidue(q), x);
106        }
107
108        Fp(BigInteger q, BigInteger r, BigInteger x)
109        {
110            if (x == null || x.signum() < 0 || x.compareTo(q) >= 0)
111            {
112                throw new IllegalArgumentException("x value invalid in Fp field element");
113            }
114
115            this.q = q;
116            this.r = r;
117            this.x = x;
118        }
119
120        public BigInteger toBigInteger()
121        {
122            return x;
123        }
124
125        /**
126         * return the field name for this field.
127         *
128         * @return the string "Fp".
129         */
130        public String getFieldName()
131        {
132            return "Fp";
133        }
134
135        public int getFieldSize()
136        {
137            return q.bitLength();
138        }
139
140        public BigInteger getQ()
141        {
142            return q;
143        }
144
145        public ECFieldElement add(ECFieldElement b)
146        {
147            return new Fp(q, r, modAdd(x, b.toBigInteger()));
148        }
149
150        public ECFieldElement addOne()
151        {
152            BigInteger x2 = x.add(ECConstants.ONE);
153            if (x2.compareTo(q) == 0)
154            {
155                x2 = ECConstants.ZERO;
156            }
157            return new Fp(q, r, x2);
158        }
159
160        public ECFieldElement subtract(ECFieldElement b)
161        {
162            BigInteger x2 = b.toBigInteger();
163            BigInteger x3 = x.subtract(x2);
164            if (x3.signum() < 0)
165            {
166                x3 = x3.add(q);
167            }
168            return new Fp(q, r, x3);
169        }
170
171        public ECFieldElement multiply(ECFieldElement b)
172        {
173            return new Fp(q, r, modMult(x, b.toBigInteger()));
174        }
175
176        public ECFieldElement divide(ECFieldElement b)
177        {
178            return new Fp(q, modMult(x, b.toBigInteger().modInverse(q)));
179        }
180
181        public ECFieldElement negate()
182        {
183            BigInteger x2;
184            if (x.signum() == 0)
185            {
186                x2 = x;
187            }
188            else if (ONE.equals(r))
189            {
190                x2 = q.xor(x);
191            }
192            else
193            {
194                x2 = q.subtract(x);
195            }
196            return new Fp(q, r, x2);
197        }
198
199        public ECFieldElement square()
200        {
201            return new Fp(q, r, modMult(x, x));
202        }
203
204        public ECFieldElement invert()
205        {
206            // TODO Modular inversion can be faster for a (Generalized) Mersenne Prime.
207            return new Fp(q, r, x.modInverse(q));
208        }
209
210        // D.1.4 91
211        /**
212         * return a sqrt root - the routine verifies that the calculation
213         * returns the right value - if none exists it returns null.
214         */
215        public ECFieldElement sqrt()
216        {
217            if (!q.testBit(0))
218            {
219                throw new RuntimeException("not done yet");
220            }
221
222            // note: even though this class implements ECConstants don't be tempted to
223            // remove the explicit declaration, some J2ME environments don't cope.
224            // p mod 4 == 3
225            if (q.testBit(1))
226            {
227                // z = g^(u+1) + p, p = 4u + 3
228                ECFieldElement z = new Fp(q, r, x.modPow(q.shiftRight(2).add(ECConstants.ONE), q));
229
230                return z.square().equals(this) ? z : null;
231            }
232
233            // p mod 4 == 1
234            BigInteger qMinusOne = q.subtract(ECConstants.ONE);
235
236            BigInteger legendreExponent = qMinusOne.shiftRight(1);
237            if (!(x.modPow(legendreExponent, q).equals(ECConstants.ONE)))
238            {
239                return null;
240            }
241
242            BigInteger u = qMinusOne.shiftRight(2);
243            BigInteger k = u.shiftLeft(1).add(ECConstants.ONE);
244
245            BigInteger Q = this.x;
246            BigInteger fourQ = modDouble(modDouble(Q));
247
248            BigInteger U, V;
249            Random rand = new Random();
250            do
251            {
252                BigInteger P;
253                do
254                {
255                    P = new BigInteger(q.bitLength(), rand);
256                }
257                while (P.compareTo(q) >= 0
258                    || !(P.multiply(P).subtract(fourQ).modPow(legendreExponent, q).equals(qMinusOne)));
259
260                BigInteger[] result = lucasSequence(P, Q, k);
261                U = result[0];
262                V = result[1];
263
264                if (modMult(V, V).equals(fourQ))
265                {
266                    // Integer division by 2, mod q
267                    if (V.testBit(0))
268                    {
269                        V = V.add(q);
270                    }
271
272                    V = V.shiftRight(1);
273
274                    //assert V.multiply(V).mod(q).equals(x);
275
276                    return new ECFieldElement.Fp(q, r, V);
277                }
278            }
279            while (U.equals(ECConstants.ONE) || U.equals(qMinusOne));
280
281            return null;
282
283//            BigInteger qMinusOne = q.subtract(ECConstants.ONE);
284//            BigInteger legendreExponent = qMinusOne.shiftRight(1); //divide(ECConstants.TWO);
285//            if (!(x.modPow(legendreExponent, q).equals(ECConstants.ONE)))
286//            {
287//                return null;
288//            }
289//
290//            Random rand = new Random();
291//            BigInteger fourX = x.shiftLeft(2);
292//
293//            BigInteger r;
294//            do
295//            {
296//                r = new BigInteger(q.bitLength(), rand);
297//            }
298//            while (r.compareTo(q) >= 0
299//                || !(r.multiply(r).subtract(fourX).modPow(legendreExponent, q).equals(qMinusOne)));
300//
301//            BigInteger n1 = qMinusOne.shiftRight(2); //.divide(ECConstants.FOUR);
302//            BigInteger n2 = n1.add(ECConstants.ONE); //q.add(ECConstants.THREE).divide(ECConstants.FOUR);
303//
304//            BigInteger wOne = WOne(r, x, q);
305//            BigInteger wSum = W(n1, wOne, q).add(W(n2, wOne, q)).mod(q);
306//            BigInteger twoR = r.shiftLeft(1); //ECConstants.TWO.multiply(r);
307//
308//            BigInteger root = twoR.modPow(q.subtract(ECConstants.TWO), q)
309//                .multiply(x).mod(q)
310//                .multiply(wSum).mod(q);
311//
312//            return new Fp(q, root);
313        }
314
315//        private static BigInteger W(BigInteger n, BigInteger wOne, BigInteger p)
316//        {
317//            if (n.equals(ECConstants.ONE))
318//            {
319//                return wOne;
320//            }
321//            boolean isEven = !n.testBit(0);
322//            n = n.shiftRight(1);//divide(ECConstants.TWO);
323//            if (isEven)
324//            {
325//                BigInteger w = W(n, wOne, p);
326//                return w.multiply(w).subtract(ECConstants.TWO).mod(p);
327//            }
328//            BigInteger w1 = W(n.add(ECConstants.ONE), wOne, p);
329//            BigInteger w2 = W(n, wOne, p);
330//            return w1.multiply(w2).subtract(wOne).mod(p);
331//        }
332//
333//        private BigInteger WOne(BigInteger r, BigInteger x, BigInteger p)
334//        {
335//            return r.multiply(r).multiply(x.modPow(q.subtract(ECConstants.TWO), q)).subtract(ECConstants.TWO).mod(p);
336//        }
337
338        private BigInteger[] lucasSequence(
339            BigInteger  P,
340            BigInteger  Q,
341            BigInteger  k)
342        {
343            int n = k.bitLength();
344            int s = k.getLowestSetBit();
345
346            BigInteger Uh = ECConstants.ONE;
347            BigInteger Vl = ECConstants.TWO;
348            BigInteger Vh = P;
349            BigInteger Ql = ECConstants.ONE;
350            BigInteger Qh = ECConstants.ONE;
351
352            for (int j = n - 1; j >= s + 1; --j)
353            {
354                Ql = modMult(Ql, Qh);
355
356                if (k.testBit(j))
357                {
358                    Qh = modMult(Ql, Q);
359                    Uh = modMult(Uh, Vh);
360                    Vl = modReduce(Vh.multiply(Vl).subtract(P.multiply(Ql)));
361                    Vh = modReduce(Vh.multiply(Vh).subtract(Qh.shiftLeft(1)));
362                }
363                else
364                {
365                    Qh = Ql;
366                    Uh = modReduce(Uh.multiply(Vl).subtract(Ql));
367                    Vh = modReduce(Vh.multiply(Vl).subtract(P.multiply(Ql)));
368                    Vl = modReduce(Vl.multiply(Vl).subtract(Ql.shiftLeft(1)));
369                }
370            }
371
372            Ql = modMult(Ql, Qh);
373            Qh = modMult(Ql, Q);
374            Uh = modReduce(Uh.multiply(Vl).subtract(Ql));
375            Vl = modReduce(Vh.multiply(Vl).subtract(P.multiply(Ql)));
376            Ql = modMult(Ql, Qh);
377
378            for (int j = 1; j <= s; ++j)
379            {
380                Uh = modMult(Uh, Vl);
381                Vl = modReduce(Vl.multiply(Vl).subtract(Ql.shiftLeft(1)));
382                Ql = modMult(Ql, Ql);
383            }
384
385            return new BigInteger[]{ Uh, Vl };
386        }
387
388        protected BigInteger modAdd(BigInteger x1, BigInteger x2)
389        {
390            BigInteger x3 = x1.add(x2);
391            if (x3.compareTo(q) >= 0)
392            {
393                x3 = x3.subtract(q);
394            }
395            return x3;
396        }
397
398        protected BigInteger modDouble(BigInteger x)
399        {
400            BigInteger _2x = x.shiftLeft(1);
401            if (_2x.compareTo(q) >= 0)
402            {
403                _2x = _2x.subtract(q);
404            }
405            return _2x;
406        }
407
408        protected BigInteger modMult(BigInteger x1, BigInteger x2)
409        {
410            return modReduce(x1.multiply(x2));
411        }
412
413        protected BigInteger modReduce(BigInteger x)
414        {
415//            if (naf != null)
416//            {
417//                int last = naf.length - 1;
418//                int bits = naf[last];
419//                while (x.bitLength() > (bits + 1))
420//                {
421//                    BigInteger u = x.shiftRight(bits);
422//                    BigInteger v = x.subtract(u.shiftLeft(bits));
423//
424//                    x = v;
425//
426//                    for (int i = 0; i < last; ++i)
427//                    {
428//                        int ni = naf[i];
429//                        if (ni < 0)
430//                        {
431//                            x = x.add(u.shiftLeft(~ni));
432//                        }
433//                        else
434//                        {
435//                            x = x.subtract(u.shiftLeft(ni));
436//                        }
437//                    }
438//                }
439//                while (x.compareTo(q) >= 0)
440//                {
441//                    x = x.subtract(q);
442//                }
443//            }
444//            else
445            if (r != null)
446            {
447                int qLen = q.bitLength();
448                while (x.bitLength() > (qLen + 1))
449                {
450                    BigInteger u = x.shiftRight(qLen);
451                    BigInteger v = x.subtract(u.shiftLeft(qLen));
452                    if (!r.equals(ONE))
453                    {
454                        u = u.multiply(r);
455                    }
456                    x = u.add(v);
457                }
458                while (x.compareTo(q) >= 0)
459                {
460                    x = x.subtract(q);
461                }
462            }
463            else
464            {
465                x = x.mod(q);
466            }
467            return x;
468        }
469
470        public boolean equals(Object other)
471        {
472            if (other == this)
473            {
474                return true;
475            }
476
477            if (!(other instanceof ECFieldElement.Fp))
478            {
479                return false;
480            }
481
482            ECFieldElement.Fp o = (ECFieldElement.Fp)other;
483            return q.equals(o.q) && x.equals(o.x);
484        }
485
486        public int hashCode()
487        {
488            return q.hashCode() ^ x.hashCode();
489        }
490    }
491
492//    /**
493//     * Class representing the Elements of the finite field
494//     * <code>F<sub>2<sup>m</sup></sub></code> in polynomial basis (PB)
495//     * representation. Both trinomial (TPB) and pentanomial (PPB) polynomial
496//     * basis representations are supported. Gaussian normal basis (GNB)
497//     * representation is not supported.
498//     */
499//    public static class F2m extends ECFieldElement
500//    {
501//        BigInteger x;
502//
503//        /**
504//         * Indicates gaussian normal basis representation (GNB). Number chosen
505//         * according to X9.62. GNB is not implemented at present.
506//         */
507//        public static final int GNB = 1;
508//
509//        /**
510//         * Indicates trinomial basis representation (TPB). Number chosen
511//         * according to X9.62.
512//         */
513//        public static final int TPB = 2;
514//
515//        /**
516//         * Indicates pentanomial basis representation (PPB). Number chosen
517//         * according to X9.62.
518//         */
519//        public static final int PPB = 3;
520//
521//        /**
522//         * TPB or PPB.
523//         */
524//        private int representation;
525//
526//        /**
527//         * The exponent <code>m</code> of <code>F<sub>2<sup>m</sup></sub></code>.
528//         */
529//        private int m;
530//
531//        /**
532//         * TPB: The integer <code>k</code> where <code>x<sup>m</sup> +
533//         * x<sup>k</sup> + 1</code> represents the reduction polynomial
534//         * <code>f(z)</code>.<br>
535//         * PPB: The integer <code>k1</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>.<br>
538//         */
539//        private int k1;
540//
541//        /**
542//         * TPB: Always set to <code>0</code><br>
543//         * PPB: The integer <code>k2</code> where <code>x<sup>m</sup> +
544//         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
545//         * represents the reduction polynomial <code>f(z)</code>.<br>
546//         */
547//        private int k2;
548//
549//        /**
550//         * TPB: Always set to <code>0</code><br>
551//         * PPB: The integer <code>k3</code> where <code>x<sup>m</sup> +
552//         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
553//         * represents the reduction polynomial <code>f(z)</code>.<br>
554//         */
555//        private int k3;
556//
557//        /**
558//         * Constructor for PPB.
559//         * @param m  The exponent <code>m</code> of
560//         * <code>F<sub>2<sup>m</sup></sub></code>.
561//         * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
562//         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
563//         * represents the reduction polynomial <code>f(z)</code>.
564//         * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
565//         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
566//         * represents the reduction polynomial <code>f(z)</code>.
567//         * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
568//         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
569//         * represents the reduction polynomial <code>f(z)</code>.
570//         * @param x The BigInteger representing the value of the field element.
571//         */
572//        public F2m(
573//            int m,
574//            int k1,
575//            int k2,
576//            int k3,
577//            BigInteger x)
578//        {
579////            super(x);
580//            this.x = x;
581//
582//            if ((k2 == 0) && (k3 == 0))
583//            {
584//                this.representation = TPB;
585//            }
586//            else
587//            {
588//                if (k2 >= k3)
589//                {
590//                    throw new IllegalArgumentException(
591//                            "k2 must be smaller than k3");
592//                }
593//                if (k2 <= 0)
594//                {
595//                    throw new IllegalArgumentException(
596//                            "k2 must be larger than 0");
597//                }
598//                this.representation = PPB;
599//            }
600//
601//            if (x.signum() < 0)
602//            {
603//                throw new IllegalArgumentException("x value cannot be negative");
604//            }
605//
606//            this.m = m;
607//            this.k1 = k1;
608//            this.k2 = k2;
609//            this.k3 = k3;
610//        }
611//
612//        /**
613//         * Constructor for TPB.
614//         * @param m  The exponent <code>m</code> of
615//         * <code>F<sub>2<sup>m</sup></sub></code>.
616//         * @param k The integer <code>k</code> where <code>x<sup>m</sup> +
617//         * x<sup>k</sup> + 1</code> represents the reduction
618//         * polynomial <code>f(z)</code>.
619//         * @param x The BigInteger representing the value of the field element.
620//         */
621//        public F2m(int m, int k, BigInteger x)
622//        {
623//            // Set k1 to k, and set k2 and k3 to 0
624//            this(m, k, 0, 0, x);
625//        }
626//
627//        public BigInteger toBigInteger()
628//        {
629//            return x;
630//        }
631//
632//        public String getFieldName()
633//        {
634//            return "F2m";
635//        }
636//
637//        public int getFieldSize()
638//        {
639//            return m;
640//        }
641//
642//        /**
643//         * Checks, if the ECFieldElements <code>a</code> and <code>b</code>
644//         * are elements of the same field <code>F<sub>2<sup>m</sup></sub></code>
645//         * (having the same representation).
646//         * @param a field element.
647//         * @param b field element to be compared.
648//         * @throws IllegalArgumentException if <code>a</code> and <code>b</code>
649//         * are not elements of the same field
650//         * <code>F<sub>2<sup>m</sup></sub></code> (having the same
651//         * representation).
652//         */
653//        public static void checkFieldElements(
654//            ECFieldElement a,
655//            ECFieldElement b)
656//        {
657//            if ((!(a instanceof F2m)) || (!(b instanceof F2m)))
658//            {
659//                throw new IllegalArgumentException("Field elements are not "
660//                        + "both instances of ECFieldElement.F2m");
661//            }
662//
663//            if ((a.toBigInteger().signum() < 0) || (b.toBigInteger().signum() < 0))
664//            {
665//                throw new IllegalArgumentException(
666//                        "x value may not be negative");
667//            }
668//
669//            ECFieldElement.F2m aF2m = (ECFieldElement.F2m)a;
670//            ECFieldElement.F2m bF2m = (ECFieldElement.F2m)b;
671//
672//            if ((aF2m.m != bF2m.m) || (aF2m.k1 != bF2m.k1)
673//                    || (aF2m.k2 != bF2m.k2) || (aF2m.k3 != bF2m.k3))
674//            {
675//                throw new IllegalArgumentException("Field elements are not "
676//                        + "elements of the same field F2m");
677//            }
678//
679//            if (aF2m.representation != bF2m.representation)
680//            {
681//                // Should never occur
682//                throw new IllegalArgumentException(
683//                        "One of the field "
684//                                + "elements are not elements has incorrect representation");
685//            }
686//        }
687//
688//        /**
689//         * Computes <code>z * a(z) mod f(z)</code>, where <code>f(z)</code> is
690//         * the reduction polynomial of <code>this</code>.
691//         * @param a The polynomial <code>a(z)</code> to be multiplied by
692//         * <code>z mod f(z)</code>.
693//         * @return <code>z * a(z) mod f(z)</code>
694//         */
695//        private BigInteger multZModF(final BigInteger a)
696//        {
697//            // Left-shift of a(z)
698//            BigInteger az = a.shiftLeft(1);
699//            if (az.testBit(this.m))
700//            {
701//                // If the coefficient of z^m in a(z) equals 1, reduction
702//                // modulo f(z) is performed: Add f(z) to to a(z):
703//                // Step 1: Unset mth coeffient of a(z)
704//                az = az.clearBit(this.m);
705//
706//                // Step 2: Add r(z) to a(z), where r(z) is defined as
707//                // f(z) = z^m + r(z), and k1, k2, k3 are the positions of
708//                // the non-zero coefficients in r(z)
709//                az = az.flipBit(0);
710//                az = az.flipBit(this.k1);
711//                if (this.representation == PPB)
712//                {
713//                    az = az.flipBit(this.k2);
714//                    az = az.flipBit(this.k3);
715//                }
716//            }
717//            return az;
718//        }
719//
720//        public ECFieldElement add(final ECFieldElement b)
721//        {
722//            // No check performed here for performance reasons. Instead the
723//            // elements involved are checked in ECPoint.F2m
724//            // checkFieldElements(this, b);
725//            if (b.toBigInteger().signum() == 0)
726//            {
727//                return this;
728//            }
729//
730//            return new F2m(this.m, this.k1, this.k2, this.k3, this.x.xor(b.toBigInteger()));
731//        }
732//
733//        public ECFieldElement subtract(final ECFieldElement b)
734//        {
735//            // Addition and subtraction are the same in F2m
736//            return add(b);
737//        }
738//
739//
740//        public ECFieldElement multiply(final ECFieldElement b)
741//        {
742//            // Left-to-right shift-and-add field multiplication in F2m
743//            // Input: Binary polynomials a(z) and b(z) of degree at most m-1
744//            // Output: c(z) = a(z) * b(z) mod f(z)
745//
746//            // No check performed here for performance reasons. Instead the
747//            // elements involved are checked in ECPoint.F2m
748//            // checkFieldElements(this, b);
749//            final BigInteger az = this.x;
750//            BigInteger bz = b.toBigInteger();
751//            BigInteger cz;
752//
753//            // Compute c(z) = a(z) * b(z) mod f(z)
754//            if (az.testBit(0))
755//            {
756//                cz = bz;
757//            }
758//            else
759//            {
760//                cz = ECConstants.ZERO;
761//            }
762//
763//            for (int i = 1; i < this.m; i++)
764//            {
765//                // b(z) := z * b(z) mod f(z)
766//                bz = multZModF(bz);
767//
768//                if (az.testBit(i))
769//                {
770//                    // If the coefficient of x^i in a(z) equals 1, b(z) is added
771//                    // to c(z)
772//                    cz = cz.xor(bz);
773//                }
774//            }
775//            return new ECFieldElement.F2m(m, this.k1, this.k2, this.k3, cz);
776//        }
777//
778//
779//        public ECFieldElement divide(final ECFieldElement b)
780//        {
781//            // There may be more efficient implementations
782//            ECFieldElement bInv = b.invert();
783//            return multiply(bInv);
784//        }
785//
786//        public ECFieldElement negate()
787//        {
788//            // -x == x holds for all x in F2m
789//            return this;
790//        }
791//
792//        public ECFieldElement square()
793//        {
794//            // Naive implementation, can probably be speeded up using modular
795//            // reduction
796//            return multiply(this);
797//        }
798//
799//        public ECFieldElement invert()
800//        {
801//            // Inversion in F2m using the extended Euclidean algorithm
802//            // Input: A nonzero polynomial a(z) of degree at most m-1
803//            // Output: a(z)^(-1) mod f(z)
804//
805//            // u(z) := a(z)
806//            BigInteger uz = this.x;
807//            if (uz.signum() <= 0)
808//            {
809//                throw new ArithmeticException("x is zero or negative, " +
810//                        "inversion is impossible");
811//            }
812//
813//            // v(z) := f(z)
814//            BigInteger vz = ECConstants.ZERO.setBit(m);
815//            vz = vz.setBit(0);
816//            vz = vz.setBit(this.k1);
817//            if (this.representation == PPB)
818//            {
819//                vz = vz.setBit(this.k2);
820//                vz = vz.setBit(this.k3);
821//            }
822//
823//            // g1(z) := 1, g2(z) := 0
824//            BigInteger g1z = ECConstants.ONE;
825//            BigInteger g2z = ECConstants.ZERO;
826//
827//            // while u != 1
828//            while (!(uz.equals(ECConstants.ZERO)))
829//            {
830//                // j := deg(u(z)) - deg(v(z))
831//                int j = uz.bitLength() - vz.bitLength();
832//
833//                // If j < 0 then: u(z) <-> v(z), g1(z) <-> g2(z), j := -j
834//                if (j < 0)
835//                {
836//                    final BigInteger uzCopy = uz;
837//                    uz = vz;
838//                    vz = uzCopy;
839//
840//                    final BigInteger g1zCopy = g1z;
841//                    g1z = g2z;
842//                    g2z = g1zCopy;
843//
844//                    j = -j;
845//                }
846//
847//                // u(z) := u(z) + z^j * v(z)
848//                // Note, that no reduction modulo f(z) is required, because
849//                // deg(u(z) + z^j * v(z)) <= max(deg(u(z)), j + deg(v(z)))
850//                // = max(deg(u(z)), deg(u(z)) - deg(v(z)) + deg(v(z))
851//                // = deg(u(z))
852//                uz = uz.xor(vz.shiftLeft(j));
853//
854//                // g1(z) := g1(z) + z^j * g2(z)
855//                g1z = g1z.xor(g2z.shiftLeft(j));
856////                if (g1z.bitLength() > this.m) {
857////                    throw new ArithmeticException(
858////                            "deg(g1z) >= m, g1z = " + g1z.toString(16));
859////                }
860//            }
861//            return new ECFieldElement.F2m(
862//                    this.m, this.k1, this.k2, this.k3, g2z);
863//        }
864//
865//        public ECFieldElement sqrt()
866//        {
867//            throw new RuntimeException("Not implemented");
868//        }
869//
870//        /**
871//         * @return the representation of the field
872//         * <code>F<sub>2<sup>m</sup></sub></code>, either of
873//         * TPB (trinomial
874//         * basis representation) or
875//         * PPB (pentanomial
876//         * basis representation).
877//         */
878//        public int getRepresentation()
879//        {
880//            return this.representation;
881//        }
882//
883//        /**
884//         * @return the degree <code>m</code> of the reduction polynomial
885//         * <code>f(z)</code>.
886//         */
887//        public int getM()
888//        {
889//            return this.m;
890//        }
891//
892//        /**
893//         * @return TPB: The integer <code>k</code> where <code>x<sup>m</sup> +
894//         * x<sup>k</sup> + 1</code> represents the reduction polynomial
895//         * <code>f(z)</code>.<br>
896//         * PPB: The integer <code>k1</code> where <code>x<sup>m</sup> +
897//         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
898//         * represents the reduction polynomial <code>f(z)</code>.<br>
899//         */
900//        public int getK1()
901//        {
902//            return this.k1;
903//        }
904//
905//        /**
906//         * @return TPB: Always returns <code>0</code><br>
907//         * PPB: The integer <code>k2</code> where <code>x<sup>m</sup> +
908//         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
909//         * represents the reduction polynomial <code>f(z)</code>.<br>
910//         */
911//        public int getK2()
912//        {
913//            return this.k2;
914//        }
915//
916//        /**
917//         * @return TPB: Always set to <code>0</code><br>
918//         * PPB: The integer <code>k3</code> where <code>x<sup>m</sup> +
919//         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
920//         * represents the reduction polynomial <code>f(z)</code>.<br>
921//         */
922//        public int getK3()
923//        {
924//            return this.k3;
925//        }
926//
927//        public boolean equals(Object anObject)
928//        {
929//            if (anObject == this)
930//            {
931//                return true;
932//            }
933//
934//            if (!(anObject instanceof ECFieldElement.F2m))
935//            {
936//                return false;
937//            }
938//
939//            ECFieldElement.F2m b = (ECFieldElement.F2m)anObject;
940//
941//            return ((this.m == b.m) && (this.k1 == b.k1) && (this.k2 == b.k2)
942//                && (this.k3 == b.k3)
943//                && (this.representation == b.representation)
944//                && (this.x.equals(b.x)));
945//        }
946//
947//        public int hashCode()
948//        {
949//            return x.hashCode() ^ m ^ k1 ^ k2 ^ k3;
950//        }
951//    }
952
953    /**
954     * Class representing the Elements of the finite field
955     * <code>F<sub>2<sup>m</sup></sub></code> in polynomial basis (PB)
956     * representation. Both trinomial (TPB) and pentanomial (PPB) polynomial
957     * basis representations are supported. Gaussian normal basis (GNB)
958     * representation is not supported.
959     */
960    public static class F2m extends ECFieldElement
961    {
962        /**
963         * Indicates gaussian normal basis representation (GNB). Number chosen
964         * according to X9.62. GNB is not implemented at present.
965         */
966        public static final int GNB = 1;
967
968        /**
969         * Indicates trinomial basis representation (TPB). Number chosen
970         * according to X9.62.
971         */
972        public static final int TPB = 2;
973
974        /**
975         * Indicates pentanomial basis representation (PPB). Number chosen
976         * according to X9.62.
977         */
978        public static final int PPB = 3;
979
980        /**
981         * TPB or PPB.
982         */
983        private int representation;
984
985        /**
986         * The exponent <code>m</code> of <code>F<sub>2<sup>m</sup></sub></code>.
987         */
988        private int m;
989
990//        /**
991//         * TPB: The integer <code>k</code> where <code>x<sup>m</sup> +
992//         * x<sup>k</sup> + 1</code> represents the reduction polynomial
993//         * <code>f(z)</code>.<br>
994//         * PPB: The integer <code>k1</code> where <code>x<sup>m</sup> +
995//         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
996//         * represents the reduction polynomial <code>f(z)</code>.<br>
997//         */
998//        private int k1;
999//
1000//        /**
1001//         * TPB: Always set to <code>0</code><br>
1002//         * PPB: The integer <code>k2</code> where <code>x<sup>m</sup> +
1003//         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
1004//         * represents the reduction polynomial <code>f(z)</code>.<br>
1005//         */
1006//        private int k2;
1007//
1008//        /**
1009//         * TPB: Always set to <code>0</code><br>
1010//         * PPB: The integer <code>k3</code> where <code>x<sup>m</sup> +
1011//         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
1012//         * represents the reduction polynomial <code>f(z)</code>.<br>
1013//         */
1014//        private int k3;
1015
1016        private int[] ks;
1017
1018        /**
1019         * The <code>LongArray</code> holding the bits.
1020         */
1021        private LongArray x;
1022
1023        /**
1024         * Constructor for PPB.
1025         * @param m  The exponent <code>m</code> of
1026         * <code>F<sub>2<sup>m</sup></sub></code>.
1027         * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
1028         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
1029         * represents the reduction polynomial <code>f(z)</code>.
1030         * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
1031         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
1032         * represents the reduction polynomial <code>f(z)</code>.
1033         * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
1034         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
1035         * represents the reduction polynomial <code>f(z)</code>.
1036         * @param x The BigInteger representing the value of the field element.
1037         * @deprecated Use ECCurve.fromBigInteger to construct field elements
1038         */
1039        public F2m(
1040            int m,
1041            int k1,
1042            int k2,
1043            int k3,
1044            BigInteger x)
1045        {
1046            if ((k2 == 0) && (k3 == 0))
1047            {
1048                this.representation = TPB;
1049                this.ks = new int[]{ k1 };
1050            }
1051            else
1052            {
1053                if (k2 >= k3)
1054                {
1055                    throw new IllegalArgumentException(
1056                            "k2 must be smaller than k3");
1057                }
1058                if (k2 <= 0)
1059                {
1060                    throw new IllegalArgumentException(
1061                            "k2 must be larger than 0");
1062                }
1063                this.representation = PPB;
1064                this.ks = new int[]{ k1, k2, k3 };
1065            }
1066
1067            this.m = m;
1068            this.x = new LongArray(x);
1069        }
1070
1071        /**
1072         * Constructor for TPB.
1073         * @param m  The exponent <code>m</code> of
1074         * <code>F<sub>2<sup>m</sup></sub></code>.
1075         * @param k The integer <code>k</code> where <code>x<sup>m</sup> +
1076         * x<sup>k</sup> + 1</code> represents the reduction
1077         * polynomial <code>f(z)</code>.
1078         * @param x The BigInteger representing the value of the field element.
1079         * @deprecated Use ECCurve.fromBigInteger to construct field elements
1080         */
1081        public F2m(int m, int k, BigInteger x)
1082        {
1083            // Set k1 to k, and set k2 and k3 to 0
1084            this(m, k, 0, 0, x);
1085        }
1086
1087        private F2m(int m, int[] ks, LongArray x)
1088        {
1089            this.m = m;
1090            this.representation = (ks.length == 1) ? TPB : PPB;
1091            this.ks = ks;
1092            this.x = x;
1093        }
1094
1095        public int bitLength()
1096        {
1097            return x.degree();
1098        }
1099
1100        public boolean isZero()
1101        {
1102            return x.isZero();
1103        }
1104
1105        public boolean testBitZero()
1106        {
1107            return x.testBitZero();
1108        }
1109
1110        public BigInteger toBigInteger()
1111        {
1112            return x.toBigInteger();
1113        }
1114
1115        public String getFieldName()
1116        {
1117            return "F2m";
1118        }
1119
1120        public int getFieldSize()
1121        {
1122            return m;
1123        }
1124
1125        /**
1126         * Checks, if the ECFieldElements <code>a</code> and <code>b</code>
1127         * are elements of the same field <code>F<sub>2<sup>m</sup></sub></code>
1128         * (having the same representation).
1129         * @param a field element.
1130         * @param b field element to be compared.
1131         * @throws IllegalArgumentException if <code>a</code> and <code>b</code>
1132         * are not elements of the same field
1133         * <code>F<sub>2<sup>m</sup></sub></code> (having the same
1134         * representation).
1135         */
1136        public static void checkFieldElements(
1137            ECFieldElement a,
1138            ECFieldElement b)
1139        {
1140            if ((!(a instanceof F2m)) || (!(b instanceof F2m)))
1141            {
1142                throw new IllegalArgumentException("Field elements are not "
1143                        + "both instances of ECFieldElement.F2m");
1144            }
1145
1146            ECFieldElement.F2m aF2m = (ECFieldElement.F2m)a;
1147            ECFieldElement.F2m bF2m = (ECFieldElement.F2m)b;
1148
1149            if (aF2m.representation != bF2m.representation)
1150            {
1151                // Should never occur
1152                throw new IllegalArgumentException("One of the F2m field elements has incorrect representation");
1153            }
1154
1155            if ((aF2m.m != bF2m.m) || !Arrays.areEqual(aF2m.ks, bF2m.ks))
1156            {
1157                throw new IllegalArgumentException("Field elements are not elements of the same field F2m");
1158            }
1159        }
1160
1161        public ECFieldElement add(final ECFieldElement b)
1162        {
1163            // No check performed here for performance reasons. Instead the
1164            // elements involved are checked in ECPoint.F2m
1165            // checkFieldElements(this, b);
1166            LongArray iarrClone = (LongArray)this.x.clone();
1167            F2m bF2m = (F2m)b;
1168            iarrClone.addShiftedByWords(bF2m.x, 0);
1169            return new F2m(m, ks, iarrClone);
1170        }
1171
1172        public ECFieldElement addOne()
1173        {
1174            return new F2m(m, ks, x.addOne());
1175        }
1176
1177        public ECFieldElement subtract(final ECFieldElement b)
1178        {
1179            // Addition and subtraction are the same in F2m
1180            return add(b);
1181        }
1182
1183        public ECFieldElement multiply(final ECFieldElement b)
1184        {
1185            // Right-to-left comb multiplication in the LongArray
1186            // Input: Binary polynomials a(z) and b(z) of degree at most m-1
1187            // Output: c(z) = a(z) * b(z) mod f(z)
1188
1189            // No check performed here for performance reasons. Instead the
1190            // elements involved are checked in ECPoint.F2m
1191            // checkFieldElements(this, b);
1192            return new F2m(m, ks, x.modMultiply(((F2m)b).x, m, ks));
1193        }
1194
1195        public ECFieldElement divide(final ECFieldElement b)
1196        {
1197            // There may be more efficient implementations
1198            ECFieldElement bInv = b.invert();
1199            return multiply(bInv);
1200        }
1201
1202        public ECFieldElement negate()
1203        {
1204            // -x == x holds for all x in F2m
1205            return this;
1206        }
1207
1208        public ECFieldElement square()
1209        {
1210            return new F2m(m, ks, x.modSquare(m, ks));
1211        }
1212
1213        public ECFieldElement invert()
1214        {
1215            return new ECFieldElement.F2m(this.m, this.ks, this.x.modInverse(m, ks));
1216        }
1217
1218        public ECFieldElement sqrt()
1219        {
1220            throw new RuntimeException("Not implemented");
1221        }
1222
1223        /**
1224         * @return the representation of the field
1225         * <code>F<sub>2<sup>m</sup></sub></code>, either of
1226         * TPB (trinomial
1227         * basis representation) or
1228         * PPB (pentanomial
1229         * basis representation).
1230         */
1231        public int getRepresentation()
1232        {
1233            return this.representation;
1234        }
1235
1236        /**
1237         * @return the degree <code>m</code> of the reduction polynomial
1238         * <code>f(z)</code>.
1239         */
1240        public int getM()
1241        {
1242            return this.m;
1243        }
1244
1245        /**
1246         * @return TPB: The integer <code>k</code> where <code>x<sup>m</sup> +
1247         * x<sup>k</sup> + 1</code> represents the reduction polynomial
1248         * <code>f(z)</code>.<br>
1249         * PPB: The integer <code>k1</code> where <code>x<sup>m</sup> +
1250         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
1251         * represents the reduction polynomial <code>f(z)</code>.<br>
1252         */
1253        public int getK1()
1254        {
1255            return this.ks[0];
1256        }
1257
1258        /**
1259         * @return TPB: Always returns <code>0</code><br>
1260         * PPB: The integer <code>k2</code> where <code>x<sup>m</sup> +
1261         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
1262         * represents the reduction polynomial <code>f(z)</code>.<br>
1263         */
1264        public int getK2()
1265        {
1266            return this.ks.length >= 2 ? this.ks[1] : 0;
1267        }
1268
1269        /**
1270         * @return TPB: Always set to <code>0</code><br>
1271         * PPB: The integer <code>k3</code> where <code>x<sup>m</sup> +
1272         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
1273         * represents the reduction polynomial <code>f(z)</code>.<br>
1274         */
1275        public int getK3()
1276        {
1277            return this.ks.length >= 3 ? this.ks[2] : 0;
1278        }
1279
1280        public boolean equals(Object anObject)
1281        {
1282            if (anObject == this)
1283            {
1284                return true;
1285            }
1286
1287            if (!(anObject instanceof ECFieldElement.F2m))
1288            {
1289                return false;
1290            }
1291
1292            ECFieldElement.F2m b = (ECFieldElement.F2m)anObject;
1293
1294            return ((this.m == b.m)
1295                && (this.representation == b.representation)
1296                && Arrays.areEqual(this.ks, b.ks)
1297                && (this.x.equals(b.x)));
1298        }
1299
1300        public int hashCode()
1301        {
1302            return x.hashCode() ^ m ^ Arrays.hashCode(ks);
1303        }
1304    }
1305}
1306