package org.bouncycastle.math.ec;

import java.math.BigInteger;

/**
 * Class implementing the WNAF (Window Non-Adjacent Form) multiplication
 * algorithm.
 */
public class WNafL2RMultiplier implements ECMultiplier
{
    /**
     * Multiplies <code>this</code> by an integer <code>k</code> using the
     * Window NAF method.
     * @param k The integer by which <code>this</code> is multiplied.
     * @return A new <code>ECPoint</code> which equals <code>this</code>
     * multiplied by <code>k</code>.
     */
    public ECPoint multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo)
    {
        // floor(log2(k))
        int m = k.bitLength();

        // Clamp the window width in the range [2, 8]
        int width = Math.max(2, Math.min(8, getWindowSize(m)));

        WNafPreCompInfo wnafPreCompInfo = WNafUtil.precompute(p, preCompInfo, width);
        ECPoint[] preComp = wnafPreCompInfo.getPreComp();

        // Compute the Window NAF of the desired width
        byte[] wnaf = WNafUtil.generateWindowNaf(width, k);
        int l = wnaf.length;

        // Apply the Window NAF to p using the precomputed ECPoint values.
        ECPoint q = p.getCurve().getInfinity();
        for (int i = l - 1; i >= 0; i--)
        {
            int wi = wnaf[i];
            if (wi == 0)
            {
                q = q.twice();
            }
            else
            {
                int index = (Math.abs(wi) - 1) / 2;
                ECPoint r = preComp[index];
                if (wi < 0)
                {
                    r = r.negate();
                }

                q = q.twicePlus(r);
            }
        }

        return q;
    }

    /**
     * Determine window width to use for a scalar multiplication of the given size.
     * 
     * @param bits the bit-length of the scalar to multiply by
     * @return the window size to use
     */
    protected int getWindowSize(int bits)
    {
        return WNafUtil.getWindowSize(bits);
    }
}

@@ -603,56 +603,217 @@
     
-// floor(log2(k))%0A        int m = k.bitLength();
+if (k.signum() %3C 0)%0A        %7B%0A            throw new IllegalArgumentException(%22'k' cannot be negative%22);%0A        %7D%0A        if (k.signum() == 0)%0A        %7B%0A            return p.getCurve().getInfinity();%0A        %7D
 %0A%0A  
@@ -922,17 +922,29 @@
 dowSize(
-m
+k.bitLength()
 )));%0A%0A  
@@ -1098,67 +1098,11 @@
     
-// Compute the Window NAF of the desired width%0A        byte
+int
 %5B%5D w
@@ -1124,16 +1124,23 @@
 generate
+Compact
 WindowNa
@@ -1156,130 +1156,26 @@
 k);%0A
-        int l = wnaf.length;%0A%0A        // Apply the Window NAF to p using the precomputed ECPoint values.%0A        ECPoint q
+%0A        ECPoint R
  = p
@@ -1201,24 +1201,25 @@
 nity();%0A
+%0A
         
 for (int
@@ -1214,21 +1214,16 @@
     
-for (
 int i = 
 l - 
@@ -1222,26 +1222,44 @@
 i = 
-l - 1; i %3E= 0; i--
+wnaf.length;%0A        while (--i %3E= 0
 )%0A  
@@ -1313,114 +1313,52 @@
    i
-f (wi == 0)%0A            %7B%0A                q = q.twice();%0A            %7D%0A            else%0A            %7B%0A    
+nt digit = wi %3E%3E 16, zeroes = wi & 0xFFFF;%0A%0A
     
@@ -1387,18 +1387,21 @@
 ath.abs(
-wi
+digit
 ) - 1) /
@@ -1412,28 +1412,24 @@
             
-    
 ECPoint r = 
@@ -1452,28 +1452,24 @@
             
-    
 if (wi %3C 0)%0A
@@ -1476,34 +1476,26 @@
             
-    %7B%0A    
+%7B%0A
             
@@ -1522,28 +1522,24 @@
             
-    
 %7D%0A%0A         
@@ -1545,17 +1545,13 @@
     
-    q = q
+R = R
 .twi
@@ -1565,33 +1565,56 @@
 r);%0A            
-%7D
+R = R.timesPow2(zeroes);
 %0A        %7D%0A%0A    
@@ -1624,17 +1624,17 @@
  return 
-q
+R
 ;%0A    %7D%0A

Switch to the compact w-NAF format, and call timesPow2