• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.bouncycastle.math.ec;
2 
3 import java.math.BigInteger;
4 
5 /**
6  * Class holding methods for point multiplication based on the window
7  * τ-adic nonadjacent form (WTNAF). The algorithms are based on the
8  * paper "Improved Algorithms for Arithmetic on Anomalous Binary Curves"
9  * by Jerome A. Solinas. The paper first appeared in the Proceedings of
10  * Crypto 1997.
11  */
12 class Tnaf
13 {
14     private static final BigInteger MINUS_ONE = ECConstants.ONE.negate();
15     private static final BigInteger MINUS_TWO = ECConstants.TWO.negate();
16     private static final BigInteger MINUS_THREE = ECConstants.THREE.negate();
17 
18     /**
19      * The window width of WTNAF. The standard value of 4 is slightly less
20      * than optimal for running time, but keeps space requirements for
21      * precomputation low. For typical curves, a value of 5 or 6 results in
22      * a better running time. When changing this value, the
23      * <code>&alpha;<sub>u</sub></code>'s must be computed differently, see
24      * e.g. "Guide to Elliptic Curve Cryptography", Darrel Hankerson,
25      * Alfred Menezes, Scott Vanstone, Springer-Verlag New York Inc., 2004,
26      * p. 121-122
27      */
28     public static final byte WIDTH = 4;
29 
30     /**
31      * 2<sup>4</sup>
32      */
33     public static final byte POW_2_WIDTH = 16;
34 
35     /**
36      * The <code>&alpha;<sub>u</sub></code>'s for <code>a=0</code> as an array
37      * of <code>ZTauElement</code>s.
38      */
39     public static final ZTauElement[] alpha0 = {
40         null,
41         new ZTauElement(ECConstants.ONE, ECConstants.ZERO), null,
42         new ZTauElement(MINUS_THREE, MINUS_ONE), null,
43         new ZTauElement(MINUS_ONE, MINUS_ONE), null,
44         new ZTauElement(ECConstants.ONE, MINUS_ONE), null
45     };
46 
47     /**
48      * The <code>&alpha;<sub>u</sub></code>'s for <code>a=0</code> as an array
49      * of TNAFs.
50      */
51     public static final byte[][] alpha0Tnaf = {
52         null, {1}, null, {-1, 0, 1}, null, {1, 0, 1}, null, {-1, 0, 0, 1}
53     };
54 
55     /**
56      * The <code>&alpha;<sub>u</sub></code>'s for <code>a=1</code> as an array
57      * of <code>ZTauElement</code>s.
58      */
59     public static final ZTauElement[] alpha1 = {null,
60         new ZTauElement(ECConstants.ONE, ECConstants.ZERO), null,
61         new ZTauElement(MINUS_THREE, ECConstants.ONE), null,
62         new ZTauElement(MINUS_ONE, ECConstants.ONE), null,
63         new ZTauElement(ECConstants.ONE, ECConstants.ONE), null
64     };
65 
66     /**
67      * The <code>&alpha;<sub>u</sub></code>'s for <code>a=1</code> as an array
68      * of TNAFs.
69      */
70     public static final byte[][] alpha1Tnaf = {
71         null, {1}, null, {-1, 0, 1}, null, {1, 0, 1}, null, {-1, 0, 0, -1}
72     };
73 
74     /**
75      * Computes the norm of an element <code>&lambda;</code> of
76      * <code><b>Z</b>[&tau;]</code>.
77      * @param mu The parameter <code>&mu;</code> of the elliptic curve.
78      * @param lambda The element <code>&lambda;</code> of
79      * <code><b>Z</b>[&tau;]</code>.
80      * @return The norm of <code>&lambda;</code>.
81      */
norm(final byte mu, ZTauElement lambda)82     public static BigInteger norm(final byte mu, ZTauElement lambda)
83     {
84         BigInteger norm;
85 
86         // s1 = u^2
87         BigInteger s1 = lambda.u.multiply(lambda.u);
88 
89         // s2 = u * v
90         BigInteger s2 = lambda.u.multiply(lambda.v);
91 
92         // s3 = 2 * v^2
93         BigInteger s3 = lambda.v.multiply(lambda.v).shiftLeft(1);
94 
95         if (mu == 1)
96         {
97             norm = s1.add(s2).add(s3);
98         }
99         else if (mu == -1)
100         {
101             norm = s1.subtract(s2).add(s3);
102         }
103         else
104         {
105             throw new IllegalArgumentException("mu must be 1 or -1");
106         }
107 
108         return norm;
109     }
110 
111     /**
112      * Computes the norm of an element <code>&lambda;</code> of
113      * <code><b>R</b>[&tau;]</code>, where <code>&lambda; = u + v&tau;</code>
114      * and <code>u</code> and <code>u</code> are real numbers (elements of
115      * <code><b>R</b></code>).
116      * @param mu The parameter <code>&mu;</code> of the elliptic curve.
117      * @param u The real part of the element <code>&lambda;</code> of
118      * <code><b>R</b>[&tau;]</code>.
119      * @param v The <code>&tau;</code>-adic part of the element
120      * <code>&lambda;</code> of <code><b>R</b>[&tau;]</code>.
121      * @return The norm of <code>&lambda;</code>.
122      */
norm(final byte mu, SimpleBigDecimal u, SimpleBigDecimal v)123     public static SimpleBigDecimal norm(final byte mu, SimpleBigDecimal u,
124             SimpleBigDecimal v)
125     {
126         SimpleBigDecimal norm;
127 
128         // s1 = u^2
129         SimpleBigDecimal s1 = u.multiply(u);
130 
131         // s2 = u * v
132         SimpleBigDecimal s2 = u.multiply(v);
133 
134         // s3 = 2 * v^2
135         SimpleBigDecimal s3 = v.multiply(v).shiftLeft(1);
136 
137         if (mu == 1)
138         {
139             norm = s1.add(s2).add(s3);
140         }
141         else if (mu == -1)
142         {
143             norm = s1.subtract(s2).add(s3);
144         }
145         else
146         {
147             throw new IllegalArgumentException("mu must be 1 or -1");
148         }
149 
150         return norm;
151     }
152 
153     /**
154      * Rounds an element <code>&lambda;</code> of <code><b>R</b>[&tau;]</code>
155      * to an element of <code><b>Z</b>[&tau;]</code>, such that their difference
156      * has minimal norm. <code>&lambda;</code> is given as
157      * <code>&lambda; = &lambda;<sub>0</sub> + &lambda;<sub>1</sub>&tau;</code>.
158      * @param lambda0 The component <code>&lambda;<sub>0</sub></code>.
159      * @param lambda1 The component <code>&lambda;<sub>1</sub></code>.
160      * @param mu The parameter <code>&mu;</code> of the elliptic curve. Must
161      * equal 1 or -1.
162      * @return The rounded element of <code><b>Z</b>[&tau;]</code>.
163      * @throws IllegalArgumentException if <code>lambda0</code> and
164      * <code>lambda1</code> do not have same scale.
165      */
round(SimpleBigDecimal lambda0, SimpleBigDecimal lambda1, byte mu)166     public static ZTauElement round(SimpleBigDecimal lambda0,
167             SimpleBigDecimal lambda1, byte mu)
168     {
169         int scale = lambda0.getScale();
170         if (lambda1.getScale() != scale)
171         {
172             throw new IllegalArgumentException("lambda0 and lambda1 do not " +
173                     "have same scale");
174         }
175 
176         if (!((mu == 1) || (mu == -1)))
177         {
178             throw new IllegalArgumentException("mu must be 1 or -1");
179         }
180 
181         BigInteger f0 = lambda0.round();
182         BigInteger f1 = lambda1.round();
183 
184         SimpleBigDecimal eta0 = lambda0.subtract(f0);
185         SimpleBigDecimal eta1 = lambda1.subtract(f1);
186 
187         // eta = 2*eta0 + mu*eta1
188         SimpleBigDecimal eta = eta0.add(eta0);
189         if (mu == 1)
190         {
191             eta = eta.add(eta1);
192         }
193         else
194         {
195             // mu == -1
196             eta = eta.subtract(eta1);
197         }
198 
199         // check1 = eta0 - 3*mu*eta1
200         // check2 = eta0 + 4*mu*eta1
201         SimpleBigDecimal threeEta1 = eta1.add(eta1).add(eta1);
202         SimpleBigDecimal fourEta1 = threeEta1.add(eta1);
203         SimpleBigDecimal check1;
204         SimpleBigDecimal check2;
205         if (mu == 1)
206         {
207             check1 = eta0.subtract(threeEta1);
208             check2 = eta0.add(fourEta1);
209         }
210         else
211         {
212             // mu == -1
213             check1 = eta0.add(threeEta1);
214             check2 = eta0.subtract(fourEta1);
215         }
216 
217         byte h0 = 0;
218         byte h1 = 0;
219 
220         // if eta >= 1
221         if (eta.compareTo(ECConstants.ONE) >= 0)
222         {
223             if (check1.compareTo(MINUS_ONE) < 0)
224             {
225                 h1 = mu;
226             }
227             else
228             {
229                 h0 = 1;
230             }
231         }
232         else
233         {
234             // eta < 1
235             if (check2.compareTo(ECConstants.TWO) >= 0)
236             {
237                 h1 = mu;
238             }
239         }
240 
241         // if eta < -1
242         if (eta.compareTo(MINUS_ONE) < 0)
243         {
244             if (check1.compareTo(ECConstants.ONE) >= 0)
245             {
246                 h1 = (byte)-mu;
247             }
248             else
249             {
250                 h0 = -1;
251             }
252         }
253         else
254         {
255             // eta >= -1
256             if (check2.compareTo(MINUS_TWO) < 0)
257             {
258                 h1 = (byte)-mu;
259             }
260         }
261 
262         BigInteger q0 = f0.add(BigInteger.valueOf(h0));
263         BigInteger q1 = f1.add(BigInteger.valueOf(h1));
264         return new ZTauElement(q0, q1);
265     }
266 
267     /**
268      * Approximate division by <code>n</code>. For an integer
269      * <code>k</code>, the value <code>&lambda; = s k / n</code> is
270      * computed to <code>c</code> bits of accuracy.
271      * @param k The parameter <code>k</code>.
272      * @param s The curve parameter <code>s<sub>0</sub></code> or
273      * <code>s<sub>1</sub></code>.
274      * @param vm The Lucas Sequence element <code>V<sub>m</sub></code>.
275      * @param a The parameter <code>a</code> of the elliptic curve.
276      * @param m The bit length of the finite field
277      * <code><b>F</b><sub>m</sub></code>.
278      * @param c The number of bits of accuracy, i.e. the scale of the returned
279      * <code>SimpleBigDecimal</code>.
280      * @return The value <code>&lambda; = s k / n</code> computed to
281      * <code>c</code> bits of accuracy.
282      */
approximateDivisionByN(BigInteger k, BigInteger s, BigInteger vm, byte a, int m, int c)283     public static SimpleBigDecimal approximateDivisionByN(BigInteger k,
284             BigInteger s, BigInteger vm, byte a, int m, int c)
285     {
286         int _k = (m + 5)/2 + c;
287         BigInteger ns = k.shiftRight(m - _k - 2 + a);
288 
289         BigInteger gs = s.multiply(ns);
290 
291         BigInteger hs = gs.shiftRight(m);
292 
293         BigInteger js = vm.multiply(hs);
294 
295         BigInteger gsPlusJs = gs.add(js);
296         BigInteger ls = gsPlusJs.shiftRight(_k-c);
297         if (gsPlusJs.testBit(_k-c-1))
298         {
299             // round up
300             ls = ls.add(ECConstants.ONE);
301         }
302 
303         return new SimpleBigDecimal(ls, c);
304     }
305 
306     /**
307      * Computes the <code>&tau;</code>-adic NAF (non-adjacent form) of an
308      * element <code>&lambda;</code> of <code><b>Z</b>[&tau;]</code>.
309      * @param mu The parameter <code>&mu;</code> of the elliptic curve.
310      * @param lambda The element <code>&lambda;</code> of
311      * <code><b>Z</b>[&tau;]</code>.
312      * @return The <code>&tau;</code>-adic NAF of <code>&lambda;</code>.
313      */
tauAdicNaf(byte mu, ZTauElement lambda)314     public static byte[] tauAdicNaf(byte mu, ZTauElement lambda)
315     {
316         if (!((mu == 1) || (mu == -1)))
317         {
318             throw new IllegalArgumentException("mu must be 1 or -1");
319         }
320 
321         BigInteger norm = norm(mu, lambda);
322 
323         // Ceiling of log2 of the norm
324         int log2Norm = norm.bitLength();
325 
326         // If length(TNAF) > 30, then length(TNAF) < log2Norm + 3.52
327         int maxLength = log2Norm > 30 ? log2Norm + 4 : 34;
328 
329         // The array holding the TNAF
330         byte[] u = new byte[maxLength];
331         int i = 0;
332 
333         // The actual length of the TNAF
334         int length = 0;
335 
336         BigInteger r0 = lambda.u;
337         BigInteger r1 = lambda.v;
338 
339         while(!((r0.equals(ECConstants.ZERO)) && (r1.equals(ECConstants.ZERO))))
340         {
341             // If r0 is odd
342             if (r0.testBit(0))
343             {
344                 u[i] = (byte) ECConstants.TWO.subtract((r0.subtract(r1.shiftLeft(1))).mod(ECConstants.FOUR)).intValue();
345 
346                 // r0 = r0 - u[i]
347                 if (u[i] == 1)
348                 {
349                     r0 = r0.clearBit(0);
350                 }
351                 else
352                 {
353                     // u[i] == -1
354                     r0 = r0.add(ECConstants.ONE);
355                 }
356                 length = i;
357             }
358             else
359             {
360                 u[i] = 0;
361             }
362 
363             BigInteger t = r0;
364             BigInteger s = r0.shiftRight(1);
365             if (mu == 1)
366             {
367                 r0 = r1.add(s);
368             }
369             else
370             {
371                 // mu == -1
372                 r0 = r1.subtract(s);
373             }
374 
375             r1 = t.shiftRight(1).negate();
376             i++;
377         }
378 
379         length++;
380 
381         // Reduce the TNAF array to its actual length
382         byte[] tnaf = new byte[length];
383         System.arraycopy(u, 0, tnaf, 0, length);
384         return tnaf;
385     }
386 
387     /**
388      * Applies the operation <code>&tau;()</code> to an
389      * <code>ECPoint.AbstractF2m</code>.
390      * @param p The ECPoint.AbstractF2m to which <code>&tau;()</code> is applied.
391      * @return <code>&tau;(p)</code>
392      */
tau(ECPoint.AbstractF2m p)393     public static ECPoint.AbstractF2m tau(ECPoint.AbstractF2m p)
394     {
395         return p.tau();
396     }
397 
398     /**
399      * Returns the parameter <code>&mu;</code> of the elliptic curve.
400      * @param curve The elliptic curve from which to obtain <code>&mu;</code>.
401      * The curve must be a Koblitz curve, i.e. <code>a</code> equals
402      * <code>0</code> or <code>1</code> and <code>b</code> equals
403      * <code>1</code>.
404      * @return <code>&mu;</code> of the elliptic curve.
405      * @throws IllegalArgumentException if the given ECCurve is not a Koblitz
406      * curve.
407      */
getMu(ECCurve.AbstractF2m curve)408     public static byte getMu(ECCurve.AbstractF2m curve)
409     {
410         if (!curve.isKoblitz())
411         {
412             throw new IllegalArgumentException("No Koblitz curve (ABC), TNAF multiplication not possible");
413         }
414 
415         if (curve.getA().isZero())
416         {
417             return -1;
418         }
419 
420         return 1;
421     }
422 
getMu(ECFieldElement curveA)423     public static byte getMu(ECFieldElement curveA)
424     {
425         return (byte)(curveA.isZero() ? -1 : 1);
426     }
427 
getMu(int curveA)428     public static byte getMu(int curveA)
429     {
430         return (byte)(curveA == 0 ? -1 : 1);
431     }
432 
433     /**
434      * Calculates the Lucas Sequence elements <code>U<sub>k-1</sub></code> and
435      * <code>U<sub>k</sub></code> or <code>V<sub>k-1</sub></code> and
436      * <code>V<sub>k</sub></code>.
437      * @param mu The parameter <code>&mu;</code> of the elliptic curve.
438      * @param k The index of the second element of the Lucas Sequence to be
439      * returned.
440      * @param doV If set to true, computes <code>V<sub>k-1</sub></code> and
441      * <code>V<sub>k</sub></code>, otherwise <code>U<sub>k-1</sub></code> and
442      * <code>U<sub>k</sub></code>.
443      * @return An array with 2 elements, containing <code>U<sub>k-1</sub></code>
444      * and <code>U<sub>k</sub></code> or <code>V<sub>k-1</sub></code>
445      * and <code>V<sub>k</sub></code>.
446      */
getLucas(byte mu, int k, boolean doV)447     public static BigInteger[] getLucas(byte mu, int k, boolean doV)
448     {
449         if (!((mu == 1) || (mu == -1)))
450         {
451             throw new IllegalArgumentException("mu must be 1 or -1");
452         }
453 
454         BigInteger u0;
455         BigInteger u1;
456         BigInteger u2;
457 
458         if (doV)
459         {
460             u0 = ECConstants.TWO;
461             u1 = BigInteger.valueOf(mu);
462         }
463         else
464         {
465             u0 = ECConstants.ZERO;
466             u1 = ECConstants.ONE;
467         }
468 
469         for (int i = 1; i < k; i++)
470         {
471             // u2 = mu*u1 - 2*u0;
472             BigInteger s = null;
473             if (mu == 1)
474             {
475                 s = u1;
476             }
477             else
478             {
479                 // mu == -1
480                 s = u1.negate();
481             }
482 
483             u2 = s.subtract(u0.shiftLeft(1));
484             u0 = u1;
485             u1 = u2;
486 //            System.out.println(i + ": " + u2);
487 //            System.out.println();
488         }
489 
490         BigInteger[] retVal = {u0, u1};
491         return retVal;
492     }
493 
494     /**
495      * Computes the auxiliary value <code>t<sub>w</sub></code>. If the width is
496      * 4, then for <code>mu = 1</code>, <code>t<sub>w</sub> = 6</code> and for
497      * <code>mu = -1</code>, <code>t<sub>w</sub> = 10</code>
498      * @param mu The parameter <code>&mu;</code> of the elliptic curve.
499      * @param w The window width of the WTNAF.
500      * @return the auxiliary value <code>t<sub>w</sub></code>
501      */
getTw(byte mu, int w)502     public static BigInteger getTw(byte mu, int w)
503     {
504         if (w == 4)
505         {
506             if (mu == 1)
507             {
508                 return BigInteger.valueOf(6);
509             }
510             else
511             {
512                 // mu == -1
513                 return BigInteger.valueOf(10);
514             }
515         }
516         else
517         {
518             // For w <> 4, the values must be computed
519             BigInteger[] us = getLucas(mu, w, false);
520             BigInteger twoToW = ECConstants.ZERO.setBit(w);
521             BigInteger u1invert = us[1].modInverse(twoToW);
522             BigInteger tw;
523             tw = ECConstants.TWO.multiply(us[0]).multiply(u1invert).mod(twoToW);
524 //            System.out.println("mu = " + mu);
525 //            System.out.println("tw = " + tw);
526             return tw;
527         }
528     }
529 
530     /**
531      * Computes the auxiliary values <code>s<sub>0</sub></code> and
532      * <code>s<sub>1</sub></code> used for partial modular reduction.
533      * @param curve The elliptic curve for which to compute
534      * <code>s<sub>0</sub></code> and <code>s<sub>1</sub></code>.
535      * @throws IllegalArgumentException if <code>curve</code> is not a
536      * Koblitz curve (Anomalous Binary Curve, ABC).
537      */
getSi(ECCurve.AbstractF2m curve)538     public static BigInteger[] getSi(ECCurve.AbstractF2m curve)
539     {
540         if (!curve.isKoblitz())
541         {
542             throw new IllegalArgumentException("si is defined for Koblitz curves only");
543         }
544 
545         int m = curve.getFieldSize();
546         int a = curve.getA().toBigInteger().intValue();
547         byte mu = getMu(a);
548         int shifts = getShiftsForCofactor(curve.getCofactor());
549         int index = m + 3 - a;
550         BigInteger[] ui = getLucas(mu, index, false);
551         if (mu == 1)
552         {
553             ui[0] = ui[0].negate();
554             ui[1] = ui[1].negate();
555         }
556 
557         BigInteger dividend0 = ECConstants.ONE.add(ui[1]).shiftRight(shifts);
558         BigInteger dividend1 = ECConstants.ONE.add(ui[0]).shiftRight(shifts).negate();
559 
560         return new BigInteger[] { dividend0, dividend1 };
561     }
562 
getSi(int fieldSize, int curveA, BigInteger cofactor)563     public static BigInteger[] getSi(int fieldSize, int curveA, BigInteger cofactor)
564     {
565         byte mu = getMu(curveA);
566         int shifts = getShiftsForCofactor(cofactor);
567         int index = fieldSize + 3 - curveA;
568         BigInteger[] ui = getLucas(mu, index, false);
569         if (mu == 1)
570         {
571             ui[0] = ui[0].negate();
572             ui[1] = ui[1].negate();
573         }
574 
575         BigInteger dividend0 = ECConstants.ONE.add(ui[1]).shiftRight(shifts);
576         BigInteger dividend1 = ECConstants.ONE.add(ui[0]).shiftRight(shifts).negate();
577 
578         return new BigInteger[] { dividend0, dividend1 };
579     }
580 
getShiftsForCofactor(BigInteger h)581     protected static int getShiftsForCofactor(BigInteger h)
582     {
583         if (h != null)
584         {
585             if (h.equals(ECConstants.TWO))
586             {
587                 return 1;
588             }
589             if (h.equals(ECConstants.FOUR))
590             {
591                 return 2;
592             }
593         }
594 
595         throw new IllegalArgumentException("h (Cofactor) must be 2 or 4");
596     }
597 
598     /**
599      * Partial modular reduction modulo
600      * <code>(&tau;<sup>m</sup> - 1)/(&tau; - 1)</code>.
601      * @param k The integer to be reduced.
602      * @param m The bitlength of the underlying finite field.
603      * @param a The parameter <code>a</code> of the elliptic curve.
604      * @param s The auxiliary values <code>s<sub>0</sub></code> and
605      * <code>s<sub>1</sub></code>.
606      * @param mu The parameter &mu; of the elliptic curve.
607      * @param c The precision (number of bits of accuracy) of the partial
608      * modular reduction.
609      * @return <code>&rho; := k partmod (&tau;<sup>m</sup> - 1)/(&tau; - 1)</code>
610      */
partModReduction(BigInteger k, int m, byte a, BigInteger[] s, byte mu, byte c)611     public static ZTauElement partModReduction(BigInteger k, int m, byte a,
612             BigInteger[] s, byte mu, byte c)
613     {
614         // d0 = s[0] + mu*s[1]; mu is either 1 or -1
615         BigInteger d0;
616         if (mu == 1)
617         {
618             d0 = s[0].add(s[1]);
619         }
620         else
621         {
622             d0 = s[0].subtract(s[1]);
623         }
624 
625         BigInteger[] v = getLucas(mu, m, true);
626         BigInteger vm = v[1];
627 
628         SimpleBigDecimal lambda0 = approximateDivisionByN(
629                 k, s[0], vm, a, m, c);
630 
631         SimpleBigDecimal lambda1 = approximateDivisionByN(
632                 k, s[1], vm, a, m, c);
633 
634         ZTauElement q = round(lambda0, lambda1, mu);
635 
636         // r0 = n - d0*q0 - 2*s1*q1
637         BigInteger r0 = k.subtract(d0.multiply(q.u)).subtract(
638                 BigInteger.valueOf(2).multiply(s[1]).multiply(q.v));
639 
640         // r1 = s1*q0 - s0*q1
641         BigInteger r1 = s[1].multiply(q.u).subtract(s[0].multiply(q.v));
642 
643         return new ZTauElement(r0, r1);
644     }
645 
646     /**
647      * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.AbstractF2m ECPoint.AbstractF2m}
648      * by a <code>BigInteger</code> using the reduced <code>&tau;</code>-adic
649      * NAF (RTNAF) method.
650      * @param p The ECPoint.AbstractF2m to multiply.
651      * @param k The <code>BigInteger</code> by which to multiply <code>p</code>.
652      * @return <code>k * p</code>
653      */
multiplyRTnaf(ECPoint.AbstractF2m p, BigInteger k)654     public static ECPoint.AbstractF2m multiplyRTnaf(ECPoint.AbstractF2m p, BigInteger k)
655     {
656         ECCurve.AbstractF2m curve = (ECCurve.AbstractF2m) p.getCurve();
657         int m = curve.getFieldSize();
658         int a = curve.getA().toBigInteger().intValue();
659         byte mu = getMu(a);
660         BigInteger[] s = curve.getSi();
661         ZTauElement rho = partModReduction(k, m, (byte)a, s, mu, (byte)10);
662 
663         return multiplyTnaf(p, rho);
664     }
665 
666     /**
667      * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.AbstractF2m ECPoint.AbstractF2m}
668      * by an element <code>&lambda;</code> of <code><b>Z</b>[&tau;]</code>
669      * using the <code>&tau;</code>-adic NAF (TNAF) method.
670      * @param p The ECPoint.AbstractF2m to multiply.
671      * @param lambda The element <code>&lambda;</code> of
672      * <code><b>Z</b>[&tau;]</code>.
673      * @return <code>&lambda; * p</code>
674      */
multiplyTnaf(ECPoint.AbstractF2m p, ZTauElement lambda)675     public static ECPoint.AbstractF2m multiplyTnaf(ECPoint.AbstractF2m p, ZTauElement lambda)
676     {
677         ECCurve.AbstractF2m curve = (ECCurve.AbstractF2m)p.getCurve();
678         byte mu = getMu(curve.getA());
679         byte[] u = tauAdicNaf(mu, lambda);
680 
681         ECPoint.AbstractF2m q = multiplyFromTnaf(p, u);
682 
683         return q;
684     }
685 
686     /**
687     * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.AbstractF2m ECPoint.AbstractF2m}
688     * by an element <code>&lambda;</code> of <code><b>Z</b>[&tau;]</code>
689     * using the <code>&tau;</code>-adic NAF (TNAF) method, given the TNAF
690     * of <code>&lambda;</code>.
691     * @param p The ECPoint.AbstractF2m to multiply.
692     * @param u The the TNAF of <code>&lambda;</code>..
693     * @return <code>&lambda; * p</code>
694     */
multiplyFromTnaf(ECPoint.AbstractF2m p, byte[] u)695     public static ECPoint.AbstractF2m multiplyFromTnaf(ECPoint.AbstractF2m p, byte[] u)
696     {
697         ECCurve curve = p.getCurve();
698         ECPoint.AbstractF2m q = (ECPoint.AbstractF2m)curve.getInfinity();
699         ECPoint.AbstractF2m pNeg = (ECPoint.AbstractF2m)p.negate();
700         int tauCount = 0;
701         for (int i = u.length - 1; i >= 0; i--)
702         {
703             ++tauCount;
704             byte ui = u[i];
705             if (ui != 0)
706             {
707                 q = q.tauPow(tauCount);
708                 tauCount = 0;
709 
710                 ECPoint x = ui > 0 ? p : pNeg;
711                 q = (ECPoint.AbstractF2m)q.add(x);
712             }
713         }
714         if (tauCount > 0)
715         {
716             q = q.tauPow(tauCount);
717         }
718         return q;
719     }
720 
721     /**
722      * Computes the <code>[&tau;]</code>-adic window NAF of an element
723      * <code>&lambda;</code> of <code><b>Z</b>[&tau;]</code>.
724      * @param mu The parameter &mu; of the elliptic curve.
725      * @param lambda The element <code>&lambda;</code> of
726      * <code><b>Z</b>[&tau;]</code> of which to compute the
727      * <code>[&tau;]</code>-adic NAF.
728      * @param width The window width of the resulting WNAF.
729      * @param pow2w 2<sup>width</sup>.
730      * @param tw The auxiliary value <code>t<sub>w</sub></code>.
731      * @param alpha The <code>&alpha;<sub>u</sub></code>'s for the window width.
732      * @return The <code>[&tau;]</code>-adic window NAF of
733      * <code>&lambda;</code>.
734      */
tauAdicWNaf(byte mu, ZTauElement lambda, byte width, BigInteger pow2w, BigInteger tw, ZTauElement[] alpha)735     public static byte[] tauAdicWNaf(byte mu, ZTauElement lambda,
736             byte width, BigInteger pow2w, BigInteger tw, ZTauElement[] alpha)
737     {
738         if (!((mu == 1) || (mu == -1)))
739         {
740             throw new IllegalArgumentException("mu must be 1 or -1");
741         }
742 
743         BigInteger norm = norm(mu, lambda);
744 
745         // Ceiling of log2 of the norm
746         int log2Norm = norm.bitLength();
747 
748         // If length(TNAF) > 30, then length(TNAF) < log2Norm + 3.52
749         int maxLength = log2Norm > 30 ? log2Norm + 4 + width : 34 + width;
750 
751         // The array holding the TNAF
752         byte[] u = new byte[maxLength];
753 
754         // 2^(width - 1)
755         BigInteger pow2wMin1 = pow2w.shiftRight(1);
756 
757         // Split lambda into two BigIntegers to simplify calculations
758         BigInteger r0 = lambda.u;
759         BigInteger r1 = lambda.v;
760         int i = 0;
761 
762         // while lambda <> (0, 0)
763         while (!((r0.equals(ECConstants.ZERO))&&(r1.equals(ECConstants.ZERO))))
764         {
765             // if r0 is odd
766             if (r0.testBit(0))
767             {
768                 // uUnMod = r0 + r1*tw mod 2^width
769                 BigInteger uUnMod
770                     = r0.add(r1.multiply(tw)).mod(pow2w);
771 
772                 byte uLocal;
773                 // if uUnMod >= 2^(width - 1)
774                 if (uUnMod.compareTo(pow2wMin1) >= 0)
775                 {
776                     uLocal = (byte) uUnMod.subtract(pow2w).intValue();
777                 }
778                 else
779                 {
780                     uLocal = (byte) uUnMod.intValue();
781                 }
782                 // uLocal is now in [-2^(width-1), 2^(width-1)-1]
783 
784                 u[i] = uLocal;
785                 boolean s = true;
786                 if (uLocal < 0)
787                 {
788                     s = false;
789                     uLocal = (byte)-uLocal;
790                 }
791                 // uLocal is now >= 0
792 
793                 if (s)
794                 {
795                     r0 = r0.subtract(alpha[uLocal].u);
796                     r1 = r1.subtract(alpha[uLocal].v);
797                 }
798                 else
799                 {
800                     r0 = r0.add(alpha[uLocal].u);
801                     r1 = r1.add(alpha[uLocal].v);
802                 }
803             }
804             else
805             {
806                 u[i] = 0;
807             }
808 
809             BigInteger t = r0;
810 
811             if (mu == 1)
812             {
813                 r0 = r1.add(r0.shiftRight(1));
814             }
815             else
816             {
817                 // mu == -1
818                 r0 = r1.subtract(r0.shiftRight(1));
819             }
820             r1 = t.shiftRight(1).negate();
821             i++;
822         }
823         return u;
824     }
825 
826     /**
827      * Does the precomputation for WTNAF multiplication.
828      * @param p The <code>ECPoint</code> for which to do the precomputation.
829      * @param a The parameter <code>a</code> of the elliptic curve.
830      * @return The precomputation array for <code>p</code>.
831      */
getPreComp(ECPoint.AbstractF2m p, byte a)832     public static ECPoint.AbstractF2m[] getPreComp(ECPoint.AbstractF2m p, byte a)
833     {
834         byte[][] alphaTnaf = (a == 0) ? Tnaf.alpha0Tnaf : Tnaf.alpha1Tnaf;
835 
836         ECPoint.AbstractF2m[] pu = new ECPoint.AbstractF2m[(alphaTnaf.length + 1) >>> 1];
837         pu[0] = p;
838 
839         int precompLen = alphaTnaf.length;
840         for (int i = 3; i < precompLen; i += 2)
841         {
842             pu[i >>> 1] = Tnaf.multiplyFromTnaf(p, alphaTnaf[i]);
843         }
844 
845         p.getCurve().normalizeAll(pu);
846 
847         return pu;
848     }
849 }
850