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