• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.bouncycastle.math.ec;
2 
3 import java.math.BigInteger;
4 import java.util.Random;
5 
6 import org.bouncycastle.util.Arrays;
7 import org.bouncycastle.util.BigIntegers;
8 
9 public abstract class ECFieldElement
10     implements ECConstants
11 {
toBigInteger()12     public abstract BigInteger     toBigInteger();
getFieldName()13     public abstract String         getFieldName();
getFieldSize()14     public abstract int            getFieldSize();
add(ECFieldElement b)15     public abstract ECFieldElement add(ECFieldElement b);
addOne()16     public abstract ECFieldElement addOne();
subtract(ECFieldElement b)17     public abstract ECFieldElement subtract(ECFieldElement b);
multiply(ECFieldElement b)18     public abstract ECFieldElement multiply(ECFieldElement b);
divide(ECFieldElement b)19     public abstract ECFieldElement divide(ECFieldElement b);
negate()20     public abstract ECFieldElement negate();
square()21     public abstract ECFieldElement square();
invert()22     public abstract ECFieldElement invert();
sqrt()23     public abstract ECFieldElement sqrt();
24 
bitLength()25     public int bitLength()
26     {
27         return toBigInteger().bitLength();
28     }
29 
isZero()30     public boolean isZero()
31     {
32         return 0 == toBigInteger().signum();
33     }
34 
testBitZero()35     public boolean testBitZero()
36     {
37         return toBigInteger().testBit(0);
38     }
39 
toString()40     public String toString()
41     {
42         return this.toBigInteger().toString(16);
43     }
44 
getEncoded()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 
calculateResidue(BigInteger p)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          */
Fp(BigInteger q, BigInteger x)103         public Fp(BigInteger q, BigInteger x)
104         {
105             this(q, calculateResidue(q), x);
106         }
107 
Fp(BigInteger q, BigInteger r, BigInteger x)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 
toBigInteger()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          */
getFieldName()130         public String getFieldName()
131         {
132             return "Fp";
133         }
134 
getFieldSize()135         public int getFieldSize()
136         {
137             return q.bitLength();
138         }
139 
getQ()140         public BigInteger getQ()
141         {
142             return q;
143         }
144 
add(ECFieldElement b)145         public ECFieldElement add(ECFieldElement b)
146         {
147             return new Fp(q, r, modAdd(x, b.toBigInteger()));
148         }
149 
addOne()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 
subtract(ECFieldElement b)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 
multiply(ECFieldElement b)171         public ECFieldElement multiply(ECFieldElement b)
172         {
173             return new Fp(q, r, modMult(x, b.toBigInteger()));
174         }
175 
divide(ECFieldElement b)176         public ECFieldElement divide(ECFieldElement b)
177         {
178             return new Fp(q, modMult(x, b.toBigInteger().modInverse(q)));
179         }
180 
negate()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 
square()199         public ECFieldElement square()
200         {
201             return new Fp(q, r, modMult(x, x));
202         }
203 
invert()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          */
sqrt()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 
lucasSequence( BigInteger P, BigInteger Q, BigInteger k)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 
modAdd(BigInteger x1, BigInteger x2)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 
modDouble(BigInteger x)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 
modMult(BigInteger x1, BigInteger x2)408         protected BigInteger modMult(BigInteger x1, BigInteger x2)
409         {
410             return modReduce(x1.multiply(x2));
411         }
412 
modReduce(BigInteger x)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 
equals(Object other)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 
hashCode()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          */
F2m( int m, int k1, int k2, int k3, BigInteger x)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          */
F2m(int m, int k, BigInteger x)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 
F2m(int m, int[] ks, LongArray x)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 
bitLength()1095         public int bitLength()
1096         {
1097             return x.degree();
1098         }
1099 
isZero()1100         public boolean isZero()
1101         {
1102             return x.isZero();
1103         }
1104 
testBitZero()1105         public boolean testBitZero()
1106         {
1107             return x.testBitZero();
1108         }
1109 
toBigInteger()1110         public BigInteger toBigInteger()
1111         {
1112             return x.toBigInteger();
1113         }
1114 
getFieldName()1115         public String getFieldName()
1116         {
1117             return "F2m";
1118         }
1119 
getFieldSize()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          */
checkFieldElements( ECFieldElement a, ECFieldElement b)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 
add(final ECFieldElement b)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 
addOne()1172         public ECFieldElement addOne()
1173         {
1174             return new F2m(m, ks, x.addOne());
1175         }
1176 
subtract(final ECFieldElement b)1177         public ECFieldElement subtract(final ECFieldElement b)
1178         {
1179             // Addition and subtraction are the same in F2m
1180             return add(b);
1181         }
1182 
multiply(final ECFieldElement b)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 
divide(final ECFieldElement b)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 
negate()1202         public ECFieldElement negate()
1203         {
1204             // -x == x holds for all x in F2m
1205             return this;
1206         }
1207 
square()1208         public ECFieldElement square()
1209         {
1210             return new F2m(m, ks, x.modSquare(m, ks));
1211         }
1212 
invert()1213         public ECFieldElement invert()
1214         {
1215             return new ECFieldElement.F2m(this.m, this.ks, this.x.modInverse(m, ks));
1216         }
1217 
sqrt()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          */
getRepresentation()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          */
getM()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          */
getK1()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          */
getK2()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          */
getK3()1275         public int getK3()
1276         {
1277             return this.ks.length >= 3 ? this.ks[2] : 0;
1278         }
1279 
equals(Object anObject)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 
hashCode()1300         public int hashCode()
1301         {
1302             return x.hashCode() ^ m ^ Arrays.hashCode(ks);
1303         }
1304     }
1305 }
1306