public PreCompInfo Precompute(PreCompInfo existing) { WNafPreCompInfo existingWNaf = existing as WNafPreCompInfo; int width = m_fromWNaf.Width; int reqPreCompLen = m_fromWNaf.PreComp.Length; if (CheckExisting(existingWNaf, width, reqPreCompLen, m_includeNegated)) { existingWNaf.DecrementPromotionCountdown(); return(existingWNaf); } /* * TODO Ideally this method would support incremental calculation, but given the * existing use-cases it would be of little-to-no benefit. */ WNafPreCompInfo result = new WNafPreCompInfo(); result.PromotionCountdown = m_fromWNaf.PromotionCountdown; ECPoint twiceFrom = m_fromWNaf.Twice; if (null != twiceFrom) { ECPoint twice = m_pointMap.Map(twiceFrom); result.Twice = twice; } ECPoint[] preCompFrom = m_fromWNaf.PreComp; ECPoint[] preComp = new ECPoint[preCompFrom.Length]; for (int i = 0; i < preCompFrom.Length; ++i) { preComp[i] = m_pointMap.Map(preCompFrom[i]); } result.PreComp = preComp; result.Width = width; if (m_includeNegated) { ECPoint[] preCompNeg = new ECPoint[preComp.Length]; for (int i = 0; i < preCompNeg.Length; ++i) { preCompNeg[i] = preComp[i].Negate(); } result.PreCompNeg = preCompNeg; } return(result); }
public PreCompInfo Precompute(PreCompInfo existing) { WNafPreCompInfo existingWNaf = existing as WNafPreCompInfo; int width = System.Math.Max(2, System.Math.Min(MAX_WIDTH, m_minWidth)); int reqPreCompLen = 1 << (width - 2); if (CheckExisting(existingWNaf, width, reqPreCompLen, m_includeNegated)) { existingWNaf.DecrementPromotionCountdown(); return(existingWNaf); } WNafPreCompInfo result = new WNafPreCompInfo(); ECCurve c = m_p.Curve; ECPoint[] preComp = null, preCompNeg = null; ECPoint twiceP = null; if (null != existingWNaf) { int promotionCountdown = existingWNaf.DecrementPromotionCountdown(); result.PromotionCountdown = promotionCountdown; int confWidth = existingWNaf.ConfWidth; result.ConfWidth = confWidth; preComp = existingWNaf.PreComp; preCompNeg = existingWNaf.PreCompNeg; twiceP = existingWNaf.Twice; } width = System.Math.Min(MAX_WIDTH, System.Math.Max(result.ConfWidth, width)); reqPreCompLen = 1 << (width - 2); int iniPreCompLen = 0; if (null == preComp) { 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 (null == isoTwiceP) { 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 (null == preCompNeg) { 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; } } result.PreComp = preComp; result.PreCompNeg = preCompNeg; result.Twice = twiceP; result.Width = width; return(result); }