I'm trying to understand the implementation of elliptic curve point multiplication. I can easily understand the naive double-and-add algorithm, but I'm struggling to find a good explanation / example of the window method, or indeed of the wNAF method.
The canonical reference seems to be this Wikipedia page, in which is outlined all the various algorithms on a high level.
Does anyone know of any accessible explanations / examples of either the window method / wNAF method for point multiplication? Alternatively, can anyone easily explain how these algorithms work?
To give you an example of how I'm confused by the Wikipedia article, the windowed method is listed as:
Q ← 0
for i from m to 0 do
Q ← point_double_repeat(Q, w)
if di > 0 then
Q ← point_add(Q, diP) # using pre-computed value of diP
return Q
But it references the "point_double_repeat(Q, w)". method call. But what is this method? What does this actually do?
With regards to the "w-ary non-adjacent form (wNAF) method", the algorithm seems simple to follow, but it's hard to be confident that I understand it properly without a simple example.
I understand that this is probably quite rudimentary to many people on this forum, but I would nonetheless greatly appreciate any help.
Update 10 Aug:
Reading Sam's answer below makes sense, and I was able to implement the wNAF method, but I'm still having trouble understanding how to implement the window method.
This is how I've tried to understand it:
Lets start with an example of a normal double-and-add for the scalar 2329
.
2329 in binary is 100100011001, so going from right to left:
1 0 0 1 0 0 0 1 1 0 0 1
DBL DBL DBL DBL DBL DBL DBL DBL DBL DBL DBL START
ADD ADD ADD ADD ADD
2048 256 16 8 1
As you can see there are 12 doubles and five additions. Now I'm going to try to convert this to a window method so that there are less additions. Lets use a window size of 4:
1 0 0 1 0 0 0 1 1 0 0 1
DBL DBL DBL DBL DBL DBL DBL DBL DBL DBL DBL START
2048 + 256 16 8 + 1
--------------- --------------- ---------------
2304 + 16 + 9
This means only three additions, a reduction of 40%, excellent.
Now for the algorithm itself, as per the description in Wikipedia:
One selects a window size $w$ and computes all $2^w$ values of $dP$ for $d = 0,1,2,...2^w - 1$. The algorithm now uses the representation $d = d_0 + 2^wd_1 + 2^{2w}d_2 + ... + 2^{mw}d_m$
In the example of using the scalar 2329 with a window size of 4, this means pre-computing a collection of 16 points, ($0 ... 2^4 - 1$ or $0 ... 15$).
For the scalar value, the algorithm then uses the representation $(9 \cdot 2^0) + (1 \cdot 2^4) + (9 \cdot 2^8)$. Simplifying: $(9 + 16 + 2304)$. So in the algorithm below, this means that $d1 = 9, d2 = 16, d3 = 2304$, and "m" is 3.
This is the window method of the algorithm as per Wikipedia:
Q ← 0
for i from m to 0 do
Q ← point_double_repeat(Q, w)
if di > 0 then
Q ← point_add(Q, diP) # using pre-computed value of diP
return Q
In this case, when it comes to adding the pre-computed point $d_iP$ There are three iterations, in which $d_i$ is either $9P, 16P, or 2304P$. But our pre-computes are $0,1,2,...2^w-1$. In order words, there is no "$9P$" in our pre-computes. There is only $P,2P,4P,8P,16P,32P,64P....$
Obviously I have misunderstood either the algorithm itself or how I am supposed to compute the pre-computes that algorithm uses, either way I'm at a bit of a loss.
point_double_repeat(Q,w)
computes $[2^w]Q$, i.e. it successively doubles $Q$ $w$-times. $\endgroup$