16e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrompackage org.bouncycastle.math.ec;
26e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
36e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport java.math.BigInteger;
46e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
56e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom/**
66e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom * Class implementing the WNAF (Window Non-Adjacent Form) multiplication
76e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom * algorithm.
86e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom */
96e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromclass WNafMultiplier implements ECMultiplier
106e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom{
116e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    /**
126e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom     * Computes the Window NAF (non-adjacent Form) of an integer.
136e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom     * @param width The width <code>w</code> of the Window NAF. The width is
146e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom     * defined as the minimal number <code>w</code>, such that for any
156e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom     * <code>w</code> consecutive digits in the resulting representation, at
166e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom     * most one is non-zero.
176e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom     * @param k The integer of which the Window NAF is computed.
186e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom     * @return The Window NAF of the given width, such that the following holds:
196e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom     * <code>k = &sum;<sub>i=0</sub><sup>l-1</sup> k<sub>i</sub>2<sup>i</sup>
206e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom     * </code>, where the <code>k<sub>i</sub></code> denote the elements of the
216e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom     * returned <code>byte[]</code>.
226e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom     */
236e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    public byte[] windowNaf(byte width, BigInteger k)
246e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    {
256e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        // The window NAF is at most 1 element longer than the binary
266e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        // representation of the integer k. byte can be used instead of short or
276e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        // int unless the window width is larger than 8. For larger width use
286e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        // short or int. However, a width of more than 8 is not efficient for
296e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        // m = log2(q) smaller than 2305 Bits. Note: Values for m larger than
306e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        // 1000 Bits are currently not used in practice.
316e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        byte[] wnaf = new byte[k.bitLength() + 1];
326e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
336e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        // 2^width as short and BigInteger
346e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        short pow2wB = (short)(1 << width);
356e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        BigInteger pow2wBI = BigInteger.valueOf(pow2wB);
366e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
376e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        int i = 0;
386e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
396e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        // The actual length of the WNAF
406e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        int length = 0;
416e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
426e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        // while k >= 1
436e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        while (k.signum() > 0)
446e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
456e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            // if k is odd
466e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            if (k.testBit(0))
476e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            {
486e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                // k mod 2^width
496e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                BigInteger remainder = k.mod(pow2wBI);
506e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
516e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                // if remainder > 2^(width - 1) - 1
526e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                if (remainder.testBit(width - 1))
536e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                {
546e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                    wnaf[i] = (byte)(remainder.intValue() - pow2wB);
556e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                }
566e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                else
576e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                {
586e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                    wnaf[i] = (byte)remainder.intValue();
596e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                }
606e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                // wnaf[i] is now in [-2^(width-1), 2^(width-1)-1]
616e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
626e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                k = k.subtract(BigInteger.valueOf(wnaf[i]));
636e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                length = i;
646e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            }
656e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            else
666e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            {
676e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                wnaf[i] = 0;
686e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            }
696e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
706e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            // k = k/2
716e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            k = k.shiftRight(1);
726e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            i++;
736e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
746e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
756e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        length++;
766e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
776e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        // Reduce the WNAF array to its actual length
786e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        byte[] wnafShort = new byte[length];
796e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        System.arraycopy(wnaf, 0, wnafShort, 0, length);
806e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        return wnafShort;
816e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    }
826e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
836e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    /**
846e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom     * Multiplies <code>this</code> by an integer <code>k</code> using the
856e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom     * Window NAF method.
866e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom     * @param k The integer by which <code>this</code> is multiplied.
876e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom     * @return A new <code>ECPoint</code> which equals <code>this</code>
886e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom     * multiplied by <code>k</code>.
896e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom     */
906e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    public ECPoint multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo)
916e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    {
926e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        WNafPreCompInfo wnafPreCompInfo;
936e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
946e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        if ((preCompInfo != null) && (preCompInfo instanceof WNafPreCompInfo))
956e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
966e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            wnafPreCompInfo = (WNafPreCompInfo)preCompInfo;
976e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
986e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        else
996e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
1006e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            // Ignore empty PreCompInfo or PreCompInfo of incorrect type
1016e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            wnafPreCompInfo = new WNafPreCompInfo();
1026e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
1036e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
1046e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        // floor(log2(k))
1056e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        int m = k.bitLength();
1066e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
1076e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        // width of the Window NAF
1086e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        byte width;
1096e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
1106e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        // Required length of precomputation array
1116e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        int reqPreCompLen;
1126e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
1136e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        // Determine optimal width and corresponding length of precomputation
1146e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        // array based on literature values
1156e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        if (m < 13)
1166e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
1176e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            width = 2;
1186e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            reqPreCompLen = 1;
1196e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
1206e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        else
1216e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
1226e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            if (m < 41)
1236e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            {
1246e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                width = 3;
1256e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                reqPreCompLen = 2;
1266e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            }
1276e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            else
1286e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            {
1296e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                if (m < 121)
1306e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                {
1316e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                    width = 4;
1326e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                    reqPreCompLen = 4;
1336e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                }
1346e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                else
1356e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                {
1366e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                    if (m < 337)
1376e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                    {
1386e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                        width = 5;
1396e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                        reqPreCompLen = 8;
1406e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                    }
1416e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                    else
1426e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                    {
1436e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                        if (m < 897)
1446e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                        {
1456e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                            width = 6;
1466e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                            reqPreCompLen = 16;
1476e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                        }
1486e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                        else
1496e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                        {
1506e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                            if (m < 2305)
1516e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                            {
1526e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                                width = 7;
1536e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                                reqPreCompLen = 32;
1546e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                            }
1556e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                            else
1566e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                            {
1576e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                                width = 8;
1586e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                                reqPreCompLen = 127;
1596e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                            }
1606e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                        }
1616e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                    }
1626e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                }
1636e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            }
1646e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
1656e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
1666e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        // The length of the precomputation array
1676e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        int preCompLen = 1;
1686e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
1696e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        ECPoint[] preComp = wnafPreCompInfo.getPreComp();
1706e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        ECPoint twiceP = wnafPreCompInfo.getTwiceP();
1716e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
1726e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        // Check if the precomputed ECPoints already exist
1736e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        if (preComp == null)
1746e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
1756e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            // Precomputation must be performed from scratch, create an empty
1766e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            // precomputation array of desired length
1776e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            preComp = new ECPoint[]{ p };
1786e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
1796e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        else
1806e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
1816e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            // Take the already precomputed ECPoints to start with
1826e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            preCompLen = preComp.length;
1836e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
1846e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
1856e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        if (twiceP == null)
1866e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
1876e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            // Compute twice(p)
1886e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            twiceP = p.twice();
1896e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
1906e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
1916e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        if (preCompLen < reqPreCompLen)
1926e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
1936e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            // Precomputation array must be made bigger, copy existing preComp
1946e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            // array into the larger new preComp array
1956e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            ECPoint[] oldPreComp = preComp;
1966e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            preComp = new ECPoint[reqPreCompLen];
1976e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            System.arraycopy(oldPreComp, 0, preComp, 0, preCompLen);
1986e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
1996e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            for (int i = preCompLen; i < reqPreCompLen; i++)
2006e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            {
2016e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                // Compute the new ECPoints for the precomputation array.
2026e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                // The values 1, 3, 5, ..., 2^(width-1)-1 times p are
2036e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                // computed
2046e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                preComp[i] = twiceP.add(preComp[i - 1]);
2056e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            }
2066e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
2076e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
2086e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        // Compute the Window NAF of the desired width
2096e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        byte[] wnaf = windowNaf(width, k);
2106e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        int l = wnaf.length;
2116e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
2126e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        // Apply the Window NAF to p using the precomputed ECPoint values.
2136e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        ECPoint q = p.getCurve().getInfinity();
2146e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        for (int i = l - 1; i >= 0; i--)
2156e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
2166e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            q = q.twice();
2176e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
2186e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            if (wnaf[i] != 0)
2196e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            {
2206e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                if (wnaf[i] > 0)
2216e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                {
2226e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                    q = q.add(preComp[(wnaf[i] - 1)/2]);
2236e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                }
2246e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                else
2256e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                {
2266e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                    // wnaf[i] < 0
2276e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                    q = q.subtract(preComp[(-wnaf[i] - 1)/2]);
2286e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                }
2296e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            }
2306e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
2316e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
2326e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        // Set PreCompInfo in ECPoint, such that it is available for next
2336e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        // multiplication.
2346e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        wnafPreCompInfo.setPreComp(preComp);
2356e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        wnafPreCompInfo.setTwiceP(twiceP);
2366e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        p.setPreCompInfo(wnafPreCompInfo);
2376e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        return q;
2386e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    }
2396e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
2406e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom}
241