private bool CheckExisting(WNafPreCompInfo existingWNaf, int reqPreCompLen, bool includeNegated) { return(existingWNaf != null && CheckTable(existingWNaf.PreComp, reqPreCompLen) && (!includeNegated || CheckTable(existingWNaf.PreCompNeg, reqPreCompLen))); }
internal MapPointCallback(WNafPreCompInfo wnafPreCompP, bool includeNegated, ECPointMap pointMap) { this.m_wnafPreCompP = wnafPreCompP; this.m_includeNegated = includeNegated; this.m_pointMap = pointMap; }
public PreCompInfo Precompute(PreCompInfo existing) { WNafPreCompInfo existingWNaf = existing as WNafPreCompInfo; int reqPreCompLen = 1 << System.Math.Max(0, m_width - 2); if (CheckExisting(existingWNaf, reqPreCompLen, m_includeNegated)) { return(existingWNaf); } ECCurve c = m_p.Curve; ECPoint[] preComp = null, preCompNeg = null; ECPoint twiceP = null; if (existingWNaf != null) { preComp = existingWNaf.PreComp; preCompNeg = existingWNaf.PreCompNeg; twiceP = existingWNaf.Twice; } int iniPreCompLen = 0; if (preComp == null) { preComp = EMPTY_POINTS; } else { iniPreCompLen = preComp.Length; } if (iniPreCompLen < reqPreCompLen) { preComp = WNafUtilities.ResizeTable(preComp, reqPreCompLen); if (reqPreCompLen == 1) { preComp[0] = m_p.Normalize(); } else { int curPreCompLen = iniPreCompLen; if (curPreCompLen == 0) { preComp[0] = m_p; curPreCompLen = 1; } ECFieldElement iso = null; if (reqPreCompLen == 2) { preComp[1] = m_p.ThreeTimes(); } else { ECPoint isoTwiceP = twiceP, last = preComp[curPreCompLen - 1]; if (isoTwiceP == null) { isoTwiceP = preComp[0].Twice(); twiceP = isoTwiceP; /* * For Fp curves with Jacobian projective coordinates, use a (quasi-)isomorphism * where 'twiceP' is "affine", so that the subsequent additions are cheaper. This * also requires scaling the initial point's X, Y coordinates, and reversing the * isomorphism as part of the subsequent normalization. * * NOTE: The correctness of this optimization depends on: * 1) additions do not use the curve's A, B coefficients. * 2) no special cases (i.e. Q +/- Q) when calculating 1P, 3P, 5P, ... */ if (!twiceP.IsInfinity && ECAlgorithms.IsFpCurve(c) && c.FieldSize >= 64) { switch (c.CoordinateSystem) { case ECCurve.COORD_JACOBIAN: case ECCurve.COORD_JACOBIAN_CHUDNOVSKY: case ECCurve.COORD_JACOBIAN_MODIFIED: { iso = twiceP.GetZCoord(0); isoTwiceP = c.CreatePoint(twiceP.XCoord.ToBigInteger(), twiceP.YCoord.ToBigInteger()); ECFieldElement iso2 = iso.Square(), iso3 = iso2.Multiply(iso); last = last.ScaleX(iso2).ScaleY(iso3); if (iniPreCompLen == 0) { preComp[0] = last; } break; } } } } while (curPreCompLen < reqPreCompLen) { /* * Compute the new ECPoints for the precomputation array. The values 1, 3, * 5, ..., 2^(width-1)-1 times p are computed */ preComp[curPreCompLen++] = last = last.Add(isoTwiceP); } } /* * Having oft-used operands in affine form makes operations faster. */ c.NormalizeAll(preComp, iniPreCompLen, reqPreCompLen - iniPreCompLen, iso); } } if (m_includeNegated) { int pos; if (preCompNeg == null) { pos = 0; preCompNeg = new ECPoint[reqPreCompLen]; } else { pos = preCompNeg.Length; if (pos < reqPreCompLen) { preCompNeg = WNafUtilities.ResizeTable(preCompNeg, reqPreCompLen); } } while (pos < reqPreCompLen) { preCompNeg[pos] = preComp[pos].Negate(); ++pos; } } WNafPreCompInfo result = new WNafPreCompInfo(); result.PreComp = preComp; result.PreCompNeg = preCompNeg; result.Twice = twiceP; return(result); }
/** * 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>. */ protected override ECPoint MultiplyPositive(ECPoint p, BigInteger k) { // Clamp the window width in the range [2, 16] int width = System.Math.Max(2, System.Math.Min(16, GetWindowSize(k.BitLength))); WNafPreCompInfo wnafPreCompInfo = WNafUtilities.Precompute(p, width, true); ECPoint[] preComp = wnafPreCompInfo.PreComp; ECPoint[] preCompNeg = wnafPreCompInfo.PreCompNeg; int[] wnaf = WNafUtilities.GenerateCompactWindowNaf(width, k); ECPoint R = p.Curve.Infinity; int i = wnaf.Length; /* * NOTE: We try to optimize the first window using the precomputed points to substitute an * addition for 2 or more doublings. */ if (i > 1) { int wi = wnaf[--i]; int digit = wi >> 16, zeroes = wi & 0xFFFF; int n = System.Math.Abs(digit); ECPoint[] table = digit < 0 ? preCompNeg : preComp; // Optimization can only be used for values in the lower half of the table if ((n << 2) < (1 << width)) { int highest = LongArray.BitLengths[n]; // TODO Get addition/doubling cost ratio from curve and compare to 'scale' to see if worth substituting? int scale = width - highest; int lowBits = n ^ (1 << (highest - 1)); int i1 = ((1 << (width - 1)) - 1); int i2 = (lowBits << scale) + 1; R = table[i1 >> 1].Add(table[i2 >> 1]); zeroes -= scale; //Console.WriteLine("Optimized: 2^" + scale + " * " + n + " = " + i1 + " + " + i2); } else { R = table[n >> 1]; } R = R.TimesPow2(zeroes); } while (i > 0) { int wi = wnaf[--i]; int digit = wi >> 16, zeroes = wi & 0xFFFF; int n = System.Math.Abs(digit); ECPoint[] table = digit < 0 ? preCompNeg : preComp; ECPoint r = table[n >> 1]; R = R.TwicePlus(r); R = R.TimesPow2(zeroes); } return(R); }