/** * Simple shift-and-add multiplication. Serves as reference implementation * to verify (possibly faster) implementations, and for very small scalars. * * @param p * The point to multiply. * @param k * The multiplier. * @return The result of the point multiplication <code>kP</code>. */ public static ECPoint ReferenceMultiply(ECPoint p, BigInteger k) { BigInteger x = k.Abs(); ECPoint q = p.Curve.Infinity; int t = x.BitLength; if (t > 0) { if (x.TestBit(0)) { q = p; } for (int i = 1; i < t; i++) { p = p.Twice(); if (x.TestBit(i)) { q = q.Add(p); } } } return k.SignValue < 0 ? q.Negate() : q; }
public override ECPoint TwicePlus(ECPoint b) { if (this.IsInfinity) return b; if (b.IsInfinity) return Twice(); ECCurve curve = this.Curve; ECFieldElement X1 = this.RawXCoord; if (X1.IsZero) { // A point with X == 0 is it's own additive inverse return b; } int coord = curve.CoordinateSystem; switch (coord) { case ECCurve.COORD_LAMBDA_PROJECTIVE: { // NOTE: twicePlus() only optimized for lambda-affine argument ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0]; if (X2.IsZero || !Z2.IsOne) { return Twice().Add(b); } ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; ECFieldElement L2 = b.RawYCoord; ECFieldElement X1Sq = X1.Square(); ECFieldElement L1Sq = L1.Square(); ECFieldElement Z1Sq = Z1.Square(); ECFieldElement L1Z1 = L1.Multiply(Z1); ECFieldElement T = curve.A.Multiply(Z1Sq).Add(L1Sq).Add(L1Z1); ECFieldElement L2plus1 = L2.AddOne(); ECFieldElement A = curve.A.Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq); ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq); ECFieldElement B = X2Z1Sq.Add(T).Square(); if (B.IsZero) { if (A.IsZero) { return b.Twice(); } return curve.Infinity; } if (A.IsZero) { return new F2mPoint(curve, A, curve.B.Sqrt(), IsCompressed); } ECFieldElement X3 = A.Square().Multiply(X2Z1Sq); ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq); ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3); return new F2mPoint(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); } default: { return Twice().Add(b); } } }