ECCurve.java revision 5db505e1f6a68c8d5dfdb0fed0b8607dea7bed96
1package org.bouncycastle.math.ec;
2
3import java.math.BigInteger;
4import java.util.Random;
5
6import org.bouncycastle.util.BigIntegers;
7
8/**
9 * base class for an elliptic curve
10 */
11public abstract class ECCurve
12{
13    public static final int COORD_AFFINE = 0;
14    public static final int COORD_HOMOGENEOUS = 1;
15    public static final int COORD_JACOBIAN = 2;
16    public static final int COORD_JACOBIAN_CHUDNOVSKY = 3;
17    public static final int COORD_JACOBIAN_MODIFIED = 4;
18    public static final int COORD_LAMBDA_AFFINE = 5;
19    public static final int COORD_LAMBDA_PROJECTIVE = 6;
20    public static final int COORD_SKEWED = 7;
21
22    public static int[] getAllCoordinateSystems()
23    {
24        return new int[]{ COORD_AFFINE, COORD_HOMOGENEOUS, COORD_JACOBIAN, COORD_JACOBIAN_CHUDNOVSKY,
25            COORD_JACOBIAN_MODIFIED, COORD_LAMBDA_AFFINE, COORD_LAMBDA_PROJECTIVE, COORD_SKEWED };
26    }
27
28    public class Config
29    {
30        protected int coord;
31        protected ECMultiplier multiplier;
32
33        Config(int coord, ECMultiplier multiplier)
34        {
35            this.coord = coord;
36            this.multiplier = multiplier;
37        }
38
39        public Config setCoordinateSystem(int coord)
40        {
41            this.coord = coord;
42            return this;
43        }
44
45        public Config setMultiplier(ECMultiplier multiplier)
46        {
47            this.multiplier = multiplier;
48            return this;
49        }
50
51        public ECCurve create()
52        {
53            if (!supportsCoordinateSystem(coord))
54            {
55                throw new IllegalStateException("unsupported coordinate system");
56            }
57
58            ECCurve c = cloneCurve();
59            if (c == ECCurve.this)
60            {
61                throw new IllegalStateException("implementation returned current curve");
62            }
63
64            c.coord = coord;
65            c.multiplier = multiplier;
66
67            return c;
68        }
69    }
70
71    protected ECFieldElement a, b;
72    protected int coord = COORD_AFFINE;
73    protected ECMultiplier multiplier = null;
74
75    public abstract int getFieldSize();
76
77    public abstract ECFieldElement fromBigInteger(BigInteger x);
78
79    public Config configure()
80    {
81        return new Config(this.coord, this.multiplier);
82    }
83
84    public ECPoint createPoint(BigInteger x, BigInteger y)
85    {
86        return createPoint(x, y, false);
87    }
88
89    /**
90     * @deprecated per-point compression property will be removed, use {@link #createPoint(BigInteger, BigInteger)}
91     * and refer {@link ECPoint#getEncoded(boolean)}
92     */
93    public ECPoint createPoint(BigInteger x, BigInteger y, boolean withCompression)
94    {
95        return createRawPoint(fromBigInteger(x), fromBigInteger(y), withCompression);
96    }
97
98    protected abstract ECCurve cloneCurve();
99
100    protected abstract ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression);
101
102    protected ECMultiplier createDefaultMultiplier()
103    {
104        return new WNafL2RMultiplier();
105    }
106
107    public boolean supportsCoordinateSystem(int coord)
108    {
109        return coord == COORD_AFFINE;
110    }
111
112    public PreCompInfo getPreCompInfo(ECPoint p)
113    {
114        checkPoint(p);
115        return p.preCompInfo;
116    }
117
118    /**
119     * Sets the <code>PreCompInfo</code> for a point on this curve. Used by
120     * <code>ECMultiplier</code>s to save the precomputation for this <code>ECPoint</code> for use
121     * by subsequent multiplication.
122     *
123     * @param point
124     *            The <code>ECPoint</code> to store precomputations for.
125     * @param preCompInfo
126     *            The values precomputed by the <code>ECMultiplier</code>.
127     */
128    public void setPreCompInfo(ECPoint point, PreCompInfo preCompInfo)
129    {
130        checkPoint(point);
131        point.preCompInfo = preCompInfo;
132    }
133
134    public ECPoint importPoint(ECPoint p)
135    {
136        if (this == p.getCurve())
137        {
138            return p;
139        }
140        if (p.isInfinity())
141        {
142            return getInfinity();
143        }
144
145        // TODO Default behaviour could be improved if the two curves have the same coordinate system by copying any Z coordinates.
146        p = p.normalize();
147
148        return createPoint(p.getXCoord().toBigInteger(), p.getYCoord().toBigInteger(), p.withCompression);
149    }
150
151    /**
152     * Normalization ensures that any projective coordinate is 1, and therefore that the x, y
153     * coordinates reflect those of the equivalent point in an affine coordinate system. Where more
154     * than one point is to be normalized, this method will generally be more efficient than
155     * normalizing each point separately.
156     *
157     * @param points
158     *            An array of points that will be updated in place with their normalized versions,
159     *            where necessary
160     */
161    public void normalizeAll(ECPoint[] points)
162    {
163        checkPoints(points);
164
165        if (this.getCoordinateSystem() == ECCurve.COORD_AFFINE)
166        {
167            return;
168        }
169
170        /*
171         * Figure out which of the points actually need to be normalized
172         */
173        ECFieldElement[] zs = new ECFieldElement[points.length];
174        int[] indices = new int[points.length];
175        int count = 0;
176        for (int i = 0; i < points.length; ++i)
177        {
178            ECPoint p = points[i];
179            if (null != p && !p.isNormalized())
180            {
181                zs[count] = p.getZCoord(0);
182                indices[count++] = i;
183            }
184        }
185
186        if (count == 0)
187        {
188            return;
189        }
190
191        ECAlgorithms.implMontgomeryTrick(zs, 0, count);
192
193        for (int j = 0; j < count; ++j)
194        {
195            int index = indices[j];
196            points[index] = points[index].normalize(zs[j]);
197        }
198    }
199
200    public abstract ECPoint getInfinity();
201
202    public ECFieldElement getA()
203    {
204        return a;
205    }
206
207    public ECFieldElement getB()
208    {
209        return b;
210    }
211
212    public int getCoordinateSystem()
213    {
214        return coord;
215    }
216
217    protected abstract ECPoint decompressPoint(int yTilde, BigInteger X1);
218
219    /**
220     * Sets the default <code>ECMultiplier</code>, unless already set.
221     */
222    public ECMultiplier getMultiplier()
223    {
224        if (this.multiplier == null)
225        {
226            this.multiplier = createDefaultMultiplier();
227        }
228        return this.multiplier;
229    }
230
231    /**
232     * Decode a point on this curve from its ASN.1 encoding. The different
233     * encodings are taken account of, including point compression for
234     * <code>F<sub>p</sub></code> (X9.62 s 4.2.1 pg 17).
235     * @return The decoded point.
236     */
237    public ECPoint decodePoint(byte[] encoded)
238    {
239        ECPoint p = null;
240        int expectedLength = (getFieldSize() + 7) / 8;
241
242        switch (encoded[0])
243        {
244        case 0x00: // infinity
245        {
246            if (encoded.length != 1)
247            {
248                throw new IllegalArgumentException("Incorrect length for infinity encoding");
249            }
250
251            p = getInfinity();
252            break;
253        }
254        case 0x02: // compressed
255        case 0x03: // compressed
256        {
257            if (encoded.length != (expectedLength + 1))
258            {
259                throw new IllegalArgumentException("Incorrect length for compressed encoding");
260            }
261
262            int yTilde = encoded[0] & 1;
263            BigInteger X = BigIntegers.fromUnsignedByteArray(encoded, 1, expectedLength);
264
265            p = decompressPoint(yTilde, X);
266            break;
267        }
268        case 0x04: // uncompressed
269        case 0x06: // hybrid
270        case 0x07: // hybrid
271        {
272            if (encoded.length != (2 * expectedLength + 1))
273            {
274                throw new IllegalArgumentException("Incorrect length for uncompressed/hybrid encoding");
275            }
276
277            BigInteger X = BigIntegers.fromUnsignedByteArray(encoded, 1, expectedLength);
278            BigInteger Y = BigIntegers.fromUnsignedByteArray(encoded, 1 + expectedLength, expectedLength);
279
280            p = createPoint(X, Y);
281            break;
282        }
283        default:
284            throw new IllegalArgumentException("Invalid point encoding 0x" + Integer.toString(encoded[0], 16));
285        }
286
287        return p;
288    }
289
290    protected void checkPoint(ECPoint point)
291    {
292        if (null == point || (this != point.getCurve()))
293        {
294            throw new IllegalArgumentException("'point' must be non-null and on this curve");
295        }
296    }
297
298    protected void checkPoints(ECPoint[] points)
299    {
300        if (points == null)
301        {
302            throw new IllegalArgumentException("'points' cannot be null");
303        }
304
305        for (int i = 0; i < points.length; ++i)
306        {
307            ECPoint point = points[i];
308            if (null != point && this != point.getCurve())
309            {
310                throw new IllegalArgumentException("'points' entries must be null or on this curve");
311            }
312        }
313    }
314
315    /**
316     * Elliptic curve over Fp
317     */
318    public static class Fp extends ECCurve
319    {
320        private static final int FP_DEFAULT_COORDS = COORD_JACOBIAN_MODIFIED;
321
322        BigInteger q, r;
323        ECPoint.Fp infinity;
324
325        public Fp(BigInteger q, BigInteger a, BigInteger b)
326        {
327            this.q = q;
328            this.r = ECFieldElement.Fp.calculateResidue(q);
329            this.infinity = new ECPoint.Fp(this, null, null);
330
331            this.a = fromBigInteger(a);
332            this.b = fromBigInteger(b);
333            this.coord = FP_DEFAULT_COORDS;
334        }
335
336        protected Fp(BigInteger q, BigInteger r, ECFieldElement a, ECFieldElement b)
337        {
338            this.q = q;
339            this.r = r;
340            this.infinity = new ECPoint.Fp(this, null, null);
341
342            this.a = a;
343            this.b = b;
344            this.coord = FP_DEFAULT_COORDS;
345        }
346
347        protected ECCurve cloneCurve()
348        {
349            return new Fp(q, r, a, b);
350        }
351
352        public boolean supportsCoordinateSystem(int coord)
353        {
354            switch (coord)
355            {
356            case COORD_AFFINE:
357            case COORD_HOMOGENEOUS:
358            case COORD_JACOBIAN:
359            case COORD_JACOBIAN_MODIFIED:
360                return true;
361            default:
362                return false;
363            }
364        }
365
366        public BigInteger getQ()
367        {
368            return q;
369        }
370
371        public int getFieldSize()
372        {
373            return q.bitLength();
374        }
375
376        public ECFieldElement fromBigInteger(BigInteger x)
377        {
378            return new ECFieldElement.Fp(this.q, this.r, x);
379        }
380
381        protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)
382        {
383            return new ECPoint.Fp(this, x, y, withCompression);
384        }
385
386        public ECPoint importPoint(ECPoint p)
387        {
388            if (this != p.getCurve() && this.getCoordinateSystem() == COORD_JACOBIAN && !p.isInfinity())
389            {
390                switch (p.getCurve().getCoordinateSystem())
391                {
392                case COORD_JACOBIAN:
393                case COORD_JACOBIAN_CHUDNOVSKY:
394                case COORD_JACOBIAN_MODIFIED:
395                    return new ECPoint.Fp(this,
396                        fromBigInteger(p.x.toBigInteger()),
397                        fromBigInteger(p.y.toBigInteger()),
398                        new ECFieldElement[]{ fromBigInteger(p.zs[0].toBigInteger()) },
399                        p.withCompression);
400                default:
401                    break;
402                }
403            }
404
405            return super.importPoint(p);
406        }
407
408        protected ECPoint decompressPoint(int yTilde, BigInteger X1)
409        {
410            ECFieldElement x = fromBigInteger(X1);
411            ECFieldElement alpha = x.multiply(x.square().add(a)).add(b);
412            ECFieldElement beta = alpha.sqrt();
413
414            //
415            // if we can't find a sqrt we haven't got a point on the
416            // curve - run!
417            //
418            if (beta == null)
419            {
420                throw new RuntimeException("Invalid point compression");
421            }
422
423            BigInteger betaValue = beta.toBigInteger();
424            if (betaValue.testBit(0) != (yTilde == 1))
425            {
426                // Use the other root
427                beta = fromBigInteger(q.subtract(betaValue));
428            }
429
430            return new ECPoint.Fp(this, x, beta, true);
431        }
432
433        public ECPoint getInfinity()
434        {
435            return infinity;
436        }
437
438        public boolean equals(
439            Object anObject)
440        {
441            if (anObject == this)
442            {
443                return true;
444            }
445
446            if (!(anObject instanceof ECCurve.Fp))
447            {
448                return false;
449            }
450
451            ECCurve.Fp other = (ECCurve.Fp) anObject;
452
453            return this.q.equals(other.q)
454                    && a.equals(other.a) && b.equals(other.b);
455        }
456
457        public int hashCode()
458        {
459            return a.hashCode() ^ b.hashCode() ^ q.hashCode();
460        }
461    }
462
463    /**
464     * Elliptic curves over F2m. The Weierstrass equation is given by
465     * <code>y<sup>2</sup> + xy = x<sup>3</sup> + ax<sup>2</sup> + b</code>.
466     */
467    public static class F2m extends ECCurve
468    {
469        private static final int F2M_DEFAULT_COORDS = COORD_AFFINE;
470
471        /**
472         * The exponent <code>m</code> of <code>F<sub>2<sup>m</sup></sub></code>.
473         */
474        private int m;  // can't be final - JDK 1.1
475
476        /**
477         * TPB: The integer <code>k</code> where <code>x<sup>m</sup> +
478         * x<sup>k</sup> + 1</code> represents the reduction polynomial
479         * <code>f(z)</code>.<br>
480         * PPB: The integer <code>k1</code> where <code>x<sup>m</sup> +
481         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
482         * represents the reduction polynomial <code>f(z)</code>.<br>
483         */
484        private int k1;  // can't be final - JDK 1.1
485
486        /**
487         * TPB: Always set to <code>0</code><br>
488         * PPB: The integer <code>k2</code> where <code>x<sup>m</sup> +
489         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
490         * represents the reduction polynomial <code>f(z)</code>.<br>
491         */
492        private int k2;  // can't be final - JDK 1.1
493
494        /**
495         * TPB: Always set to <code>0</code><br>
496         * PPB: The integer <code>k3</code> where <code>x<sup>m</sup> +
497         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
498         * represents the reduction polynomial <code>f(z)</code>.<br>
499         */
500        private int k3;  // can't be final - JDK 1.1
501
502        /**
503         * The order of the base point of the curve.
504         */
505        private BigInteger n;  // can't be final - JDK 1.1
506
507        /**
508         * The cofactor of the curve.
509         */
510        private BigInteger h;  // can't be final - JDK 1.1
511
512         /**
513         * The point at infinity on this curve.
514         */
515        private ECPoint.F2m infinity;  // can't be final - JDK 1.1
516
517        /**
518         * The parameter <code>&mu;</code> of the elliptic curve if this is
519         * a Koblitz curve.
520         */
521        private byte mu = 0;
522
523        /**
524         * The auxiliary values <code>s<sub>0</sub></code> and
525         * <code>s<sub>1</sub></code> used for partial modular reduction for
526         * Koblitz curves.
527         */
528        private BigInteger[] si = null;
529
530        /**
531         * Constructor for Trinomial Polynomial Basis (TPB).
532         * @param m  The exponent <code>m</code> of
533         * <code>F<sub>2<sup>m</sup></sub></code>.
534         * @param k The integer <code>k</code> where <code>x<sup>m</sup> +
535         * x<sup>k</sup> + 1</code> represents the reduction
536         * polynomial <code>f(z)</code>.
537         * @param a The coefficient <code>a</code> in the Weierstrass equation
538         * for non-supersingular elliptic curves over
539         * <code>F<sub>2<sup>m</sup></sub></code>.
540         * @param b The coefficient <code>b</code> in the Weierstrass equation
541         * for non-supersingular elliptic curves over
542         * <code>F<sub>2<sup>m</sup></sub></code>.
543         */
544        public F2m(
545            int m,
546            int k,
547            BigInteger a,
548            BigInteger b)
549        {
550            this(m, k, 0, 0, a, b, null, null);
551        }
552
553        /**
554         * Constructor for Trinomial Polynomial Basis (TPB).
555         * @param m  The exponent <code>m</code> of
556         * <code>F<sub>2<sup>m</sup></sub></code>.
557         * @param k The integer <code>k</code> where <code>x<sup>m</sup> +
558         * x<sup>k</sup> + 1</code> represents the reduction
559         * polynomial <code>f(z)</code>.
560         * @param a The coefficient <code>a</code> in the Weierstrass equation
561         * for non-supersingular elliptic curves over
562         * <code>F<sub>2<sup>m</sup></sub></code>.
563         * @param b The coefficient <code>b</code> in the Weierstrass equation
564         * for non-supersingular elliptic curves over
565         * <code>F<sub>2<sup>m</sup></sub></code>.
566         * @param n The order of the main subgroup of the elliptic curve.
567         * @param h The cofactor of the elliptic curve, i.e.
568         * <code>#E<sub>a</sub>(F<sub>2<sup>m</sup></sub>) = h * n</code>.
569         */
570        public F2m(
571            int m,
572            int k,
573            BigInteger a,
574            BigInteger b,
575            BigInteger n,
576            BigInteger h)
577        {
578            this(m, k, 0, 0, a, b, n, h);
579        }
580
581        /**
582         * Constructor for Pentanomial Polynomial Basis (PPB).
583         * @param m  The exponent <code>m</code> of
584         * <code>F<sub>2<sup>m</sup></sub></code>.
585         * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
586         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
587         * represents the reduction polynomial <code>f(z)</code>.
588         * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
589         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
590         * represents the reduction polynomial <code>f(z)</code>.
591         * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
592         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
593         * represents the reduction polynomial <code>f(z)</code>.
594         * @param a The coefficient <code>a</code> in the Weierstrass equation
595         * for non-supersingular elliptic curves over
596         * <code>F<sub>2<sup>m</sup></sub></code>.
597         * @param b The coefficient <code>b</code> in the Weierstrass equation
598         * for non-supersingular elliptic curves over
599         * <code>F<sub>2<sup>m</sup></sub></code>.
600         */
601        public F2m(
602            int m,
603            int k1,
604            int k2,
605            int k3,
606            BigInteger a,
607            BigInteger b)
608        {
609            this(m, k1, k2, k3, a, b, null, null);
610        }
611
612        /**
613         * Constructor for Pentanomial Polynomial Basis (PPB).
614         * @param m  The exponent <code>m</code> of
615         * <code>F<sub>2<sup>m</sup></sub></code>.
616         * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
617         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
618         * represents the reduction polynomial <code>f(z)</code>.
619         * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
620         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
621         * represents the reduction polynomial <code>f(z)</code>.
622         * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
623         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
624         * represents the reduction polynomial <code>f(z)</code>.
625         * @param a The coefficient <code>a</code> in the Weierstrass equation
626         * for non-supersingular elliptic curves over
627         * <code>F<sub>2<sup>m</sup></sub></code>.
628         * @param b The coefficient <code>b</code> in the Weierstrass equation
629         * for non-supersingular elliptic curves over
630         * <code>F<sub>2<sup>m</sup></sub></code>.
631         * @param n The order of the main subgroup of the elliptic curve.
632         * @param h The cofactor of the elliptic curve, i.e.
633         * <code>#E<sub>a</sub>(F<sub>2<sup>m</sup></sub>) = h * n</code>.
634         */
635        public F2m(
636            int m,
637            int k1,
638            int k2,
639            int k3,
640            BigInteger a,
641            BigInteger b,
642            BigInteger n,
643            BigInteger h)
644        {
645            this.m = m;
646            this.k1 = k1;
647            this.k2 = k2;
648            this.k3 = k3;
649            this.n = n;
650            this.h = h;
651
652            if (k1 == 0)
653            {
654                throw new IllegalArgumentException("k1 must be > 0");
655            }
656
657            if (k2 == 0)
658            {
659                if (k3 != 0)
660                {
661                    throw new IllegalArgumentException("k3 must be 0 if k2 == 0");
662                }
663            }
664            else
665            {
666                if (k2 <= k1)
667                {
668                    throw new IllegalArgumentException("k2 must be > k1");
669                }
670
671                if (k3 <= k2)
672                {
673                    throw new IllegalArgumentException("k3 must be > k2");
674                }
675            }
676
677            this.infinity = new ECPoint.F2m(this, null, null);
678            this.a = fromBigInteger(a);
679            this.b = fromBigInteger(b);
680            this.coord = F2M_DEFAULT_COORDS;
681        }
682
683        protected F2m(int m, int k1, int k2, int k3, ECFieldElement a, ECFieldElement b, BigInteger n, BigInteger h)
684        {
685            this.m = m;
686            this.k1 = k1;
687            this.k2 = k2;
688            this.k3 = k3;
689            this.n = n;
690            this.h = h;
691
692            this.infinity = new ECPoint.F2m(this, null, null);
693            this.a = a;
694            this.b = b;
695            this.coord = F2M_DEFAULT_COORDS;
696        }
697
698        protected ECCurve cloneCurve()
699        {
700            return new F2m(m, k1, k2, k3, a, b, n, h);
701        }
702
703        public boolean supportsCoordinateSystem(int coord)
704        {
705            switch (coord)
706            {
707            case COORD_AFFINE:
708            case COORD_HOMOGENEOUS:
709            case COORD_LAMBDA_PROJECTIVE:
710                return true;
711            default:
712                return false;
713            }
714        }
715
716        protected ECMultiplier createDefaultMultiplier()
717        {
718            if (isKoblitz())
719            {
720                return new WTauNafMultiplier();
721            }
722
723            return super.createDefaultMultiplier();
724        }
725
726        public int getFieldSize()
727        {
728            return m;
729        }
730
731        public ECFieldElement fromBigInteger(BigInteger x)
732        {
733            return new ECFieldElement.F2m(this.m, this.k1, this.k2, this.k3, x);
734        }
735
736        public ECPoint createPoint(BigInteger x, BigInteger y, boolean withCompression)
737        {
738            ECFieldElement X = fromBigInteger(x), Y = fromBigInteger(y);
739
740            switch (this.getCoordinateSystem())
741            {
742            case COORD_LAMBDA_AFFINE:
743            case COORD_LAMBDA_PROJECTIVE:
744            {
745                if (!X.isZero())
746                {
747                    // Y becomes Lambda (X + Y/X) here
748                    Y = Y.divide(X).add(X);
749                }
750                break;
751            }
752            default:
753            {
754                break;
755            }
756            }
757
758            return createRawPoint(X, Y, withCompression);
759        }
760
761        protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)
762        {
763            return new ECPoint.F2m(this, x, y, withCompression);
764        }
765
766        public ECPoint getInfinity()
767        {
768            return infinity;
769        }
770
771        /**
772         * Returns true if this is a Koblitz curve (ABC curve).
773         * @return true if this is a Koblitz curve (ABC curve), false otherwise
774         */
775        public boolean isKoblitz()
776        {
777            return n != null && h != null && a.bitLength() <= 1 && b.bitLength() == 1;
778        }
779
780        /**
781         * Returns the parameter <code>&mu;</code> of the elliptic curve.
782         * @return <code>&mu;</code> of the elliptic curve.
783         * @throws IllegalArgumentException if the given ECCurve is not a
784         * Koblitz curve.
785         */
786        synchronized byte getMu()
787        {
788            if (mu == 0)
789            {
790                mu = Tnaf.getMu(this);
791            }
792            return mu;
793        }
794
795        /**
796         * @return the auxiliary values <code>s<sub>0</sub></code> and
797         * <code>s<sub>1</sub></code> used for partial modular reduction for
798         * Koblitz curves.
799         */
800        synchronized BigInteger[] getSi()
801        {
802            if (si == null)
803            {
804                si = Tnaf.getSi(this);
805            }
806            return si;
807        }
808
809        /**
810         * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
811         *
812         * @param yTilde
813         *            ~yp, an indication bit for the decompression of yp.
814         * @param X1
815         *            The field element xp.
816         * @return the decompressed point.
817         */
818        protected ECPoint decompressPoint(int yTilde, BigInteger X1)
819        {
820            ECFieldElement xp = fromBigInteger(X1);
821            ECFieldElement yp = null;
822            if (xp.isZero())
823            {
824                yp = (ECFieldElement.F2m)b;
825                for (int i = 0; i < m - 1; i++)
826                {
827                    yp = yp.square();
828                }
829            }
830            else
831            {
832                ECFieldElement beta = xp.add(a).add(b.multiply(xp.square().invert()));
833                ECFieldElement z = solveQuadraticEquation(beta);
834                if (z == null)
835                {
836                    throw new IllegalArgumentException("Invalid point compression");
837                }
838                if (z.testBitZero() != (yTilde == 1))
839                {
840                    z = z.addOne();
841                }
842
843                yp = xp.multiply(z);
844
845                switch (this.getCoordinateSystem())
846                {
847                case COORD_LAMBDA_AFFINE:
848                case COORD_LAMBDA_PROJECTIVE:
849                {
850                    yp = yp.divide(xp).add(xp);
851                    break;
852                }
853                default:
854                {
855                    break;
856                }
857                }
858            }
859
860            return new ECPoint.F2m(this, xp, yp, true);
861        }
862
863        /**
864         * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
865         * D.1.6) The other solution is <code>z + 1</code>.
866         *
867         * @param beta
868         *            The value to solve the quadratic equation for.
869         * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
870         *         <code>null</code> if no solution exists.
871         */
872        private ECFieldElement solveQuadraticEquation(ECFieldElement beta)
873        {
874            if (beta.isZero())
875            {
876                return beta;
877            }
878
879            ECFieldElement zeroElement = fromBigInteger(ECConstants.ZERO);
880
881            ECFieldElement z = null;
882            ECFieldElement gamma = null;
883
884            Random rand = new Random();
885            do
886            {
887                ECFieldElement t = fromBigInteger(new BigInteger(m, rand));
888                z = zeroElement;
889                ECFieldElement w = beta;
890                for (int i = 1; i <= m - 1; i++)
891                {
892                    ECFieldElement w2 = w.square();
893                    z = z.square().add(w2.multiply(t));
894                    w = w2.add(beta);
895                }
896                if (!w.isZero())
897                {
898                    return null;
899                }
900                gamma = z.square().add(z);
901            }
902            while (gamma.isZero());
903
904            return z;
905        }
906
907        public boolean equals(
908            Object anObject)
909        {
910            if (anObject == this)
911            {
912                return true;
913            }
914
915            if (!(anObject instanceof ECCurve.F2m))
916            {
917                return false;
918            }
919
920            ECCurve.F2m other = (ECCurve.F2m)anObject;
921
922            return (this.m == other.m) && (this.k1 == other.k1)
923                && (this.k2 == other.k2) && (this.k3 == other.k3)
924                && a.equals(other.a) && b.equals(other.b);
925        }
926
927        public int hashCode()
928        {
929            return this.a.hashCode() ^ this.b.hashCode() ^ m ^ k1 ^ k2 ^ k3;
930        }
931
932        public int getM()
933        {
934            return m;
935        }
936
937        /**
938         * Return true if curve uses a Trinomial basis.
939         *
940         * @return true if curve Trinomial, false otherwise.
941         */
942        public boolean isTrinomial()
943        {
944            return k2 == 0 && k3 == 0;
945        }
946
947        public int getK1()
948        {
949            return k1;
950        }
951
952        public int getK2()
953        {
954            return k2;
955        }
956
957        public int getK3()
958        {
959            return k3;
960        }
961
962        public BigInteger getN()
963        {
964            return n;
965        }
966
967        public BigInteger getH()
968        {
969            return h;
970        }
971    }
972}
973