private static ECPoint ImplShamirsTrick(ECPoint P, BigInteger k, ECPoint Q, BigInteger l) { int m = System.Math.Max(k.BitLength, l.BitLength); ECPoint Z = P.Add(Q); ECPoint R = P.Curve.Infinity; for (int i = m - 1; i >= 0; --i) { R = R.Twice(); if (k.TestBit(i)) { if (l.TestBit(i)) { R = R.Add(Z); } else { R = R.Add(P); } } else { if (l.TestBit(i)) { R = R.Add(Q); } } } return R; }
/** * Computes the Window NAF (non-adjacent Form) of an integer. * @param width The width <code>w</code> of the Window NAF. The width is * defined as the minimal number <code>w</code>, such that for any * <code>w</code> consecutive digits in the resulting representation, at * most one is non-zero. * @param k The integer of which the Window NAF is computed. * @return The Window NAF of the given width, such that the following holds: * <code>k = −<sub>i=0</sub><sup>l-1</sup> k<sub>i</sub>2<sup>i</sup> * </code>, where the <code>k<sub>i</sub></code> denote the elements of the * returned <code>sbyte[]</code>. */ public sbyte[] WindowNaf(sbyte width, BigInteger k) { // The window NAF is at most 1 element longer than the binary // representation of the integer k. sbyte can be used instead of short or // int unless the window width is larger than 8. For larger width use // short or int. However, a width of more than 8 is not efficient for // m = log2(q) smaller than 2305 Bits. Note: Values for m larger than // 1000 Bits are currently not used in practice. sbyte[] wnaf = new sbyte[k.BitLength + 1]; // 2^width as short and BigInteger short pow2wB = (short)(1 << width); BigInteger pow2wBI = BigInteger.ValueOf(pow2wB); int i = 0; // The actual length of the WNAF int length = 0; // while k >= 1 while (k.SignValue > 0) { // if k is odd if (k.TestBit(0)) { // k Mod 2^width BigInteger remainder = k.Mod(pow2wBI); // if remainder > 2^(width - 1) - 1 if (remainder.TestBit(width - 1)) { wnaf[i] = (sbyte)(remainder.IntValue - pow2wB); } else { wnaf[i] = (sbyte)remainder.IntValue; } // wnaf[i] is now in [-2^(width-1), 2^(width-1)-1] k = k.Subtract(BigInteger.ValueOf(wnaf[i])); length = i; } else { wnaf[i] = 0; } // k = k/2 k = k.ShiftRight(1); i++; } length++; // Reduce the WNAF array to its actual length sbyte[] wnafShort = new sbyte[length]; Array.Copy(wnaf, 0, wnafShort, 0, length); return wnafShort; }
// private static BigInteger W(BigInteger n, BigInteger wOne, BigInteger p) // { // if (n.Equals(BigInteger.One)) // return wOne; // // bool isEven = !n.TestBit(0); // n = n.ShiftRight(1); // if (isEven) // { // BigInteger w = W(n, wOne, p); // return w.Multiply(w).Subtract(BigInteger.Two).Mod(p); // } // BigInteger w1 = W(n.Add(BigInteger.One), wOne, p); // BigInteger w2 = W(n, wOne, p); // return w1.Multiply(w2).Subtract(wOne).Mod(p); // } // // private BigInteger WOne(BigInteger r, BigInteger x, BigInteger p) // { // return r.Multiply(r).Multiply(x.ModPow(q.Subtract(BigInteger.Two), q)).Subtract(BigInteger.Two).Mod(p); // } private static BigInteger[] fastLucasSequence( BigInteger p, BigInteger P, BigInteger Q, BigInteger k) { // TODO Research and apply "common-multiplicand multiplication here" int n = k.BitLength; int s = k.GetLowestSetBit(); Debug.Assert(k.TestBit(s)); BigInteger Uh = BigInteger.One; BigInteger Vl = BigInteger.Two; BigInteger Vh = P; BigInteger Ql = BigInteger.One; BigInteger Qh = BigInteger.One; for (int j = n - 1; j >= s + 1; --j) { Ql = Ql.Multiply(Qh).Mod(p); if (k.TestBit(j)) { Qh = Ql.Multiply(Q).Mod(p); Uh = Uh.Multiply(Vh).Mod(p); Vl = Vh.Multiply(Vl).Subtract(P.Multiply(Ql)).Mod(p); Vh = Vh.Multiply(Vh).Subtract(Qh.ShiftLeft(1)).Mod(p); } else { Qh = Ql; Uh = Uh.Multiply(Vl).Subtract(Ql).Mod(p); Vh = Vh.Multiply(Vl).Subtract(P.Multiply(Ql)).Mod(p); Vl = Vl.Multiply(Vl).Subtract(Ql.ShiftLeft(1)).Mod(p); } } Ql = Ql.Multiply(Qh).Mod(p); Qh = Ql.Multiply(Q).Mod(p); Uh = Uh.Multiply(Vl).Subtract(Ql).Mod(p); Vl = Vh.Multiply(Vl).Subtract(P.Multiply(Ql)).Mod(p); Ql = Ql.Multiply(Qh).Mod(p); for (int j = 1; j <= s; ++j) { Uh = Uh.Multiply(Vl).Mod(p); Vl = Vl.Multiply(Vl).Subtract(Ql.ShiftLeft(1)).Mod(p); Ql = Ql.Multiply(Ql).Mod(p); } return new BigInteger[]{ Uh, Vl }; }