18212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrompackage org.bouncycastle.math.ec;
28212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
38212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport java.math.BigInteger;
48212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
58212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom/**
68212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * Class holding methods for point multiplication based on the window
78212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * τ-adic nonadjacent form (WTNAF). The algorithms are based on the
88212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * paper "Improved Algorithms for Arithmetic on Anomalous Binary Curves"
98212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * by Jerome A. Solinas. The paper first appeared in the Proceedings of
108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * Crypto 1997.
118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */
128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromclass Tnaf
138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom{
148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    private static final BigInteger MINUS_ONE = ECConstants.ONE.negate();
158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    private static final BigInteger MINUS_TWO = ECConstants.TWO.negate();
168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    private static final BigInteger MINUS_THREE = ECConstants.THREE.negate();
178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    /**
198212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * The window width of WTNAF. The standard value of 4 is slightly less
208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * than optimal for running time, but keeps space requirements for
218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * precomputation low. For typical curves, a value of 5 or 6 results in
228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * a better running time. When changing this value, the
238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * <code>&alpha;<sub>u</sub></code>'s must be computed differently, see
248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * e.g. "Guide to Elliptic Curve Cryptography", Darrel Hankerson,
258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * Alfred Menezes, Scott Vanstone, Springer-Verlag New York Inc., 2004,
268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * p. 121-122
278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     */
288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public static final byte WIDTH = 4;
298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    /**
318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * 2<sup>4</sup>
328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     */
338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public static final byte POW_2_WIDTH = 16;
348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    /**
368212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * The <code>&alpha;<sub>u</sub></code>'s for <code>a=0</code> as an array
378212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * of <code>ZTauElement</code>s.
388212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     */
398212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public static final ZTauElement[] alpha0 = {
408212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        null,
418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        new ZTauElement(ECConstants.ONE, ECConstants.ZERO), null,
428212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        new ZTauElement(MINUS_THREE, MINUS_ONE), null,
438212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        new ZTauElement(MINUS_ONE, MINUS_ONE), null,
448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        new ZTauElement(ECConstants.ONE, MINUS_ONE), null
458212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    };
468212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
478212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    /**
488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * The <code>&alpha;<sub>u</sub></code>'s for <code>a=0</code> as an array
498212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * of TNAFs.
508212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     */
518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public static final byte[][] alpha0Tnaf = {
528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        null, {1}, null, {-1, 0, 1}, null, {1, 0, 1}, null, {-1, 0, 0, 1}
538212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    };
548212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
558212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    /**
568212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * The <code>&alpha;<sub>u</sub></code>'s for <code>a=1</code> as an array
578212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * of <code>ZTauElement</code>s.
588212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     */
598212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public static final ZTauElement[] alpha1 = {null,
608212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        new ZTauElement(ECConstants.ONE, ECConstants.ZERO), null,
618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        new ZTauElement(MINUS_THREE, ECConstants.ONE), null,
628212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        new ZTauElement(MINUS_ONE, ECConstants.ONE), null,
638212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        new ZTauElement(ECConstants.ONE, ECConstants.ONE), null
648212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    };
658212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
668212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    /**
678212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * The <code>&alpha;<sub>u</sub></code>'s for <code>a=1</code> as an array
688212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * of TNAFs.
698212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     */
708212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public static final byte[][] alpha1Tnaf = {
718212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        null, {1}, null, {-1, 0, 1}, null, {1, 0, 1}, null, {-1, 0, 0, -1}
728212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    };
738212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
748212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    /**
758212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * Computes the norm of an element <code>&lambda;</code> of
768212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * <code><b>Z</b>[&tau;]</code>.
778212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param mu The parameter <code>&mu;</code> of the elliptic curve.
788212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param lambda The element <code>&lambda;</code> of
798212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * <code><b>Z</b>[&tau;]</code>.
808212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @return The norm of <code>&lambda;</code>.
818212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     */
828212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public static BigInteger norm(final byte mu, ZTauElement lambda)
838212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
848212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger norm;
858212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
868212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // s1 = u^2
878212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger s1 = lambda.u.multiply(lambda.u);
888212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
898212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // s2 = u * v
908212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger s2 = lambda.u.multiply(lambda.v);
918212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
928212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // s3 = 2 * v^2
938212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger s3 = lambda.v.multiply(lambda.v).shiftLeft(1);
948212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
958212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (mu == 1)
968212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
978212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            norm = s1.add(s2).add(s3);
988212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
998212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        else if (mu == -1)
1008212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
1018212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            norm = s1.subtract(s2).add(s3);
1028212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
1038212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        else
1048212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
1058212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            throw new IllegalArgumentException("mu must be 1 or -1");
1068212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
1078212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1088212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return norm;
1098212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
1108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    /**
1128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * Computes the norm of an element <code>&lambda;</code> of
1138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * <code><b>R</b>[&tau;]</code>, where <code>&lambda; = u + v&tau;</code>
1148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * and <code>u</code> and <code>u</code> are real numbers (elements of
1158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * <code><b>R</b></code>).
1168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param mu The parameter <code>&mu;</code> of the elliptic curve.
1178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param u The real part of the element <code>&lambda;</code> of
1188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * <code><b>R</b>[&tau;]</code>.
1198212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param v The <code>&tau;</code>-adic part of the element
1208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * <code>&lambda;</code> of <code><b>R</b>[&tau;]</code>.
1218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @return The norm of <code>&lambda;</code>.
1228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     */
1238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public static SimpleBigDecimal norm(final byte mu, SimpleBigDecimal u,
1248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            SimpleBigDecimal v)
1258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
1268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        SimpleBigDecimal norm;
1278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // s1 = u^2
1298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        SimpleBigDecimal s1 = u.multiply(u);
1308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // s2 = u * v
1328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        SimpleBigDecimal s2 = u.multiply(v);
1338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // s3 = 2 * v^2
1358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        SimpleBigDecimal s3 = v.multiply(v).shiftLeft(1);
1368212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1378212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (mu == 1)
1388212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
1398212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            norm = s1.add(s2).add(s3);
1408212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
1418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        else if (mu == -1)
1428212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
1438212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            norm = s1.subtract(s2).add(s3);
1448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
1458212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        else
1468212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
1478212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            throw new IllegalArgumentException("mu must be 1 or -1");
1488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
1498212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1508212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return norm;
1518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
1528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1538212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    /**
1548212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * Rounds an element <code>&lambda;</code> of <code><b>R</b>[&tau;]</code>
1558212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * to an element of <code><b>Z</b>[&tau;]</code>, such that their difference
1568212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * has minimal norm. <code>&lambda;</code> is given as
1578212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * <code>&lambda; = &lambda;<sub>0</sub> + &lambda;<sub>1</sub>&tau;</code>.
1588212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param lambda0 The component <code>&lambda;<sub>0</sub></code>.
1598212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param lambda1 The component <code>&lambda;<sub>1</sub></code>.
1608212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param mu The parameter <code>&mu;</code> of the elliptic curve. Must
1618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * equal 1 or -1.
1628212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @return The rounded element of <code><b>Z</b>[&tau;]</code>.
1638212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @throws IllegalArgumentException if <code>lambda0</code> and
1648212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * <code>lambda1</code> do not have same scale.
1658212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     */
1668212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public static ZTauElement round(SimpleBigDecimal lambda0,
1678212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            SimpleBigDecimal lambda1, byte mu)
1688212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
1698212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        int scale = lambda0.getScale();
1708212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (lambda1.getScale() != scale)
1718212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
1728212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            throw new IllegalArgumentException("lambda0 and lambda1 do not " +
1738212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    "have same scale");
1748212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
1758212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1768212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (!((mu == 1) || (mu == -1)))
1778212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
1788212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            throw new IllegalArgumentException("mu must be 1 or -1");
1798212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
1808212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1818212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger f0 = lambda0.round();
1828212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger f1 = lambda1.round();
1838212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1848212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        SimpleBigDecimal eta0 = lambda0.subtract(f0);
1858212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        SimpleBigDecimal eta1 = lambda1.subtract(f1);
1868212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1878212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // eta = 2*eta0 + mu*eta1
1888212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        SimpleBigDecimal eta = eta0.add(eta0);
1898212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (mu == 1)
1908212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
1918212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            eta = eta.add(eta1);
1928212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
1938212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        else
1948212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
1958212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            // mu == -1
1968212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            eta = eta.subtract(eta1);
1978212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
1988212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
1998212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // check1 = eta0 - 3*mu*eta1
2008212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // check2 = eta0 + 4*mu*eta1
2018212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        SimpleBigDecimal threeEta1 = eta1.add(eta1).add(eta1);
2028212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        SimpleBigDecimal fourEta1 = threeEta1.add(eta1);
2038212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        SimpleBigDecimal check1;
2048212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        SimpleBigDecimal check2;
2058212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (mu == 1)
2068212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
2078212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            check1 = eta0.subtract(threeEta1);
2088212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            check2 = eta0.add(fourEta1);
2098212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
2108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        else
2118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
2128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            // mu == -1
2138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            check1 = eta0.add(threeEta1);
2148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            check2 = eta0.subtract(fourEta1);
2158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
2168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        byte h0 = 0;
2188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        byte h1 = 0;
2198212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // if eta >= 1
2218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (eta.compareTo(ECConstants.ONE) >= 0)
2228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
2238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (check1.compareTo(MINUS_ONE) < 0)
2248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
2258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                h1 = mu;
2268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
2278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            else
2288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
2298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                h0 = 1;
2308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
2318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
2328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        else
2338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
2348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            // eta < 1
2358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (check2.compareTo(ECConstants.TWO) >= 0)
2368212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
2378212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                h1 = mu;
2388212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
2398212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
2408212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // if eta < -1
2428212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (eta.compareTo(MINUS_ONE) < 0)
2438212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
2448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (check1.compareTo(ECConstants.ONE) >= 0)
2458212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
2468212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                h1 = (byte)-mu;
2478212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
2488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            else
2498212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
2508212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                h0 = -1;
2518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
2528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
2538212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        else
2548212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
2558212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            // eta >= -1
2568212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (check2.compareTo(MINUS_TWO) < 0)
2578212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
2588212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                h1 = (byte)-mu;
2598212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
2608212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
2618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2628212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger q0 = f0.add(BigInteger.valueOf(h0));
2638212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger q1 = f1.add(BigInteger.valueOf(h1));
2648212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return new ZTauElement(q0, q1);
2658212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
2668212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2678212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    /**
2688212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * Approximate division by <code>n</code>. For an integer
2698212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * <code>k</code>, the value <code>&lambda; = s k / n</code> is
2708212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * computed to <code>c</code> bits of accuracy.
2718212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param k The parameter <code>k</code>.
2728212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param s The curve parameter <code>s<sub>0</sub></code> or
2738212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * <code>s<sub>1</sub></code>.
2748212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param vm The Lucas Sequence element <code>V<sub>m</sub></code>.
2758212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param a The parameter <code>a</code> of the elliptic curve.
2768212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param m The bit length of the finite field
2778212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * <code><b>F</b><sub>m</sub></code>.
2788212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param c The number of bits of accuracy, i.e. the scale of the returned
2798212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * <code>SimpleBigDecimal</code>.
2808212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @return The value <code>&lambda; = s k / n</code> computed to
2818212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * <code>c</code> bits of accuracy.
2828212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     */
2838212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public static SimpleBigDecimal approximateDivisionByN(BigInteger k,
2848212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            BigInteger s, BigInteger vm, byte a, int m, int c)
2858212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
2868212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        int _k = (m + 5)/2 + c;
2878212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger ns = k.shiftRight(m - _k - 2 + a);
2888212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2898212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger gs = s.multiply(ns);
2908212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2918212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger hs = gs.shiftRight(m);
2928212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2938212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger js = vm.multiply(hs);
2948212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
2958212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger gsPlusJs = gs.add(js);
2968212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger ls = gsPlusJs.shiftRight(_k-c);
2978212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (gsPlusJs.testBit(_k-c-1))
2988212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
2998212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            // round up
3008212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            ls = ls.add(ECConstants.ONE);
3018212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
3028212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3038212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return new SimpleBigDecimal(ls, c);
3048212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
3058212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3068212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    /**
3078212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * Computes the <code>&tau;</code>-adic NAF (non-adjacent form) of an
3088212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * element <code>&lambda;</code> of <code><b>Z</b>[&tau;]</code>.
3098212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param mu The parameter <code>&mu;</code> of the elliptic curve.
3108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param lambda The element <code>&lambda;</code> of
3118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * <code><b>Z</b>[&tau;]</code>.
3128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @return The <code>&tau;</code>-adic NAF of <code>&lambda;</code>.
3138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     */
3148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public static byte[] tauAdicNaf(byte mu, ZTauElement lambda)
3158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
3168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (!((mu == 1) || (mu == -1)))
3178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
3188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            throw new IllegalArgumentException("mu must be 1 or -1");
3198212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
3208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger norm = norm(mu, lambda);
3228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // Ceiling of log2 of the norm
3248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        int log2Norm = norm.bitLength();
3258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // If length(TNAF) > 30, then length(TNAF) < log2Norm + 3.52
3278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        int maxLength = log2Norm > 30 ? log2Norm + 4 : 34;
3288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // The array holding the TNAF
3308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        byte[] u = new byte[maxLength];
3318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        int i = 0;
3328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // The actual length of the TNAF
3348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        int length = 0;
3358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3368212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger r0 = lambda.u;
3378212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger r1 = lambda.v;
3388212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3398212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        while(!((r0.equals(ECConstants.ZERO)) && (r1.equals(ECConstants.ZERO))))
3408212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
3418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            // If r0 is odd
3428212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (r0.testBit(0))
3438212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
3448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                u[i] = (byte) ECConstants.TWO.subtract((r0.subtract(r1.shiftLeft(1))).mod(ECConstants.FOUR)).intValue();
3458212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3468212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                // r0 = r0 - u[i]
3478212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                if (u[i] == 1)
3488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                {
3498212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    r0 = r0.clearBit(0);
3508212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                }
3518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                else
3528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                {
3538212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    // u[i] == -1
3548212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    r0 = r0.add(ECConstants.ONE);
3558212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                }
3568212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                length = i;
3578212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
3588212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            else
3598212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
3608212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                u[i] = 0;
3618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
3628212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3638212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            BigInteger t = r0;
3648212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            BigInteger s = r0.shiftRight(1);
3658212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (mu == 1)
3668212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
3678212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                r0 = r1.add(s);
3688212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
3698212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            else
3708212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
3718212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                // mu == -1
3728212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                r0 = r1.subtract(s);
3738212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
3748212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3758212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            r1 = t.shiftRight(1).negate();
3768212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            i++;
3778212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
3788212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3798212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        length++;
3808212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3818212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // Reduce the TNAF array to its actual length
3828212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        byte[] tnaf = new byte[length];
3838212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        System.arraycopy(u, 0, tnaf, 0, length);
3848212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return tnaf;
3858212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
3868212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
3878212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    /**
3888212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * Applies the operation <code>&tau;()</code> to an
3898212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * <code>ECPoint.F2m</code>.
3908212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param p The ECPoint.F2m to which <code>&tau;()</code> is applied.
3918212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @return <code>&tau;(p)</code>
3928212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     */
3938212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public static ECPoint.F2m tau(ECPoint.F2m p)
3948212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
3958212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (p.isInfinity())
3968212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
3978212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return p;
3988212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
3998212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4008212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        ECFieldElement x = p.getX();
4018212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        ECFieldElement y = p.getY();
4028212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4038212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return new ECPoint.F2m(p.getCurve(), x.square(), y.square(), p.isCompressed());
4048212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
4058212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4068212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    /**
4078212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * Returns the parameter <code>&mu;</code> of the elliptic curve.
4088212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param curve The elliptic curve from which to obtain <code>&mu;</code>.
4098212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * The curve must be a Koblitz curve, i.e. <code>a</code> equals
4108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * <code>0</code> or <code>1</code> and <code>b</code> equals
4118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * <code>1</code>.
4128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @return <code>&mu;</code> of the elliptic curve.
4138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @throws IllegalArgumentException if the given ECCurve is not a Koblitz
4148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * curve.
4158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     */
4168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public static byte getMu(ECCurve.F2m curve)
4178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
4188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger a = curve.getA().toBigInteger();
4198212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        byte mu;
4208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (a.equals(ECConstants.ZERO))
4228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
4238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            mu = -1;
4248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
4258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        else if (a.equals(ECConstants.ONE))
4268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
4278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            mu = 1;
4288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
4298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        else
4308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
4318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            throw new IllegalArgumentException("No Koblitz curve (ABC), " +
4328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    "TNAF multiplication not possible");
4338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
4348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return mu;
4358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
4368212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4378212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    /**
4388212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * Calculates the Lucas Sequence elements <code>U<sub>k-1</sub></code> and
4398212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * <code>U<sub>k</sub></code> or <code>V<sub>k-1</sub></code> and
4408212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * <code>V<sub>k</sub></code>.
4418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param mu The parameter <code>&mu;</code> of the elliptic curve.
4428212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param k The index of the second element of the Lucas Sequence to be
4438212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * returned.
4448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param doV If set to true, computes <code>V<sub>k-1</sub></code> and
4458212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * <code>V<sub>k</sub></code>, otherwise <code>U<sub>k-1</sub></code> and
4468212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * <code>U<sub>k</sub></code>.
4478212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @return An array with 2 elements, containing <code>U<sub>k-1</sub></code>
4488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * and <code>U<sub>k</sub></code> or <code>V<sub>k-1</sub></code>
4498212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * and <code>V<sub>k</sub></code>.
4508212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     */
4518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public static BigInteger[] getLucas(byte mu, int k, boolean doV)
4528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
4538212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (!((mu == 1) || (mu == -1)))
4548212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
4558212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            throw new IllegalArgumentException("mu must be 1 or -1");
4568212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
4578212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4588212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger u0;
4598212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger u1;
4608212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger u2;
4618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4628212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (doV)
4638212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
4648212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            u0 = ECConstants.TWO;
4658212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            u1 = BigInteger.valueOf(mu);
4668212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
4678212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        else
4688212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
4698212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            u0 = ECConstants.ZERO;
4708212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            u1 = ECConstants.ONE;
4718212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
4728212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4738212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        for (int i = 1; i < k; i++)
4748212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
4758212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            // u2 = mu*u1 - 2*u0;
4768212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            BigInteger s = null;
4778212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (mu == 1)
4788212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
4798212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                s = u1;
4808212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
4818212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            else
4828212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
4838212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                // mu == -1
4848212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                s = u1.negate();
4858212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
4868212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4878212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            u2 = s.subtract(u0.shiftLeft(1));
4888212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            u0 = u1;
4898212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            u1 = u2;
4908212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom//            System.out.println(i + ": " + u2);
4918212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom//            System.out.println();
4928212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
4938212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4948212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger[] retVal = {u0, u1};
4958212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return retVal;
4968212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
4978212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
4988212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    /**
4998212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * Computes the auxiliary value <code>t<sub>w</sub></code>. If the width is
5008212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * 4, then for <code>mu = 1</code>, <code>t<sub>w</sub> = 6</code> and for
5018212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * <code>mu = -1</code>, <code>t<sub>w</sub> = 10</code>
5028212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param mu The parameter <code>&mu;</code> of the elliptic curve.
5038212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param w The window width of the WTNAF.
5048212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @return the auxiliary value <code>t<sub>w</sub></code>
5058212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     */
5068212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public static BigInteger getTw(byte mu, int w)
5078212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
5088212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (w == 4)
5098212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
5108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (mu == 1)
5118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
5128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                return BigInteger.valueOf(6);
5138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
5148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            else
5158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
5168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                // mu == -1
5178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                return BigInteger.valueOf(10);
5188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
5198212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
5208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        else
5218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
5228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            // For w <> 4, the values must be computed
5238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            BigInteger[] us = getLucas(mu, w, false);
5248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            BigInteger twoToW = ECConstants.ZERO.setBit(w);
5258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            BigInteger u1invert = us[1].modInverse(twoToW);
5268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            BigInteger tw;
5278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            tw = ECConstants.TWO.multiply(us[0]).multiply(u1invert).mod(twoToW);
5288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom//            System.out.println("mu = " + mu);
5298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom//            System.out.println("tw = " + tw);
5308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            return tw;
5318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
5328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
5338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
5348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    /**
5358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * Computes the auxiliary values <code>s<sub>0</sub></code> and
5368212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * <code>s<sub>1</sub></code> used for partial modular reduction.
5378212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param curve The elliptic curve for which to compute
5388212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * <code>s<sub>0</sub></code> and <code>s<sub>1</sub></code>.
5398212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @throws IllegalArgumentException if <code>curve</code> is not a
5408212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * Koblitz curve (Anomalous Binary Curve, ABC).
5418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     */
5428212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public static BigInteger[] getSi(ECCurve.F2m curve)
5438212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
5448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (!curve.isKoblitz())
5458212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
5468212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            throw new IllegalArgumentException("si is defined for Koblitz curves only");
5478212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
5488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
5498212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        int m = curve.getM();
5508212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        int a = curve.getA().toBigInteger().intValue();
5518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        byte mu = curve.getMu();
5528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        int h = curve.getH().intValue();
5538212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        int index = m + 3 - a;
5548212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger[] ui = getLucas(mu, index, false);
5558212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
5568212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger dividend0;
5578212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger dividend1;
5588212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (mu == 1)
5598212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
5608212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            dividend0 = ECConstants.ONE.subtract(ui[1]);
5618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            dividend1 = ECConstants.ONE.subtract(ui[0]);
5628212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
5638212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        else if (mu == -1)
5648212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
5658212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            dividend0 = ECConstants.ONE.add(ui[1]);
5668212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            dividend1 = ECConstants.ONE.add(ui[0]);
5678212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
5688212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        else
5698212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
5708212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            throw new IllegalArgumentException("mu must be 1 or -1");
5718212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
5728212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
5738212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger[] si = new BigInteger[2];
5748212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
5758212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (h == 2)
5768212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
5778212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            si[0] = dividend0.shiftRight(1);
5788212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            si[1] = dividend1.shiftRight(1).negate();
5798212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
5808212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        else if (h == 4)
5818212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
5828212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            si[0] = dividend0.shiftRight(2);
5838212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            si[1] = dividend1.shiftRight(2).negate();
5848212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
5858212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        else
5868212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
5878212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            throw new IllegalArgumentException("h (Cofactor) must be 2 or 4");
5888212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
5898212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
5908212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return si;
5918212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
5928212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
5938212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    /**
5948212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * Partial modular reduction modulo
5958212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * <code>(&tau;<sup>m</sup> - 1)/(&tau; - 1)</code>.
5968212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param k The integer to be reduced.
5978212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param m The bitlength of the underlying finite field.
5988212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param a The parameter <code>a</code> of the elliptic curve.
5998212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param s The auxiliary values <code>s<sub>0</sub></code> and
6008212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * <code>s<sub>1</sub></code>.
6018212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param mu The parameter &mu; of the elliptic curve.
6028212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param c The precision (number of bits of accuracy) of the partial
6038212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * modular reduction.
6048212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @return <code>&rho; := k partmod (&tau;<sup>m</sup> - 1)/(&tau; - 1)</code>
6058212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     */
6068212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public static ZTauElement partModReduction(BigInteger k, int m, byte a,
6078212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            BigInteger[] s, byte mu, byte c)
6088212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
6098212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // d0 = s[0] + mu*s[1]; mu is either 1 or -1
6108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger d0;
6118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (mu == 1)
6128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
6138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            d0 = s[0].add(s[1]);
6148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
6158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        else
6168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
6178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            d0 = s[0].subtract(s[1]);
6188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
6198212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
6208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger[] v = getLucas(mu, m, true);
6218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger vm = v[1];
6228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
6238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        SimpleBigDecimal lambda0 = approximateDivisionByN(
6248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                k, s[0], vm, a, m, c);
6258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
6268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        SimpleBigDecimal lambda1 = approximateDivisionByN(
6278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                k, s[1], vm, a, m, c);
6288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
6298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        ZTauElement q = round(lambda0, lambda1, mu);
6308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
6318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // r0 = n - d0*q0 - 2*s1*q1
6328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger r0 = k.subtract(d0.multiply(q.u)).subtract(
6338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                BigInteger.valueOf(2).multiply(s[1]).multiply(q.v));
6348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
6358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // r1 = s1*q0 - s0*q1
6368212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger r1 = s[1].multiply(q.u).subtract(s[0].multiply(q.v));
6378212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
6388212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return new ZTauElement(r0, r1);
6398212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
6408212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
6418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    /**
6428212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m}
6438212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * by a <code>BigInteger</code> using the reduced <code>&tau;</code>-adic
6448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * NAF (RTNAF) method.
6458212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param p The ECPoint.F2m to multiply.
6468212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param k The <code>BigInteger</code> by which to multiply <code>p</code>.
6478212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @return <code>k * p</code>
6488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     */
6498212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public static ECPoint.F2m multiplyRTnaf(ECPoint.F2m p, BigInteger k)
6508212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
6518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        ECCurve.F2m curve = (ECCurve.F2m) p.getCurve();
6528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        int m = curve.getM();
6538212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        byte a = (byte) curve.getA().toBigInteger().intValue();
6548212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        byte mu = curve.getMu();
6558212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger[] s = curve.getSi();
6568212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        ZTauElement rho = partModReduction(k, m, a, s, mu, (byte)10);
6578212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
6588212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return multiplyTnaf(p, rho);
6598212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
6608212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
6618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    /**
6628212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m}
6638212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * by an element <code>&lambda;</code> of <code><b>Z</b>[&tau;]</code>
6648212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * using the <code>&tau;</code>-adic NAF (TNAF) method.
6658212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param p The ECPoint.F2m to multiply.
6668212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param lambda The element <code>&lambda;</code> of
6678212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * <code><b>Z</b>[&tau;]</code>.
6688212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @return <code>&lambda; * p</code>
6698212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     */
6708212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public static ECPoint.F2m multiplyTnaf(ECPoint.F2m p, ZTauElement lambda)
6718212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
6728212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        ECCurve.F2m curve = (ECCurve.F2m)p.getCurve();
6738212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        byte mu = curve.getMu();
6748212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        byte[] u = tauAdicNaf(mu, lambda);
6758212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
6768212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        ECPoint.F2m q = multiplyFromTnaf(p, u);
6778212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
6788212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return q;
6798212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
6808212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
6818212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    /**
6828212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m}
6838212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    * by an element <code>&lambda;</code> of <code><b>Z</b>[&tau;]</code>
6848212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    * using the <code>&tau;</code>-adic NAF (TNAF) method, given the TNAF
6858212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    * of <code>&lambda;</code>.
6868212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    * @param p The ECPoint.F2m to multiply.
6878212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    * @param u The the TNAF of <code>&lambda;</code>..
6888212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    * @return <code>&lambda; * p</code>
6898212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    */
6908212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public static ECPoint.F2m multiplyFromTnaf(ECPoint.F2m p, byte[] u)
6918212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
6928212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        ECCurve.F2m curve = (ECCurve.F2m)p.getCurve();
6938212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        ECPoint.F2m q = (ECPoint.F2m) curve.getInfinity();
6948212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        for (int i = u.length - 1; i >= 0; i--)
6958212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
6968212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            q = tau(q);
6978212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (u[i] == 1)
6988212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
6998212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                q = (ECPoint.F2m)q.addSimple(p);
7008212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
7018212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            else if (u[i] == -1)
7028212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
7038212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                q = (ECPoint.F2m)q.subtractSimple(p);
7048212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
7058212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
7068212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return q;
7078212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
7088212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
7098212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    /**
7108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * Computes the <code>[&tau;]</code>-adic window NAF of an element
7118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * <code>&lambda;</code> of <code><b>Z</b>[&tau;]</code>.
7128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param mu The parameter &mu; of the elliptic curve.
7138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param lambda The element <code>&lambda;</code> of
7148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * <code><b>Z</b>[&tau;]</code> of which to compute the
7158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * <code>[&tau;]</code>-adic NAF.
7168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param width The window width of the resulting WNAF.
7178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param pow2w 2<sup>width</sup>.
7188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param tw The auxiliary value <code>t<sub>w</sub></code>.
7198212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param alpha The <code>&alpha;<sub>u</sub></code>'s for the window width.
7208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @return The <code>[&tau;]</code>-adic window NAF of
7218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * <code>&lambda;</code>.
7228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     */
7238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public static byte[] tauAdicWNaf(byte mu, ZTauElement lambda,
7248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            byte width, BigInteger pow2w, BigInteger tw, ZTauElement[] alpha)
7258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
7268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (!((mu == 1) || (mu == -1)))
7278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
7288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            throw new IllegalArgumentException("mu must be 1 or -1");
7298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
7308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
7318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger norm = norm(mu, lambda);
7328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
7338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // Ceiling of log2 of the norm
7348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        int log2Norm = norm.bitLength();
7358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
7368212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // If length(TNAF) > 30, then length(TNAF) < log2Norm + 3.52
7378212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        int maxLength = log2Norm > 30 ? log2Norm + 4 + width : 34 + width;
7388212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
7398212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // The array holding the TNAF
7408212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        byte[] u = new byte[maxLength];
7418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
7428212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // 2^(width - 1)
7438212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger pow2wMin1 = pow2w.shiftRight(1);
7448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
7458212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // Split lambda into two BigIntegers to simplify calculations
7468212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger r0 = lambda.u;
7478212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        BigInteger r1 = lambda.v;
7488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        int i = 0;
7498212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
7508212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        // while lambda <> (0, 0)
7518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        while (!((r0.equals(ECConstants.ZERO))&&(r1.equals(ECConstants.ZERO))))
7528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
7538212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            // if r0 is odd
7548212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (r0.testBit(0))
7558212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
7568212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                // uUnMod = r0 + r1*tw mod 2^width
7578212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                BigInteger uUnMod
7588212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    = r0.add(r1.multiply(tw)).mod(pow2w);
7598212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
7608212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                byte uLocal;
7618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                // if uUnMod >= 2^(width - 1)
7628212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                if (uUnMod.compareTo(pow2wMin1) >= 0)
7638212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                {
7648212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    uLocal = (byte) uUnMod.subtract(pow2w).intValue();
7658212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                }
7668212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                else
7678212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                {
7688212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    uLocal = (byte) uUnMod.intValue();
7698212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                }
7708212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                // uLocal is now in [-2^(width-1), 2^(width-1)-1]
7718212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
7728212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                u[i] = uLocal;
7738212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                boolean s = true;
7748212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                if (uLocal < 0)
7758212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                {
7768212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    s = false;
7778212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    uLocal = (byte)-uLocal;
7788212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                }
7798212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                // uLocal is now >= 0
7808212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
7818212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                if (s)
7828212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                {
7838212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    r0 = r0.subtract(alpha[uLocal].u);
7848212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    r1 = r1.subtract(alpha[uLocal].v);
7858212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                }
7868212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                else
7878212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                {
7888212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    r0 = r0.add(alpha[uLocal].u);
7898212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                    r1 = r1.add(alpha[uLocal].v);
7908212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                }
7918212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
7928212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            else
7938212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
7948212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                u[i] = 0;
7958212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
7968212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
7978212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            BigInteger t = r0;
7988212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
7998212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            if (mu == 1)
8008212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
8018212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                r0 = r1.add(r0.shiftRight(1));
8028212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
8038212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            else
8048212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            {
8058212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                // mu == -1
8068212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom                r0 = r1.subtract(r0.shiftRight(1));
8078212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            }
8088212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            r1 = t.shiftRight(1).negate();
8098212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            i++;
8108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
8118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return u;
8128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
8138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
8148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    /**
8158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * Does the precomputation for WTNAF multiplication.
8168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param p The <code>ECPoint</code> for which to do the precomputation.
8178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @param a The parameter <code>a</code> of the elliptic curve.
8188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     * @return The precomputation array for <code>p</code>.
8198212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom     */
8208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    public static ECPoint.F2m[] getPreComp(ECPoint.F2m p, byte a)
8218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    {
8228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        ECPoint.F2m[] pu;
8238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        pu = new ECPoint.F2m[16];
8248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        pu[1] = p;
8258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        byte[][] alphaTnaf;
8268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        if (a == 0)
8278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
8288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            alphaTnaf = Tnaf.alpha0Tnaf;
8298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
8308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        else
8318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
8328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            // a == 1
8338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            alphaTnaf = Tnaf.alpha1Tnaf;
8348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
8358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
8368212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        int precompLen = alphaTnaf.length;
8378212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        for (int i = 3; i < precompLen; i = i + 2)
8388212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        {
8398212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom            pu[i] = Tnaf.multiplyFromTnaf(p, alphaTnaf[i]);
8408212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        }
8418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom
8428212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom        return pu;
8438212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom    }
8448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom}
845