18212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrompackage org.bouncycastle.math.ec;
28212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
38212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport java.math.BigInteger;
48212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport java.util.Random;
58212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
68212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom/**
78212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * base class for an elliptic curve
88212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */
98212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrompublic abstract class ECCurve
108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom{
118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    ECFieldElement a, b;
128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public abstract int getFieldSize();
148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public abstract ECFieldElement fromBigInteger(BigInteger x);
168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public abstract ECPoint createPoint(BigInteger x, BigInteger y, boolean withCompression);
188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
198212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public abstract ECPoint decodePoint(byte[] encoded);
208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public abstract ECPoint getInfinity();
228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public ECFieldElement getA()
248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return a;
268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public ECFieldElement getB()
298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return b;
318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    /**
348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * Elliptic curve over Fp
358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     */
368212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public static class Fp extends ECCurve
378212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
388212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger q;
398212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        ECPoint.Fp infinity;
408212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public Fp(BigInteger q, BigInteger a, BigInteger b)
428212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
438212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            this.q = q;
448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            this.a = fromBigInteger(a);
458212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            this.b = fromBigInteger(b);
468212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            this.infinity = new ECPoint.Fp(this, null, null);
478212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
498212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public BigInteger getQ()
508212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return q;
528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
538212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
548212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public int getFieldSize()
558212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
568212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return q.bitLength();
578212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
588212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
598212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public ECFieldElement fromBigInteger(BigInteger x)
608212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return new ECFieldElement.Fp(this.q, x);
628212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
638212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
648212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public ECPoint createPoint(BigInteger x, BigInteger y, boolean withCompression)
658212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
668212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return new ECPoint.Fp(this, fromBigInteger(x), fromBigInteger(y), withCompression);
678212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
688212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
698212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        /**
708212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * Decode a point on this curve from its ASN.1 encoding. The different
718212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * encodings are taken account of, including point compression for
728212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * <code>F<sub>p</sub></code> (X9.62 s 4.2.1 pg 17).
738212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @return The decoded point.
748212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         */
758212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public ECPoint decodePoint(byte[] encoded)
768212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
778212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            ECPoint p = null;
788212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
798212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            switch (encoded[0])
808212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
818212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                // infinity
828212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            case 0x00:
836e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                if (encoded.length > 1)
846e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                {
856e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                    throw new RuntimeException("Invalid point encoding");
866e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                }
878212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                p = getInfinity();
888212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                break;
898212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                // compressed
908212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            case 0x02:
918212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            case 0x03:
928212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                int ytilde = encoded[0] & 1;
938212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                byte[]  i = new byte[encoded.length - 1];
948212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
958212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                System.arraycopy(encoded, 1, i, 0, i.length);
968212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
978212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                ECFieldElement x = new ECFieldElement.Fp(this.q, new BigInteger(1, i));
988212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                ECFieldElement alpha = x.multiply(x.square().add(a)).add(b);
998212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                ECFieldElement beta = alpha.sqrt();
1008212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1018212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                //
1028212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                // if we can't find a sqrt we haven't got a point on the
1038212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                // curve - run!
1048212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                //
1058212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                if (beta == null)
1068212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                {
1078212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    throw new RuntimeException("Invalid point compression");
1088212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                }
1098212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                int bit0 = (beta.toBigInteger().testBit(0) ? 1 : 0);
1118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                if (bit0 == ytilde)
1138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                {
1148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    p = new ECPoint.Fp(this, x, beta, true);
1158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                }
1168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                else
1178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                {
1188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    p = new ECPoint.Fp(this, x,
1198212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                        new ECFieldElement.Fp(this.q, q.subtract(beta.toBigInteger())), true);
1208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                }
1218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                break;
1228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                // uncompressed
1238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            case 0x04:
1248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                // hybrid
1258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            case 0x06:
1268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            case 0x07:
1278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                byte[]  xEnc = new byte[(encoded.length - 1) / 2];
1288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                byte[]  yEnc = new byte[(encoded.length - 1) / 2];
1298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                System.arraycopy(encoded, 1, xEnc, 0, xEnc.length);
1318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                System.arraycopy(encoded, xEnc.length + 1, yEnc, 0, yEnc.length);
1328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                p = new ECPoint.Fp(this,
1348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                        new ECFieldElement.Fp(this.q, new BigInteger(1, xEnc)),
1358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                        new ECFieldElement.Fp(this.q, new BigInteger(1, yEnc)));
1368212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                break;
1378212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            default:
1388212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                throw new RuntimeException("Invalid point encoding 0x" + Integer.toString(encoded[0], 16));
1398212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
1408212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return p;
1428212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
1438212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public ECPoint getInfinity()
1458212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
1468212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return infinity;
1478212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
1488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1498212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public boolean equals(
1508212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            Object anObject)
1518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
1528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (anObject == this)
1538212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
1548212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                return true;
1558212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
1568212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1578212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (!(anObject instanceof ECCurve.Fp))
1588212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
1598212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                return false;
1608212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
1618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1628212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            ECCurve.Fp other = (ECCurve.Fp) anObject;
1638212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1648212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return this.q.equals(other.q)
1658212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    && a.equals(other.a) && b.equals(other.b);
1668212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
1678212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1688212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public int hashCode()
1698212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
1708212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return a.hashCode() ^ b.hashCode() ^ q.hashCode();
1718212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
1728212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
1738212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1748212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    /**
1758212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * Elliptic curves over F2m. The Weierstrass equation is given by
1768212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * <code>y<sup>2</sup> + xy = x<sup>3</sup> + ax<sup>2</sup> + b</code>.
1778212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     */
1788212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public static class F2m extends ECCurve
1798212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
1808212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        /**
1818212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * The exponent <code>m</code> of <code>F<sub>2<sup>m</sup></sub></code>.
1828212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         */
1838212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        private int m;  // can't be final - JDK 1.1
1848212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1858212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        /**
1868212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * TPB: The integer <code>k</code> where <code>x<sup>m</sup> +
1878212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * x<sup>k</sup> + 1</code> represents the reduction polynomial
1888212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * <code>f(z)</code>.<br>
1898212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * PPB: The integer <code>k1</code> where <code>x<sup>m</sup> +
1908212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
1918212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * represents the reduction polynomial <code>f(z)</code>.<br>
1928212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         */
1938212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        private int k1;  // can't be final - JDK 1.1
1948212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1958212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        /**
1968212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * TPB: Always set to <code>0</code><br>
1978212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * PPB: The integer <code>k2</code> where <code>x<sup>m</sup> +
1988212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
1998212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * represents the reduction polynomial <code>f(z)</code>.<br>
2008212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         */
2018212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        private int k2;  // can't be final - JDK 1.1
2028212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2038212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        /**
2048212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * TPB: Always set to <code>0</code><br>
2058212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * PPB: The integer <code>k3</code> where <code>x<sup>m</sup> +
2068212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
2078212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * represents the reduction polynomial <code>f(z)</code>.<br>
2088212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         */
2098212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        private int k3;  // can't be final - JDK 1.1
2108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        /**
2128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * The order of the base point of the curve.
2138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         */
2148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        private BigInteger n;  // can't be final - JDK 1.1
2158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        /**
2178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * The cofactor of the curve.
2188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         */
2198212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        private BigInteger h;  // can't be final - JDK 1.1
2208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         /**
2228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * The point at infinity on this curve.
2238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         */
2248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        private ECPoint.F2m infinity;  // can't be final - JDK 1.1
2258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        /**
2278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * The parameter <code>&mu;</code> of the elliptic curve if this is
2288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * a Koblitz curve.
2298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         */
2308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        private byte mu = 0;
2318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        /**
2338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * The auxiliary values <code>s<sub>0</sub></code> and
2348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * <code>s<sub>1</sub></code> used for partial modular reduction for
2358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * Koblitz curves.
2368212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         */
2378212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        private BigInteger[] si = null;
2388212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2398212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        /**
2408212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * Constructor for Trinomial Polynomial Basis (TPB).
2418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param m  The exponent <code>m</code> of
2428212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * <code>F<sub>2<sup>m</sup></sub></code>.
2438212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param k The integer <code>k</code> where <code>x<sup>m</sup> +
2448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * x<sup>k</sup> + 1</code> represents the reduction
2458212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * polynomial <code>f(z)</code>.
2468212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param a The coefficient <code>a</code> in the Weierstrass equation
2478212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * for non-supersingular elliptic curves over
2488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * <code>F<sub>2<sup>m</sup></sub></code>.
2498212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param b The coefficient <code>b</code> in the Weierstrass equation
2508212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * for non-supersingular elliptic curves over
2518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * <code>F<sub>2<sup>m</sup></sub></code>.
2528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         */
2538212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public F2m(
2548212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            int m,
2558212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            int k,
2568212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            BigInteger a,
2578212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            BigInteger b)
2588212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
2598212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            this(m, k, 0, 0, a, b, null, null);
2608212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
2618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2628212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        /**
2638212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * Constructor for Trinomial Polynomial Basis (TPB).
2648212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param m  The exponent <code>m</code> of
2658212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * <code>F<sub>2<sup>m</sup></sub></code>.
2668212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param k The integer <code>k</code> where <code>x<sup>m</sup> +
2678212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * x<sup>k</sup> + 1</code> represents the reduction
2688212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * polynomial <code>f(z)</code>.
2698212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param a The coefficient <code>a</code> in the Weierstrass equation
2708212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * for non-supersingular elliptic curves over
2718212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * <code>F<sub>2<sup>m</sup></sub></code>.
2728212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param b The coefficient <code>b</code> in the Weierstrass equation
2738212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * for non-supersingular elliptic curves over
2748212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * <code>F<sub>2<sup>m</sup></sub></code>.
2758212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param n The order of the main subgroup of the elliptic curve.
2768212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param h The cofactor of the elliptic curve, i.e.
2778212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * <code>#E<sub>a</sub>(F<sub>2<sup>m</sup></sub>) = h * n</code>.
2788212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         */
2798212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public F2m(
2808212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            int m,
2818212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            int k,
2828212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            BigInteger a,
2838212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            BigInteger b,
2848212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            BigInteger n,
2858212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            BigInteger h)
2868212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
2878212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            this(m, k, 0, 0, a, b, n, h);
2888212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
2898212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2908212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        /**
2918212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * Constructor for Pentanomial Polynomial Basis (PPB).
2928212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param m  The exponent <code>m</code> of
2938212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * <code>F<sub>2<sup>m</sup></sub></code>.
2948212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
2958212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
2968212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * represents the reduction polynomial <code>f(z)</code>.
2978212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
2988212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
2998212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * represents the reduction polynomial <code>f(z)</code>.
3008212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
3018212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
3028212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * represents the reduction polynomial <code>f(z)</code>.
3038212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param a The coefficient <code>a</code> in the Weierstrass equation
3048212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * for non-supersingular elliptic curves over
3058212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * <code>F<sub>2<sup>m</sup></sub></code>.
3068212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param b The coefficient <code>b</code> in the Weierstrass equation
3078212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * for non-supersingular elliptic curves over
3088212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * <code>F<sub>2<sup>m</sup></sub></code>.
3098212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         */
3108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public F2m(
3118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            int m,
3128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            int k1,
3138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            int k2,
3148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            int k3,
3158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            BigInteger a,
3168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            BigInteger b)
3178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
3188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            this(m, k1, k2, k3, a, b, null, null);
3198212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
3208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        /**
3228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * Constructor for Pentanomial Polynomial Basis (PPB).
3238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param m  The exponent <code>m</code> of
3248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * <code>F<sub>2<sup>m</sup></sub></code>.
3258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
3268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
3278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * represents the reduction polynomial <code>f(z)</code>.
3288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
3298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
3308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * represents the reduction polynomial <code>f(z)</code>.
3318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
3328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
3338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * represents the reduction polynomial <code>f(z)</code>.
3348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param a The coefficient <code>a</code> in the Weierstrass equation
3358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * for non-supersingular elliptic curves over
3368212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * <code>F<sub>2<sup>m</sup></sub></code>.
3378212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param b The coefficient <code>b</code> in the Weierstrass equation
3388212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * for non-supersingular elliptic curves over
3398212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * <code>F<sub>2<sup>m</sup></sub></code>.
3408212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param n The order of the main subgroup of the elliptic curve.
3418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param h The cofactor of the elliptic curve, i.e.
3428212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * <code>#E<sub>a</sub>(F<sub>2<sup>m</sup></sub>) = h * n</code>.
3438212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         */
3448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public F2m(
3458212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            int m,
3468212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            int k1,
3478212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            int k2,
3488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            int k3,
3498212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            BigInteger a,
3508212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            BigInteger b,
3518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            BigInteger n,
3528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            BigInteger h)
3538212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
3548212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            this.m = m;
3558212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            this.k1 = k1;
3568212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            this.k2 = k2;
3578212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            this.k3 = k3;
3588212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            this.n = n;
3598212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            this.h = h;
3608212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (k1 == 0)
3628212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
3638212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                throw new IllegalArgumentException("k1 must be > 0");
3648212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
3658212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3668212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (k2 == 0)
3678212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
3688212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                if (k3 != 0)
3698212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                {
3708212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    throw new IllegalArgumentException("k3 must be 0 if k2 == 0");
3718212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                }
3728212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
3738212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            else
3748212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
3758212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                if (k2 <= k1)
3768212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                {
3778212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    throw new IllegalArgumentException("k2 must be > k1");
3788212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                }
3798212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3808212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                if (k3 <= k2)
3818212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                {
3828212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    throw new IllegalArgumentException("k3 must be > k2");
3838212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                }
3848212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
3858212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3868212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            this.a = fromBigInteger(a);
3878212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            this.b = fromBigInteger(b);
3888212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            this.infinity = new ECPoint.F2m(this, null, null);
3898212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
3908212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3918212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public int getFieldSize()
3928212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
3938212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return m;
3948212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
3958212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3968212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public ECFieldElement fromBigInteger(BigInteger x)
3978212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
3988212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return new ECFieldElement.F2m(this.m, this.k1, this.k2, this.k3, x);
3998212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
4008212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4018212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public ECPoint createPoint(BigInteger x, BigInteger y, boolean withCompression)
4028212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
4038212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return new ECPoint.F2m(this, fromBigInteger(x), fromBigInteger(y), withCompression);
4048212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
4058212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4068212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        /* (non-Javadoc)
4078212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @see org.bouncycastle.math.ec.ECCurve#decodePoint(byte[])
4088212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         */
4098212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public ECPoint decodePoint(byte[] encoded)
4108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
4118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            ECPoint p = null;
4128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            switch (encoded[0])
4148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
4158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                // infinity
4168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            case 0x00:
4176e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                if (encoded.length > 1)
4186e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                {
4196e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                    throw new RuntimeException("Invalid point encoding");
4206e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                }
4218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                p = getInfinity();
4228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                break;
4238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                // compressed
4248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            case 0x02:
4258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            case 0x03:
4268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                byte[] enc = new byte[encoded.length - 1];
4278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                System.arraycopy(encoded, 1, enc, 0, enc.length);
4288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                if (encoded[0] == 0x02)
4298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                {
4308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                        p = decompressPoint(enc, 0);
4318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                }
4328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                else
4338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                {
4348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                        p = decompressPoint(enc, 1);
4358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                }
4368212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                break;
4378212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                // uncompressed
4388212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            case 0x04:
4398212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                // hybrid
4408212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            case 0x06:
4418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            case 0x07:
4428212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                byte[] xEnc = new byte[(encoded.length - 1) / 2];
4438212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                byte[] yEnc = new byte[(encoded.length - 1) / 2];
4448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4458212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                System.arraycopy(encoded, 1, xEnc, 0, xEnc.length);
4468212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                System.arraycopy(encoded, xEnc.length + 1, yEnc, 0, yEnc.length);
4478212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                p = new ECPoint.F2m(this,
4498212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    new ECFieldElement.F2m(this.m, this.k1, this.k2, this.k3,
4508212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                        new BigInteger(1, xEnc)),
4518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    new ECFieldElement.F2m(this.m, this.k1, this.k2, this.k3,
4528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                        new BigInteger(1, yEnc)), false);
4538212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                break;
4548212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4558212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            default:
4568212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                throw new RuntimeException("Invalid point encoding 0x" + Integer.toString(encoded[0], 16));
4578212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
4588212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4598212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return p;
4608212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
4618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4628212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public ECPoint getInfinity()
4638212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
4648212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return infinity;
4658212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
4668212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4678212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        /**
4688212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * Returns true if this is a Koblitz curve (ABC curve).
4698212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @return true if this is a Koblitz curve (ABC curve), false otherwise
4708212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         */
4718212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public boolean isKoblitz()
4728212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
4738212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return ((n != null) && (h != null) &&
4748212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    ((a.toBigInteger().equals(ECConstants.ZERO)) ||
4758212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    (a.toBigInteger().equals(ECConstants.ONE))) &&
4768212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    (b.toBigInteger().equals(ECConstants.ONE)));
4778212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
4788212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4798212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        /**
4808212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * Returns the parameter <code>&mu;</code> of the elliptic curve.
4818212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @return <code>&mu;</code> of the elliptic curve.
4828212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @throws IllegalArgumentException if the given ECCurve is not a
4838212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * Koblitz curve.
4848212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         */
4858212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        synchronized byte getMu()
4868212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
4878212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (mu == 0)
4888212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
4898212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                mu = Tnaf.getMu(this);
4908212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
4918212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return mu;
4928212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
4938212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4948212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        /**
4958212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @return the auxiliary values <code>s<sub>0</sub></code> and
4968212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * <code>s<sub>1</sub></code> used for partial modular reduction for
4978212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * Koblitz curves.
4988212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         */
4998212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        synchronized BigInteger[] getSi()
5008212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
5018212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (si == null)
5028212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
5038212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                si = Tnaf.getSi(this);
5048212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
5058212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return si;
5068212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
5078212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
5088212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        /**
5098212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
5108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         *
5118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param xEnc
5128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         *            The encoding of field element xp.
5138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param ypBit
5148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         *            ~yp, an indication bit for the decompression of yp.
5158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @return the decompressed point.
5168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         */
5178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        private ECPoint decompressPoint(
5188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            byte[] xEnc,
5198212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            int ypBit)
5208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
5218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            ECFieldElement xp = new ECFieldElement.F2m(
5228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    this.m, this.k1, this.k2, this.k3, new BigInteger(1, xEnc));
5238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            ECFieldElement yp = null;
5248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (xp.toBigInteger().equals(ECConstants.ZERO))
5258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
5268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                yp = (ECFieldElement.F2m)b;
5278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                for (int i = 0; i < m - 1; i++)
5288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                {
5298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    yp = yp.square();
5308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                }
5318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
5328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            else
5338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
5348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                ECFieldElement beta = xp.add(a).add(
5358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                        b.multiply(xp.square().invert()));
5368212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                ECFieldElement z = solveQuadradicEquation(beta);
5378212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                if (z == null)
5388212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                {
5398212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    throw new RuntimeException("Invalid point compression");
5408212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                }
5418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                int zBit = 0;
5428212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                if (z.toBigInteger().testBit(0))
5438212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                {
5448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    zBit = 1;
5458212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                }
5468212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                if (zBit != ypBit)
5478212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                {
5488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    z = z.add(new ECFieldElement.F2m(this.m, this.k1, this.k2,
5498212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                            this.k3, ECConstants.ONE));
5508212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                }
5518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                yp = xp.multiply(z);
5528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
5538212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
5548212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return new ECPoint.F2m(this, xp, yp);
5558212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
5568212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
5578212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        /**
5588212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
5598212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * D.1.6) The other solution is <code>z + 1</code>.
5608212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         *
5618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param beta
5628212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         *            The value to solve the qradratic equation for.
5638212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
5648212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         *         <code>null</code> if no solution exists.
5658212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         */
5668212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        private ECFieldElement solveQuadradicEquation(ECFieldElement beta)
5678212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
5688212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            ECFieldElement zeroElement = new ECFieldElement.F2m(
5698212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    this.m, this.k1, this.k2, this.k3, ECConstants.ZERO);
5708212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
5718212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (beta.toBigInteger().equals(ECConstants.ZERO))
5728212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
5738212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                return zeroElement;
5748212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
5758212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
5768212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            ECFieldElement z = null;
5778212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            ECFieldElement gamma = zeroElement;
5788212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
5798212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            Random rand = new Random();
5808212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            do
5818212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
5828212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                ECFieldElement t = new ECFieldElement.F2m(this.m, this.k1,
5838212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                        this.k2, this.k3, new BigInteger(m, rand));
5848212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                z = zeroElement;
5858212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                ECFieldElement w = beta;
5868212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                for (int i = 1; i <= m - 1; i++)
5878212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                {
5888212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    ECFieldElement w2 = w.square();
5898212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    z = z.square().add(w2.multiply(t));
5908212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    w = w2.add(beta);
5918212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                }
5928212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                if (!w.toBigInteger().equals(ECConstants.ZERO))
5938212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                {
5948212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    return null;
5958212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                }
5968212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                gamma = z.square().add(z);
5978212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
5988212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            while (gamma.toBigInteger().equals(ECConstants.ZERO));
5998212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
6008212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return z;
6018212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
6028212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
6038212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public boolean equals(
6048212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            Object anObject)
6058212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
6068212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (anObject == this)
6078212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
6088212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                return true;
6098212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
6108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
6118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (!(anObject instanceof ECCurve.F2m))
6128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
6138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                return false;
6148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
6158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
6168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            ECCurve.F2m other = (ECCurve.F2m)anObject;
6178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
6188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return (this.m == other.m) && (this.k1 == other.k1)
6198212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                && (this.k2 == other.k2) && (this.k3 == other.k3)
6208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                && a.equals(other.a) && b.equals(other.b);
6218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
6228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
6238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public int hashCode()
6248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
6258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return this.a.hashCode() ^ this.b.hashCode() ^ m ^ k1 ^ k2 ^ k3;
6268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
6278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
6288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public int getM()
6298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
6308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return m;
6318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
6328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
6338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        /**
6348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * Return true if curve uses a Trinomial basis.
6358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         *
6368212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @return true if curve Trinomial, false otherwise.
6378212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         */
6388212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public boolean isTrinomial()
6398212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
6408212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return k2 == 0 && k3 == 0;
6418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
6428212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
6438212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public int getK1()
6448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
6458212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return k1;
6468212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
6478212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
6488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public int getK2()
6498212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
6508212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return k2;
6518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
6528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
6538212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public int getK3()
6548212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
6558212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return k3;
6568212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
6578212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
6588212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public BigInteger getN()
6598212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
6608212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return n;
6618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
6628212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
6638212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public BigInteger getH()
6648212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
6658212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return h;
6668212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
6678212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
6688212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom}
669