1package org.bouncycastle.math.ec;
2
3import java.math.BigInteger;
4
5/**
6 * Class implementing the WTNAF (Window
7 * <code>&tau;</code>-adic Non-Adjacent Form) algorithm.
8 */
9class WTauNafMultiplier implements ECMultiplier
10{
11    /**
12     * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m}
13     * by <code>k</code> using the reduced <code>&tau;</code>-adic NAF (RTNAF)
14     * method.
15     * @param p The ECPoint.F2m to multiply.
16     * @param k The integer by which to multiply <code>k</code>.
17     * @return <code>p</code> multiplied by <code>k</code>.
18     */
19    public ECPoint multiply(ECPoint point, BigInteger k, PreCompInfo preCompInfo)
20    {
21        if (!(point instanceof ECPoint.F2m))
22        {
23            throw new IllegalArgumentException("Only ECPoint.F2m can be " +
24                    "used in WTauNafMultiplier");
25        }
26
27        ECPoint.F2m p = (ECPoint.F2m)point;
28
29        ECCurve.F2m curve = (ECCurve.F2m) p.getCurve();
30        int m = curve.getM();
31        byte a = curve.getA().toBigInteger().byteValue();
32        byte mu = curve.getMu();
33        BigInteger[] s = curve.getSi();
34
35        ZTauElement rho = Tnaf.partModReduction(k, m, a, s, mu, (byte)10);
36
37        return multiplyWTnaf(p, rho, preCompInfo, a, mu);
38    }
39
40    /**
41     * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m}
42     * by an element <code>&lambda;</code> of <code><b>Z</b>[&tau;]</code> using
43     * the <code>&tau;</code>-adic NAF (TNAF) method.
44     * @param p The ECPoint.F2m to multiply.
45     * @param lambda The element <code>&lambda;</code> of
46     * <code><b>Z</b>[&tau;]</code> of which to compute the
47     * <code>[&tau;]</code>-adic NAF.
48     * @return <code>p</code> multiplied by <code>&lambda;</code>.
49     */
50    private ECPoint.F2m multiplyWTnaf(ECPoint.F2m p, ZTauElement lambda,
51            PreCompInfo preCompInfo, byte a, byte mu)
52    {
53        ZTauElement[] alpha;
54        if (a == 0)
55        {
56            alpha = Tnaf.alpha0;
57        }
58        else
59        {
60            // a == 1
61            alpha = Tnaf.alpha1;
62        }
63
64        BigInteger tw = Tnaf.getTw(mu, Tnaf.WIDTH);
65
66        byte[]u = Tnaf.tauAdicWNaf(mu, lambda, Tnaf.WIDTH,
67                BigInteger.valueOf(Tnaf.POW_2_WIDTH), tw, alpha);
68
69        return multiplyFromWTnaf(p, u, preCompInfo);
70    }
71
72    /**
73     * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m}
74     * by an element <code>&lambda;</code> of <code><b>Z</b>[&tau;]</code>
75     * using the window <code>&tau;</code>-adic NAF (TNAF) method, given the
76     * WTNAF of <code>&lambda;</code>.
77     * @param p The ECPoint.F2m to multiply.
78     * @param u The the WTNAF of <code>&lambda;</code>..
79     * @return <code>&lambda; * p</code>
80     */
81    private static ECPoint.F2m multiplyFromWTnaf(ECPoint.F2m p, byte[] u,
82            PreCompInfo preCompInfo)
83    {
84        ECCurve.F2m curve = (ECCurve.F2m)p.getCurve();
85        byte a = curve.getA().toBigInteger().byteValue();
86
87        ECPoint.F2m[] pu;
88        if ((preCompInfo == null) || !(preCompInfo instanceof WTauNafPreCompInfo))
89        {
90            pu = Tnaf.getPreComp(p, a);
91            p.setPreCompInfo(new WTauNafPreCompInfo(pu));
92        }
93        else
94        {
95            pu = ((WTauNafPreCompInfo)preCompInfo).getPreComp();
96        }
97
98        // q = infinity
99        ECPoint.F2m q = (ECPoint.F2m) p.getCurve().getInfinity();
100        for (int i = u.length - 1; i >= 0; i--)
101        {
102            q = Tnaf.tau(q);
103            if (u[i] != 0)
104            {
105                if (u[i] > 0)
106                {
107                    q = q.addSimple(pu[u[i]]);
108                }
109                else
110                {
111                    // u[i] < 0
112                    q = q.subtractSimple(pu[-u[i]]);
113                }
114            }
115        }
116
117        return q;
118    }
119}
120