diff --git a/crypto/src/math/ec/ECPoint.cs b/crypto/src/math/ec/ECPoint.cs
index e4ce58d2d..d81558939 100644
--- a/crypto/src/math/ec/ECPoint.cs
+++ b/crypto/src/math/ec/ECPoint.cs
@@ -128,6 +128,16 @@ namespace Org.BouncyCastle.Math.EC
public abstract ECPoint Twice();
public abstract ECPoint Multiply(BigInteger b);
+ public virtual ECPoint TwicePlus(ECPoint b)
+ {
+ return Twice().Add(b);
+ }
+
+ public virtual ECPoint ThreeTimes()
+ {
+ return TwicePlus(this);
+ }
+
/**
* Sets the appropriate <code>ECMultiplier</code>, unless already set.
*/
@@ -139,7 +149,7 @@ namespace Org.BouncyCastle.Math.EC
{
if (this.multiplier == null)
{
- this.multiplier = new FpNafMultiplier();
+ this.multiplier = new WNafMultiplier();
}
}
}
@@ -270,54 +280,184 @@ namespace Org.BouncyCastle.Math.EC
ECPoint b)
{
if (this.IsInfinity)
+ {
return b;
-
+ }
if (b.IsInfinity)
+ {
return this;
+ }
+ if (this == b)
+ {
+ return Twice();
+ }
+
+ ECFieldElement X1 = this.x, Y1 = this.y;
+ ECFieldElement X2 = b.x, Y2 = b.y;
- // Check if b = this or b = -this
- if (this.x.Equals(b.x))
+ ECFieldElement dx = X2.Subtract(X1), dy = Y2.Subtract(Y1);
+
+ if (dx.IsZero)
{
- if (this.y.Equals(b.y))
+ if (dy.IsZero)
{
- // this = b, i.e. this must be doubled
- return this.Twice();
+ // this == b, i.e. this must be doubled
+ return Twice();
}
- Debug.Assert(this.y.Equals(b.y.Negate()));
-
- // this = -b, i.e. the result is the point at infinity
- return this.curve.Infinity;
+ // this == -b, i.e. the result is the point at infinity
+ return curve.Infinity;
}
- ECFieldElement gamma = b.y.Subtract(this.y).Divide(b.x.Subtract(this.x));
-
- ECFieldElement x3 = gamma.Square().Subtract(this.x).Subtract(b.x);
- ECFieldElement y3 = gamma.Multiply(this.x.Subtract(x3)).Subtract(this.y);
+ ECFieldElement gamma = dy.Divide(dx);
+ ECFieldElement X3 = gamma.Square().Subtract(X1).Subtract(X2);
+ ECFieldElement Y3 = gamma.Multiply(X1.Subtract(X3)).Subtract(Y1);
- return new FpPoint(curve, x3, y3, withCompression);
+ return new FpPoint(curve, X3, Y3, this.withCompression);
}
// B.3 pg 62
public override ECPoint Twice()
{
- // Twice identity element (point at infinity) is identity
if (this.IsInfinity)
+ {
return this;
+ }
- // if y1 == 0, then (x1, y1) == (x1, -y1)
- // and hence this = -this and thus 2(x1, y1) == infinity
- if (this.y.ToBigInteger().SignValue == 0)
- return this.curve.Infinity;
+ ECFieldElement Y1 = this.y;
+ if (Y1.IsZero)
+ {
+ return curve.Infinity;
+ }
- ECFieldElement TWO = this.curve.FromBigInteger(BigInteger.Two);
- ECFieldElement THREE = this.curve.FromBigInteger(BigInteger.Three);
- ECFieldElement gamma = this.x.Square().Multiply(THREE).Add(curve.a).Divide(y.Multiply(TWO));
+ ECFieldElement X1 = this.x;
- ECFieldElement x3 = gamma.Square().Subtract(this.x.Multiply(TWO));
- ECFieldElement y3 = gamma.Multiply(this.x.Subtract(x3)).Subtract(this.y);
+ ECFieldElement X1Squared = X1.Square();
+ ECFieldElement gamma = Three(X1Squared).Add(this.Curve.A).Divide(Two(Y1));
+ ECFieldElement X3 = gamma.Square().Subtract(Two(X1));
+ ECFieldElement Y3 = gamma.Multiply(X1.Subtract(X3)).Subtract(Y1);
- return new FpPoint(curve, x3, y3, this.withCompression);
+ return new FpPoint(curve, X3, Y3, this.withCompression);
+ }
+
+ public override ECPoint TwicePlus(ECPoint b)
+ {
+ if (this == b)
+ {
+ return ThreeTimes();
+ }
+ if (this.IsInfinity)
+ {
+ return b;
+ }
+ if (b.IsInfinity)
+ {
+ return Twice();
+ }
+
+ ECFieldElement Y1 = this.y;
+ if (Y1.IsZero)
+ {
+ return b;
+ }
+
+ ECFieldElement X1 = this.x;
+ ECFieldElement X2 = b.x, Y2 = b.y;
+
+ ECFieldElement dx = X2.Subtract(X1), dy = Y2.Subtract(Y1);
+
+ if (dx.IsZero)
+ {
+ if (dy.IsZero)
+ {
+ // this == b i.e. the result is 3P
+ return ThreeTimes();
+ }
+
+ // this == -b, i.e. the result is P
+ return this;
+ }
+
+ /*
+ * Optimized calculation of 2P + Q, as described in "Trading Inversions for
+ * Multiplications in Elliptic Curve Cryptography", by Ciet, Joye, Lauter, Montgomery.
+ */
+
+ ECFieldElement X = dx.Square(), Y = dy.Square();
+ ECFieldElement d = X.Multiply(Two(X1).Add(X2)).Subtract(Y);
+ if (d.IsZero)
+ {
+ return curve.Infinity;
+ }
+
+ ECFieldElement D = d.Multiply(dx);
+ ECFieldElement I = D.Invert();
+ ECFieldElement L1 = d.Multiply(I).Multiply(dy);
+ ECFieldElement L2 = Two(Y1).Multiply(X).Multiply(dx).Multiply(I).Subtract(L1);
+ ECFieldElement X4 = (L2.Subtract(L1)).Multiply(L1.Add(L2)).Add(X2);
+ ECFieldElement Y4 = (X1.Subtract(X4)).Multiply(L2).Subtract(Y1);
+
+ return new FpPoint(curve, X4, Y4, this.withCompression);
+ }
+
+ public override ECPoint ThreeTimes()
+ {
+ if (this.IsInfinity || this.y.IsZero)
+ {
+ return this;
+ }
+
+ ECFieldElement X1 = this.x, Y1 = this.y;
+
+ ECFieldElement _2Y1 = Two(Y1);
+ ECFieldElement X = _2Y1.Square();
+ ECFieldElement Z = Three(X1.Square()).Add(this.Curve.A);
+ ECFieldElement Y = Z.Square();
+
+ ECFieldElement d = Three(X1).Multiply(X).Subtract(Y);
+ if (d.IsZero)
+ {
+ return this.Curve.Infinity;
+ }
+
+ ECFieldElement D = d.Multiply(_2Y1);
+ ECFieldElement I = D.Invert();
+ ECFieldElement L1 = d.Multiply(I).Multiply(Z);
+ ECFieldElement L2 = X.Square().Multiply(I).Subtract(L1);
+
+ ECFieldElement X4 = (L2.Subtract(L1)).Multiply(L1.Add(L2)).Add(X1);
+ ECFieldElement Y4 = (X1.Subtract(X4)).Multiply(L2).Subtract(Y1);
+ return new FpPoint(curve, X4, Y4, this.withCompression);
+ }
+
+ protected virtual ECFieldElement Two(ECFieldElement x)
+ {
+ return x.Add(x);
+ }
+
+ protected virtual ECFieldElement Three(ECFieldElement x)
+ {
+ return Two(x).Add(x);
+ }
+
+ protected virtual ECFieldElement Four(ECFieldElement x)
+ {
+ return Two(Two(x));
+ }
+
+ protected virtual ECFieldElement Eight(ECFieldElement x)
+ {
+ return Four(Two(x));
+ }
+
+ protected virtual ECFieldElement DoubleProductFromSquares(ECFieldElement a, ECFieldElement b,
+ ECFieldElement aSquared, ECFieldElement bSquared)
+ {
+ /*
+ * NOTE: If squaring in the field is faster than multiplication, then this is a quicker
+ * way to calculate 2.A.B, if A^2 and B^2 are already known.
+ */
+ return a.Add(b).Square().Subtract(aSquared).Subtract(bSquared);
}
// D.3.2 pg 102 (see Note:)
@@ -335,23 +475,6 @@ namespace Org.BouncyCastle.Math.EC
{
return new FpPoint(this.curve, this.x, this.y.Negate(), this.withCompression);
}
-
- /**
- * Sets the default <code>ECMultiplier</code>, unless already set.
- */
- internal override void AssertECMultiplier()
- {
- if (this.multiplier == null)
- {
- lock (this)
- {
- if (this.multiplier == null)
- {
- this.multiplier = new WNafMultiplier();
- }
- }
- }
- }
}
/**
|