Home | History | Annotate | Download | only in ec
      1 package org.bouncycastle.math.ec;
      2 
      3 import java.math.BigInteger;
      4 
      5 /**
      6  * Class implementing the WTNAF (Window
      7  * <code>&tau;</code>-adic Non-Adjacent Form) algorithm.
      8  */
      9 class 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