18212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrompackage org.bouncycastle.math.ec;
28212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
38212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport java.math.BigInteger;
48212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
58212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport org.bouncycastle.asn1.x9.X9IntegerConverter;
68212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
78212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom/**
88212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * base class for points on elliptic curves.
98212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */
108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrompublic abstract class ECPoint
118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom{
128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    ECCurve        curve;
138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    ECFieldElement x;
148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    ECFieldElement y;
158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    protected boolean withCompression;
178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    protected ECMultiplier multiplier = null;
198212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    protected PreCompInfo preCompInfo = null;
218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    private static X9IntegerConverter converter = new X9IntegerConverter();
238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    protected ECPoint(ECCurve curve, ECFieldElement x, ECFieldElement y)
258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        this.curve = curve;
278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        this.x = x;
288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        this.y = y;
298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public ECCurve getCurve()
328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return curve;
348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
368212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public ECFieldElement getX()
378212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
388212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return x;
398212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
408212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public ECFieldElement getY()
428212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
438212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return y;
448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
458212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
468212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public boolean isInfinity()
478212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return x == null && y == null;
498212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
508212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public boolean isCompressed()
528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
538212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return withCompression;
548212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
558212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
568212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public boolean equals(
578212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        Object  other)
588212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
598212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (other == this)
608212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return true;
628212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
638212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
648212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (!(other instanceof ECPoint))
658212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
668212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return false;
678212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
688212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
698212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        ECPoint o = (ECPoint)other;
708212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
718212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (this.isInfinity())
728212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
738212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return o.isInfinity();
748212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
758212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
768212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return x.equals(o.x) && y.equals(o.y);
778212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
788212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
798212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public int hashCode()
808212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
818212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (this.isInfinity())
828212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
838212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return 0;
848212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
858212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
868212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return x.hashCode() ^ y.hashCode();
878212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
888212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
898212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom//    /**
908212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom//     * Mainly for testing. Explicitly set the <code>ECMultiplier</code>.
918212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom//     * @param multiplier The <code>ECMultiplier</code> to be used to multiply
928212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom//     * this <code>ECPoint</code>.
938212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom//     */
948212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom//    public void setECMultiplier(ECMultiplier multiplier)
958212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom//    {
968212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom//        this.multiplier = multiplier;
978212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom//    }
988212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
998212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    /**
1008212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * Sets the <code>PreCompInfo</code>. Used by <code>ECMultiplier</code>s
1018212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * to save the precomputation for this <code>ECPoint</code> to store the
1028212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * precomputation result for use by subsequent multiplication.
1038212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param preCompInfo The values precomputed by the
1048212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * <code>ECMultiplier</code>.
1058212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     */
1068212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    void setPreCompInfo(PreCompInfo preCompInfo)
1078212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
1088212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        this.preCompInfo = preCompInfo;
1098212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
1108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public abstract byte[] getEncoded();
1128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public abstract ECPoint add(ECPoint b);
1148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public abstract ECPoint subtract(ECPoint b);
1158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public abstract ECPoint negate();
1168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public abstract ECPoint twice();
1178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    /**
1198212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * Sets the default <code>ECMultiplier</code>, unless already set.
1208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     */
1218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    synchronized void assertECMultiplier()
1228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
1238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (this.multiplier == null)
1248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
1258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            this.multiplier = new FpNafMultiplier();
1268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
1278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
1288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    /**
1308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * Multiplies this <code>ECPoint</code> by the given number.
1318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param k The multiplicator.
1328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @return <code>k * this</code>.
1338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     */
1348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public ECPoint multiply(BigInteger k)
1358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
1366e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        if (k.signum() < 0)
1376e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
1386e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            throw new IllegalArgumentException("The multiplicator cannot be negative");
1396e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
1406e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
1418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (this.isInfinity())
1428212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
1438212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return this;
1448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
1458212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1468212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (k.signum() == 0)
1478212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
1488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return this.curve.getInfinity();
1498212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
1508212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        assertECMultiplier();
1528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return this.multiplier.multiply(this, k, preCompInfo);
1538212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
1548212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1558212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    /**
1568212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * Elliptic curve points over Fp
1578212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     */
1588212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public static class Fp extends ECPoint
1598212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
1608212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        /**
1628212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * Create a point which encodes with point compression.
1638212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         *
1648212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param curve the curve to use
1658212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param x affine x co-ordinate
1668212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param y affine y co-ordinate
1678212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         */
1688212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public Fp(ECCurve curve, ECFieldElement x, ECFieldElement y)
1698212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
1708212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            this(curve, x, y, false);
1718212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
1728212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1738212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        /**
1748212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * Create a point that encodes with or without point compresion.
1758212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         *
1768212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param curve the curve to use
1778212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param x affine x co-ordinate
1788212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param y affine y co-ordinate
1798212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param withCompression if true encode with point compression
1808212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         */
1818212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public Fp(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
1828212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
1838212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            super(curve, x, y);
1848212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1858212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if ((x != null && y == null) || (x == null && y != null))
1868212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
1878212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                throw new IllegalArgumentException("Exactly one of the field elements is null");
1888212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
1898212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1908212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            this.withCompression = withCompression;
1918212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
1928212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1938212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        /**
1948212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * return the field element encoded with point compression. (S 4.3.6)
1958212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         */
1968212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public byte[] getEncoded()
1978212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
1988212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (this.isInfinity())
1998212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
2008212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                return new byte[1];
2018212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
2028212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2038212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            int qLength = converter.getByteLength(x);
2048212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2058212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (withCompression)
2068212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
2078212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                byte    PC;
2088212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2098212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                if (this.getY().toBigInteger().testBit(0))
2108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                {
2118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    PC = 0x03;
2128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                }
2138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                else
2148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                {
2158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    PC = 0x02;
2168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                }
2178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                byte[]  X = converter.integerToBytes(this.getX().toBigInteger(), qLength);
2198212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                byte[]  PO = new byte[X.length + 1];
2208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                PO[0] = PC;
2228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                System.arraycopy(X, 0, PO, 1, X.length);
2238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                return PO;
2258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
2268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            else
2278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
2288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                byte[]  X = converter.integerToBytes(this.getX().toBigInteger(), qLength);
2298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                byte[]  Y = converter.integerToBytes(this.getY().toBigInteger(), qLength);
2308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                byte[]  PO = new byte[X.length + Y.length + 1];
2318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                PO[0] = 0x04;
2338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                System.arraycopy(X, 0, PO, 1, X.length);
2348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                System.arraycopy(Y, 0, PO, X.length + 1, Y.length);
2358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2368212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                return PO;
2378212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
2388212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
2398212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2408212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // B.3 pg 62
2418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public ECPoint add(ECPoint b)
2428212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
2438212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (this.isInfinity())
2448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
2458212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                return b;
2468212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
2478212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (b.isInfinity())
2498212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
2508212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                return this;
2518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
2528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2538212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            // Check if b = this or b = -this
2548212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (this.x.equals(b.x))
2558212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
2568212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                if (this.y.equals(b.y))
2578212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                {
2588212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    // this = b, i.e. this must be doubled
2598212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    return this.twice();
2608212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                }
2618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2628212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                // this = -b, i.e. the result is the point at infinity
2638212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                return this.curve.getInfinity();
2648212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
2658212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2668212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            ECFieldElement gamma = b.y.subtract(this.y).divide(b.x.subtract(this.x));
2678212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2688212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            ECFieldElement x3 = gamma.square().subtract(this.x).subtract(b.x);
2698212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            ECFieldElement y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y);
2708212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2718212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return new ECPoint.Fp(curve, x3, y3);
2728212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
2738212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2748212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // B.3 pg 62
2758212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public ECPoint twice()
2768212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
2778212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (this.isInfinity())
2788212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
2798212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                // Twice identity element (point at infinity) is identity
2808212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                return this;
2818212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
2828212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2838212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (this.y.toBigInteger().signum() == 0)
2848212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
2858212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                // if y1 == 0, then (x1, y1) == (x1, -y1)
2868212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                // and hence this = -this and thus 2(x1, y1) == infinity
2878212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                return this.curve.getInfinity();
2888212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
2898212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2908212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            ECFieldElement TWO = this.curve.fromBigInteger(BigInteger.valueOf(2));
2918212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            ECFieldElement THREE = this.curve.fromBigInteger(BigInteger.valueOf(3));
2928212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            ECFieldElement gamma = this.x.square().multiply(THREE).add(curve.a).divide(y.multiply(TWO));
2938212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2948212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            ECFieldElement x3 = gamma.square().subtract(this.x.multiply(TWO));
2958212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            ECFieldElement y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y);
2968212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2978212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return new ECPoint.Fp(curve, x3, y3, this.withCompression);
2988212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
2998212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3008212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // D.3.2 pg 102 (see Note:)
3018212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public ECPoint subtract(ECPoint b)
3028212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
3038212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (b.isInfinity())
3048212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
3058212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                return this;
3068212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
3078212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3088212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            // Add -b
3098212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return add(b.negate());
3108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
3118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public ECPoint negate()
3138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
3148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return new ECPoint.Fp(curve, this.x, this.y.negate(), this.withCompression);
3158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
3168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3176e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        /**
3186e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom         * Sets the default <code>ECMultiplier</code>, unless already set.
3196e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom         */
3206e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        synchronized void assertECMultiplier()
3216e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
3226e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            if (this.multiplier == null)
3236e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            {
3246e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                this.multiplier = new WNafMultiplier();
3256e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            }
3266e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
3278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
3288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    /**
3308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * Elliptic curve points over F2m
3318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     */
3328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public static class F2m extends ECPoint
3338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
3348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        /**
3358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param curve base curve
3368212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param x x point
3378212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param y y point
3388212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         */
3398212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public F2m(ECCurve curve, ECFieldElement x, ECFieldElement y)
3408212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
3418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            this(curve, x, y, false);
3428212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
3438212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        /**
3458212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param curve base curve
3468212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param x x point
3478212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param y y point
3488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param withCompression true if encode with point compression.
3498212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         */
3508212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public F2m(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
3518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
3528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            super(curve, x, y);
3538212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3548212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if ((x != null && y == null) || (x == null && y != null))
3558212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
3568212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                throw new IllegalArgumentException("Exactly one of the field elements is null");
3578212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
3588212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3598212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (x != null)
3608212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
3618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                // Check if x and y are elements of the same field
3628212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                ECFieldElement.F2m.checkFieldElements(this.x, this.y);
3638212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3648212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                // Check if x and a are elements of the same field
3658212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                if (curve != null)
3668212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                {
3678212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    ECFieldElement.F2m.checkFieldElements(this.x, this.curve.getA());
3688212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                }
3698212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
3708212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3718212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            this.withCompression = withCompression;
3728212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
3738212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3748212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        /* (non-Javadoc)
3758212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @see org.bouncycastle.math.ec.ECPoint#getEncoded()
3768212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         */
3778212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public byte[] getEncoded()
3788212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
3798212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (this.isInfinity())
3808212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
3818212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                return new byte[1];
3828212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
3838212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3848212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            int byteCount = converter.getByteLength(this.x);
3858212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            byte[] X = converter.integerToBytes(this.getX().toBigInteger(), byteCount);
3868212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            byte[] PO;
3878212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3888212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (withCompression)
3898212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
3908212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                // See X9.62 4.3.6 and 4.2.2
3918212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                PO = new byte[byteCount + 1];
3928212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3938212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                PO[0] = 0x02;
3948212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                // X9.62 4.2.2 and 4.3.6:
3958212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                // if x = 0 then ypTilde := 0, else ypTilde is the rightmost
3968212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                // bit of y * x^(-1)
3978212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                // if ypTilde = 0, then PC := 02, else PC := 03
3988212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                // Note: PC === PO[0]
3998212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                if (!(this.getX().toBigInteger().equals(ECConstants.ZERO)))
4008212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                {
4018212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    if (this.getY().multiply(this.getX().invert())
4028212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                            .toBigInteger().testBit(0))
4038212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    {
4048212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                        // ypTilde = 1, hence PC = 03
4058212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                        PO[0] = 0x03;
4068212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    }
4078212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                }
4088212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4098212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                System.arraycopy(X, 0, PO, 1, byteCount);
4108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
4118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            else
4128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
4138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                byte[] Y = converter.integerToBytes(this.getY().toBigInteger(), byteCount);
4148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                PO = new byte[byteCount + byteCount + 1];
4168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                PO[0] = 0x04;
4188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                System.arraycopy(X, 0, PO, 1, byteCount);
4198212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                System.arraycopy(Y, 0, PO, byteCount + 1, byteCount);
4208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
4218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return PO;
4238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
4248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        /**
4268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * Check, if two <code>ECPoint</code>s can be added or subtracted.
4278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param a The first <code>ECPoint</code> to check.
4288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param b The second <code>ECPoint</code> to check.
4298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @throws IllegalArgumentException if <code>a</code> and <code>b</code>
4308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * cannot be added.
4318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         */
4328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        private static void checkPoints(ECPoint a, ECPoint b)
4338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
4348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            // Check, if points are on the same curve
4358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (!(a.curve.equals(b.curve)))
4368212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
4378212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                throw new IllegalArgumentException("Only points on the same "
4388212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                        + "curve can be added or subtracted");
4398212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
4408212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom//            ECFieldElement.F2m.checkFieldElements(a.x, b.x);
4428212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
4438212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        /* (non-Javadoc)
4458212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @see org.bouncycastle.math.ec.ECPoint#add(org.bouncycastle.math.ec.ECPoint)
4468212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         */
4478212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public ECPoint add(ECPoint b)
4488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
4498212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            checkPoints(this, b);
4508212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return addSimple((ECPoint.F2m)b);
4518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
4528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4538212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        /**
4548212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * Adds another <code>ECPoints.F2m</code> to <code>this</code> without
4558212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * checking if both points are on the same curve. Used by multiplication
4568212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * algorithms, because there all points are a multiple of the same point
4578212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * and hence the checks can be omitted.
4588212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param b The other <code>ECPoints.F2m</code> to add to
4598212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * <code>this</code>.
4608212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @return <code>this + b</code>
4618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         */
4628212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public ECPoint.F2m addSimple(ECPoint.F2m b)
4638212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
4648212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            ECPoint.F2m other = b;
4658212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (this.isInfinity())
4668212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
4678212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                return other;
4688212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
4698212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4708212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (other.isInfinity())
4718212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
4728212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                return this;
4738212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
4748212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4758212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            ECFieldElement.F2m x2 = (ECFieldElement.F2m)other.getX();
4768212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            ECFieldElement.F2m y2 = (ECFieldElement.F2m)other.getY();
4778212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4788212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            // Check if other = this or other = -this
4798212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (this.x.equals(x2))
4808212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
4818212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                if (this.y.equals(y2))
4828212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                {
4838212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    // this = other, i.e. this must be doubled
4848212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    return (ECPoint.F2m)this.twice();
4858212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                }
4868212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4878212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                // this = -other, i.e. the result is the point at infinity
4888212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                return (ECPoint.F2m)this.curve.getInfinity();
4898212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
4908212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4918212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            ECFieldElement.F2m lambda
4928212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                = (ECFieldElement.F2m)(this.y.add(y2)).divide(this.x.add(x2));
4938212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4948212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            ECFieldElement.F2m x3
4958212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                = (ECFieldElement.F2m)lambda.square().add(lambda).add(this.x).add(x2).add(this.curve.getA());
4968212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4978212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            ECFieldElement.F2m y3
4988212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                = (ECFieldElement.F2m)lambda.multiply(this.x.add(x3)).add(x3).add(this.y);
4998212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
5008212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return new ECPoint.F2m(curve, x3, y3, withCompression);
5018212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
5028212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
5038212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        /* (non-Javadoc)
5048212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @see org.bouncycastle.math.ec.ECPoint#subtract(org.bouncycastle.math.ec.ECPoint)
5058212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         */
5068212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public ECPoint subtract(ECPoint b)
5078212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
5088212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            checkPoints(this, b);
5098212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return subtractSimple((ECPoint.F2m)b);
5108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
5118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
5128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        /**
5138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * Subtracts another <code>ECPoints.F2m</code> from <code>this</code>
5148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * without checking if both points are on the same curve. Used by
5158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * multiplication algorithms, because there all points are a multiple
5168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * of the same point and hence the checks can be omitted.
5178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @param b The other <code>ECPoints.F2m</code> to subtract from
5188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * <code>this</code>.
5198212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @return <code>this - b</code>
5208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         */
5218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public ECPoint.F2m subtractSimple(ECPoint.F2m b)
5228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
5238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (b.isInfinity())
5248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
5258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                return this;
5268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
5278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
5288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            // Add -b
5298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return addSimple((ECPoint.F2m)b.negate());
5308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
5318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
5328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        /* (non-Javadoc)
5338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         * @see org.bouncycastle.math.ec.ECPoint#twice()
5348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom         */
5358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public ECPoint twice()
5368212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
5378212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (this.isInfinity())
5388212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
5398212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                // Twice identity element (point at infinity) is identity
5408212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                return this;
5418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
5428212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
5438212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (this.x.toBigInteger().signum() == 0)
5448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
5458212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                // if x1 == 0, then (x1, y1) == (x1, x1 + y1)
5468212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                // and hence this = -this and thus 2(x1, y1) == infinity
5478212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                return this.curve.getInfinity();
5488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
5498212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
5508212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            ECFieldElement.F2m lambda
5518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                = (ECFieldElement.F2m)this.x.add(this.y.divide(this.x));
5528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
5538212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            ECFieldElement.F2m x3
5548212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                = (ECFieldElement.F2m)lambda.square().add(lambda).
5558212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    add(this.curve.getA());
5568212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
5578212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            ECFieldElement ONE = this.curve.fromBigInteger(ECConstants.ONE);
5588212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            ECFieldElement.F2m y3
5598212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                = (ECFieldElement.F2m)this.x.square().add(
5608212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    x3.multiply(lambda.add(ONE)));
5618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
5628212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return new ECPoint.F2m(this.curve, x3, y3, withCompression);
5638212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
5648212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
5658212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        public ECPoint negate()
5668212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
5678212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return new ECPoint.F2m(curve, this.getX(), this.getY().add(this.getX()), withCompression);
5688212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
5698212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
5706e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        /**
5716e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom         * Sets the appropriate <code>ECMultiplier</code>, unless already set.
5726e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom         */
5736e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        synchronized void assertECMultiplier()
5746e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
5756e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            if (this.multiplier == null)
5766e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            {
5776e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                if (((ECCurve.F2m)this.curve).isKoblitz())
5786e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                {
5796e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                    this.multiplier = new WTauNafMultiplier();
5806e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                }
5816e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                else
5826e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                {
5836e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                    this.multiplier = new WNafMultiplier();
5846e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                }
5856e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            }
5866e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
5878212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
5888212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom}
589