diff --git a/crypto/src/math/ec/ECCurve.cs b/crypto/src/math/ec/ECCurve.cs
index 339d37f7c..9fe9e32fd 100644
--- a/crypto/src/math/ec/ECCurve.cs
+++ b/crypto/src/math/ec/ECCurve.cs
@@ -623,6 +623,18 @@ namespace Org.BouncyCastle.Math.EC
public abstract class AbstractF2mCurve
: ECCurve
{
+ public static BigInteger Inverse(int m, int[] ks, BigInteger x)
+ {
+ return new LongArray(x).ModInverse(m, ks).ToBigInteger();
+ }
+
+ /**
+ * The auxiliary values <code>s<sub>0</sub></code> and
+ * <code>s<sub>1</sub></code> used for partial modular reduction for
+ * Koblitz curves.
+ */
+ private BigInteger[] si = null;
+
private static IFiniteField BuildField(int m, int k1, int k2, int k3)
{
if (k1 == 0)
@@ -657,6 +669,69 @@ namespace Org.BouncyCastle.Math.EC
: base(BuildField(m, k1, k2, k3))
{
}
+
+ [Obsolete("Per-point compression property will be removed")]
+ public override ECPoint CreatePoint(BigInteger x, BigInteger y, bool withCompression)
+ {
+ ECFieldElement X = FromBigInteger(x), Y = FromBigInteger(y);
+
+ switch (this.CoordinateSystem)
+ {
+ case COORD_LAMBDA_AFFINE:
+ case COORD_LAMBDA_PROJECTIVE:
+ {
+ if (X.IsZero)
+ {
+ if (!Y.Square().Equals(B))
+ throw new ArgumentException();
+ }
+ else
+ {
+ // Y becomes Lambda (X + Y/X) here
+ Y = Y.Divide(X).Add(X);
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ return CreateRawPoint(X, Y, withCompression);
+ }
+
+ /**
+ * @return the auxiliary values <code>s<sub>0</sub></code> and
+ * <code>s<sub>1</sub></code> used for partial modular reduction for
+ * Koblitz curves.
+ */
+ internal virtual BigInteger[] GetSi()
+ {
+ if (si == null)
+ {
+ lock (this)
+ {
+ if (si == null)
+ {
+ si = Tnaf.GetSi(this);
+ }
+ }
+ }
+ return si;
+ }
+
+ /**
+ * Returns true if this is a Koblitz curve (ABC curve).
+ * @return true if this is a Koblitz curve (ABC curve), false otherwise
+ */
+ public virtual bool IsKoblitz
+ {
+ get
+ {
+ return m_order != null && m_cofactor != null && m_b.IsOne && (m_a.IsZero || m_a.IsOne);
+ }
+ }
}
/**
@@ -705,19 +780,6 @@ namespace Org.BouncyCastle.Math.EC
protected readonly F2mPoint m_infinity;
/**
- * The parameter <code>μ</code> of the elliptic curve if this is
- * a Koblitz curve.
- */
- private sbyte mu = 0;
-
- /**
- * The auxiliary values <code>s<sub>0</sub></code> and
- * <code>s<sub>1</sub></code> used for partial modular reduction for
- * Koblitz curves.
- */
- private BigInteger[] si = null;
-
- /**
* Constructor for Trinomial Polynomial Basis (TPB).
* @param m The exponent <code>m</code> of
* <code>F<sub>2<sup>m</sup></sub></code>.
@@ -917,37 +979,6 @@ namespace Org.BouncyCastle.Math.EC
return new F2mFieldElement(this.m, this.k1, this.k2, this.k3, x);
}
- [Obsolete("Per-point compression property will be removed")]
- public override ECPoint CreatePoint(BigInteger x, BigInteger y, bool withCompression)
- {
- ECFieldElement X = FromBigInteger(x), Y = FromBigInteger(y);
-
- switch (this.CoordinateSystem)
- {
- case COORD_LAMBDA_AFFINE:
- case COORD_LAMBDA_PROJECTIVE:
- {
- if (X.IsZero)
- {
- if (!Y.Square().Equals(B))
- throw new ArgumentException();
- }
- else
- {
- // Y becomes Lambda (X + Y/X) here
- Y = Y.Divide(X).Add(X);
- }
- break;
- }
- default:
- {
- break;
- }
- }
-
- return CreateRawPoint(X, Y, withCompression);
- }
-
protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression)
{
return new F2mPoint(this, x, y, withCompression);
@@ -963,60 +994,6 @@ namespace Org.BouncyCastle.Math.EC
get { return m_infinity; }
}
- /**
- * Returns true if this is a Koblitz curve (ABC curve).
- * @return true if this is a Koblitz curve (ABC curve), false otherwise
- */
- public virtual bool IsKoblitz
- {
- get
- {
- return m_order != null && m_cofactor != null && m_b.IsOne && (m_a.IsZero || m_a.IsOne);
- }
- }
-
- /**
- * Returns the parameter <code>μ</code> of the elliptic curve.
- * @return <code>μ</code> of the elliptic curve.
- * @throws ArgumentException if the given ECCurve is not a
- * Koblitz curve.
- */
- internal virtual sbyte GetMu()
- {
- if (mu == 0)
- {
- lock (this)
- {
- if (mu == 0)
- {
- mu = Tnaf.GetMu(this);
- }
- }
- }
-
- return mu;
- }
-
- /**
- * @return the auxiliary values <code>s<sub>0</sub></code> and
- * <code>s<sub>1</sub></code> used for partial modular reduction for
- * Koblitz curves.
- */
- internal virtual BigInteger[] GetSi()
- {
- if (si == null)
- {
- lock (this)
- {
- if (si == null)
- {
- si = Tnaf.GetSi(this);
- }
- }
- }
- return si;
- }
-
protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
{
ECFieldElement xp = FromBigInteger(X1), yp = null;
@@ -1086,7 +1063,7 @@ namespace Org.BouncyCastle.Math.EC
ECFieldElement t = FromBigInteger(new BigInteger(m, rand));
z = zeroElement;
ECFieldElement w = beta;
- for (int i = 1; i <= m - 1; i++)
+ for (int i = 1; i < m; i++)
{
ECFieldElement w2 = w.Square();
z = z.Square().Add(w2.Multiply(t));
diff --git a/crypto/src/math/ec/ECPoint.cs b/crypto/src/math/ec/ECPoint.cs
index 3e206e65f..a5ba515c5 100644
--- a/crypto/src/math/ec/ECPoint.cs
+++ b/crypto/src/math/ec/ECPoint.cs
@@ -1383,6 +1383,139 @@ namespace Org.BouncyCastle.Math.EC
return lhs.Equals(rhs);
}
+
+ public override ECPoint ScaleX(ECFieldElement scale)
+ {
+ if (this.IsInfinity)
+ return this;
+
+ switch (CurveCoordinateSystem)
+ {
+ case ECCurve.COORD_LAMBDA_AFFINE:
+ {
+ // Y is actually Lambda (X + Y/X) here
+ ECFieldElement X = RawXCoord, L = RawYCoord;
+
+ ECFieldElement X2 = X.Multiply(scale);
+ ECFieldElement L2 = L.Add(X).Divide(scale).Add(X2);
+
+ return Curve.CreateRawPoint(X, L2, RawZCoords, IsCompressed);
+ }
+ case ECCurve.COORD_LAMBDA_PROJECTIVE:
+ {
+ // Y is actually Lambda (X + Y/X) here
+ ECFieldElement X = RawXCoord, L = RawYCoord, Z = RawZCoords[0];
+
+ // We scale the Z coordinate also, to avoid an inversion
+ ECFieldElement X2 = X.Multiply(scale.Square());
+ ECFieldElement L2 = L.Add(X).Add(X2);
+ ECFieldElement Z2 = Z.Multiply(scale);
+
+ return Curve.CreateRawPoint(X, L2, new ECFieldElement[] { Z2 }, IsCompressed);
+ }
+ default:
+ {
+ return base.ScaleX(scale);
+ }
+ }
+ }
+
+ public override ECPoint ScaleY(ECFieldElement scale)
+ {
+ if (this.IsInfinity)
+ return this;
+
+ switch (CurveCoordinateSystem)
+ {
+ case ECCurve.COORD_LAMBDA_AFFINE:
+ case ECCurve.COORD_LAMBDA_PROJECTIVE:
+ {
+ ECFieldElement X = RawXCoord, L = RawYCoord;
+
+ // Y is actually Lambda (X + Y/X) here
+ ECFieldElement L2 = L.Add(X).Multiply(scale).Add(X);
+
+ return Curve.CreateRawPoint(X, L2, RawZCoords, IsCompressed);
+ }
+ default:
+ {
+ return base.ScaleY(scale);
+ }
+ }
+ }
+
+ public override ECPoint Subtract(ECPoint b)
+ {
+ if (b.IsInfinity)
+ return this;
+
+ // Add -b
+ return Add(b.Negate());
+ }
+
+ public virtual AbstractF2mPoint Tau()
+ {
+ if (this.IsInfinity)
+ return this;
+
+ ECCurve curve = this.Curve;
+ int coord = curve.CoordinateSystem;
+
+ ECFieldElement X1 = this.RawXCoord;
+
+ switch (coord)
+ {
+ case ECCurve.COORD_AFFINE:
+ case ECCurve.COORD_LAMBDA_AFFINE:
+ {
+ ECFieldElement Y1 = this.RawYCoord;
+ return (AbstractF2mPoint)curve.CreateRawPoint(X1.Square(), Y1.Square(), IsCompressed);
+ }
+ case ECCurve.COORD_HOMOGENEOUS:
+ case ECCurve.COORD_LAMBDA_PROJECTIVE:
+ {
+ ECFieldElement Y1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+ return (AbstractF2mPoint)curve.CreateRawPoint(X1.Square(), Y1.Square(),
+ new ECFieldElement[] { Z1.Square() }, IsCompressed);
+ }
+ default:
+ {
+ throw new InvalidOperationException("unsupported coordinate system");
+ }
+ }
+ }
+
+ public virtual AbstractF2mPoint TauPow(int pow)
+ {
+ if (this.IsInfinity)
+ return this;
+
+ ECCurve curve = this.Curve;
+ int coord = curve.CoordinateSystem;
+
+ ECFieldElement X1 = this.RawXCoord;
+
+ switch (coord)
+ {
+ case ECCurve.COORD_AFFINE:
+ case ECCurve.COORD_LAMBDA_AFFINE:
+ {
+ ECFieldElement Y1 = this.RawYCoord;
+ return (AbstractF2mPoint)curve.CreateRawPoint(X1.SquarePow(pow), Y1.SquarePow(pow), IsCompressed);
+ }
+ case ECCurve.COORD_HOMOGENEOUS:
+ case ECCurve.COORD_LAMBDA_PROJECTIVE:
+ {
+ ECFieldElement Y1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+ return (AbstractF2mPoint)curve.CreateRawPoint(X1.SquarePow(pow), Y1.SquarePow(pow),
+ new ECFieldElement[] { Z1.SquarePow(pow) }, IsCompressed);
+ }
+ default:
+ {
+ throw new InvalidOperationException("unsupported coordinate system");
+ }
+ }
+ }
}
/**
@@ -1491,66 +1624,6 @@ namespace Org.BouncyCastle.Math.EC
}
}
- public override ECPoint ScaleX(ECFieldElement scale)
- {
- if (this.IsInfinity)
- return this;
-
- switch (CurveCoordinateSystem)
- {
- case ECCurve.COORD_LAMBDA_AFFINE:
- {
- // Y is actually Lambda (X + Y/X) here
- ECFieldElement X = RawXCoord, L = RawYCoord;
-
- ECFieldElement X2 = X.Multiply(scale);
- ECFieldElement L2 = L.Add(X).Divide(scale).Add(X2);
-
- return Curve.CreateRawPoint(X, L2, RawZCoords, IsCompressed);
- }
- case ECCurve.COORD_LAMBDA_PROJECTIVE:
- {
- // Y is actually Lambda (X + Y/X) here
- ECFieldElement X = RawXCoord, L = RawYCoord, Z = RawZCoords[0];
-
- // We scale the Z coordinate also, to avoid an inversion
- ECFieldElement X2 = X.Multiply(scale.Square());
- ECFieldElement L2 = L.Add(X).Add(X2);
- ECFieldElement Z2 = Z.Multiply(scale);
-
- return Curve.CreateRawPoint(X, L2, new ECFieldElement[] { Z2 }, IsCompressed);
- }
- default:
- {
- return base.ScaleX(scale);
- }
- }
- }
-
- public override ECPoint ScaleY(ECFieldElement scale)
- {
- if (this.IsInfinity)
- return this;
-
- switch (CurveCoordinateSystem)
- {
- case ECCurve.COORD_LAMBDA_AFFINE:
- case ECCurve.COORD_LAMBDA_PROJECTIVE:
- {
- ECFieldElement X = RawXCoord, L = RawYCoord;
-
- // Y is actually Lambda (X + Y/X) here
- ECFieldElement L2 = L.Add(X).Multiply(scale).Add(X);
-
- return Curve.CreateRawPoint(X, L2, RawZCoords, IsCompressed);
- }
- default:
- {
- return base.ScaleY(scale);
- }
- }
- }
-
protected internal override bool CompressionYTilde
{
get
@@ -1579,44 +1652,8 @@ namespace Org.BouncyCastle.Math.EC
}
}
- /**
- * Check, if two <code>ECPoint</code>s can be added or subtracted.
- * @param a The first <code>ECPoint</code> to check.
- * @param b The second <code>ECPoint</code> to check.
- * @throws IllegalArgumentException if <code>a</code> and <code>b</code>
- * cannot be added.
- */
- private static void CheckPoints(
- ECPoint a,
- ECPoint b)
- {
- // Check, if points are on the same curve
- if (!a.Curve.Equals(b.Curve))
- throw new ArgumentException("Only points on the same curve can be added or subtracted");
-
-// F2mFieldElement.CheckFieldElements(a.x, b.x);
- }
-
- /* (non-Javadoc)
- * @see org.bouncycastle.math.ec.ECPoint#add(org.bouncycastle.math.ec.ECPoint)
- */
public override ECPoint Add(ECPoint b)
{
- CheckPoints(this, b);
- return AddSimple((F2mPoint) b);
- }
-
- /**
- * Adds another <code>ECPoints.F2m</code> to <code>this</code> without
- * checking if both points are on the same curve. Used by multiplication
- * algorithms, because there all points are a multiple of the same point
- * and hence the checks can be omitted.
- * @param b The other <code>ECPoints.F2m</code> to add to
- * <code>this</code>.
- * @return <code>this + b</code>
- */
- internal F2mPoint AddSimple(F2mPoint b)
- {
if (this.IsInfinity)
return b;
if (b.IsInfinity)
@@ -1640,10 +1677,10 @@ namespace Org.BouncyCastle.Math.EC
{
if (dy.IsZero)
{
- return (F2mPoint)Twice();
+ return Twice();
}
- return (F2mPoint)curve.Infinity;
+ return curve.Infinity;
}
ECFieldElement L = dy.Divide(dx);
@@ -1681,10 +1718,10 @@ namespace Org.BouncyCastle.Math.EC
{
if (U.IsZero)
{
- return (F2mPoint)Twice();
+ return Twice();
}
- return (F2mPoint)curve.Infinity;
+ return curve.Infinity;
}
ECFieldElement VSq = V.Square();
@@ -1705,9 +1742,9 @@ namespace Org.BouncyCastle.Math.EC
if (X1.IsZero)
{
if (X2.IsZero)
- return (F2mPoint)curve.Infinity;
+ return curve.Infinity;
- return b.AddSimple(this);
+ return b.Add(this);
}
ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
@@ -1736,10 +1773,10 @@ namespace Org.BouncyCastle.Math.EC
{
if (A.IsZero)
{
- return (F2mPoint)Twice();
+ return Twice();
}
- return (F2mPoint)curve.Infinity;
+ return curve.Infinity;
}
ECFieldElement X3, L3, Z3;
@@ -1801,68 +1838,6 @@ namespace Org.BouncyCastle.Math.EC
}
/* (non-Javadoc)
- * @see org.bouncycastle.math.ec.ECPoint#subtract(org.bouncycastle.math.ec.ECPoint)
- */
- public override ECPoint Subtract(
- ECPoint b)
- {
- CheckPoints(this, b);
- return SubtractSimple((F2mPoint) b);
- }
-
- /**
- * Subtracts another <code>ECPoints.F2m</code> from <code>this</code>
- * without checking if both points are on the same curve. Used by
- * multiplication algorithms, because there all points are a multiple
- * of the same point and hence the checks can be omitted.
- * @param b The other <code>ECPoints.F2m</code> to subtract from
- * <code>this</code>.
- * @return <code>this - b</code>
- */
- internal F2mPoint SubtractSimple(
- F2mPoint b)
- {
- if (b.IsInfinity)
- return this;
-
- // Add -b
- return AddSimple((F2mPoint) b.Negate());
- }
-
- public virtual F2mPoint Tau()
- {
- if (this.IsInfinity)
- {
- return this;
- }
-
- ECCurve curve = this.Curve;
- int coord = curve.CoordinateSystem;
-
- ECFieldElement X1 = this.RawXCoord;
-
- switch (coord)
- {
- case ECCurve.COORD_AFFINE:
- case ECCurve.COORD_LAMBDA_AFFINE:
- {
- ECFieldElement Y1 = this.RawYCoord;
- return new F2mPoint(curve, X1.Square(), Y1.Square(), IsCompressed);
- }
- case ECCurve.COORD_HOMOGENEOUS:
- case ECCurve.COORD_LAMBDA_PROJECTIVE:
- {
- ECFieldElement Y1 = this.RawYCoord, Z1 = this.RawZCoords[0];
- return new F2mPoint(curve, X1.Square(), Y1.Square(), new ECFieldElement[] { Z1.Square() }, IsCompressed);
- }
- default:
- {
- throw new InvalidOperationException("unsupported coordinate system");
- }
- }
- }
-
- /* (non-Javadoc)
* @see Org.BouncyCastle.Math.EC.ECPoint#twice()
*/
public override ECPoint Twice()
diff --git a/crypto/src/math/ec/abc/Tnaf.cs b/crypto/src/math/ec/abc/Tnaf.cs
index 9f16886f5..b6e792aa4 100644
--- a/crypto/src/math/ec/abc/Tnaf.cs
+++ b/crypto/src/math/ec/abc/Tnaf.cs
@@ -384,11 +384,11 @@ namespace Org.BouncyCastle.Math.EC.Abc
/**
* Applies the operation <code>τ()</code> to an
- * <code>F2mPoint</code>.
- * @param p The F2mPoint to which <code>τ()</code> is applied.
+ * <code>AbstractF2mPoint</code>.
+ * @param p The AbstractF2mPoint to which <code>τ()</code> is applied.
* @return <code>τ(p)</code>
*/
- public static F2mPoint Tau(F2mPoint p)
+ public static AbstractF2mPoint Tau(AbstractF2mPoint p)
{
return p.Tau();
}
@@ -403,7 +403,7 @@ namespace Org.BouncyCastle.Math.EC.Abc
* @throws ArgumentException if the given ECCurve is not a Koblitz
* curve.
*/
- public static sbyte GetMu(F2mCurve curve)
+ public static sbyte GetMu(AbstractF2mCurve curve)
{
BigInteger a = curve.A.ToBigInteger();
@@ -423,6 +423,16 @@ namespace Org.BouncyCastle.Math.EC.Abc
return mu;
}
+ public static sbyte GetMu(ECFieldElement curveA)
+ {
+ return (sbyte)(curveA.IsZero ? -1 : 1);
+ }
+
+ public static sbyte GetMu(int curveA)
+ {
+ return (sbyte)(curveA == 0 ? -1 : 1);
+ }
+
/**
* Calculates the Lucas Sequence elements <code>U<sub>k-1</sub></code> and
* <code>U<sub>k</sub></code> or <code>V<sub>k-1</sub></code> and
@@ -526,53 +536,60 @@ namespace Org.BouncyCastle.Math.EC.Abc
* @throws ArgumentException if <code>curve</code> is not a
* Koblitz curve (Anomalous Binary Curve, ABC).
*/
- public static BigInteger[] GetSi(F2mCurve curve)
+ public static BigInteger[] GetSi(AbstractF2mCurve curve)
{
if (!curve.IsKoblitz)
throw new ArgumentException("si is defined for Koblitz curves only");
- int m = curve.M;
+ int m = curve.FieldSize;
int a = curve.A.ToBigInteger().IntValue;
- sbyte mu = curve.GetMu();
- int h = curve.Cofactor.IntValue;
+ sbyte mu = GetMu(a);
+ int shifts = GetShiftsForCofactor(curve.Cofactor);
int index = m + 3 - a;
BigInteger[] ui = GetLucas(mu, index, false);
- BigInteger dividend0;
- BigInteger dividend1;
if (mu == 1)
{
- dividend0 = BigInteger.One.Subtract(ui[1]);
- dividend1 = BigInteger.One.Subtract(ui[0]);
- }
- else if (mu == -1)
- {
- dividend0 = BigInteger.One.Add(ui[1]);
- dividend1 = BigInteger.One.Add(ui[0]);
- }
- else
- {
- throw new ArgumentException("mu must be 1 or -1");
+ ui[0] = ui[0].Negate();
+ ui[1] = ui[1].Negate();
}
- BigInteger[] si = new BigInteger[2];
+ BigInteger dividend0 = BigInteger.One.Add(ui[1]).ShiftRight(shifts);
+ BigInteger dividend1 = BigInteger.One.Add(ui[0]).ShiftRight(shifts).Negate();
- if (h == 2)
- {
- si[0] = dividend0.ShiftRight(1);
- si[1] = dividend1.ShiftRight(1).Negate();
- }
- else if (h == 4)
+ return new BigInteger[] { dividend0, dividend1 };
+ }
+
+ public static BigInteger[] GetSi(int fieldSize, int curveA, BigInteger cofactor)
+ {
+ sbyte mu = GetMu(curveA);
+ int shifts = GetShiftsForCofactor(cofactor);
+ int index = fieldSize + 3 - curveA;
+ BigInteger[] ui = GetLucas(mu, index, false);
+ if (mu == 1)
{
- si[0] = dividend0.ShiftRight(2);
- si[1] = dividend1.ShiftRight(2).Negate();
+ ui[0] = ui[0].Negate();
+ ui[1] = ui[1].Negate();
}
- else
+
+ BigInteger dividend0 = BigInteger.One.Add(ui[1]).ShiftRight(shifts);
+ BigInteger dividend1 = BigInteger.One.Add(ui[0]).ShiftRight(shifts).Negate();
+
+ return new BigInteger[] { dividend0, dividend1 };
+ }
+
+ protected static int GetShiftsForCofactor(BigInteger h)
+ {
+ if (h != null && h.BitLength < 4)
{
- throw new ArgumentException("h (Cofactor) must be 2 or 4");
+ int hi = h.IntValue;
+ if (hi == 2)
+ return 1;
+ if (hi == 4)
+ return 2;
}
- return si;
+ throw new ArgumentException("h (Cofactor) must be 2 or 4");
}
/**
@@ -624,70 +641,77 @@ namespace Org.BouncyCastle.Math.EC.Abc
}
/**
- * Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint}
+ * Multiplies a {@link org.bouncycastle.math.ec.AbstractF2mPoint AbstractF2mPoint}
* by a <code>BigInteger</code> using the reduced <code>τ</code>-adic
* NAF (RTNAF) method.
- * @param p The F2mPoint to Multiply.
+ * @param p The AbstractF2mPoint to Multiply.
* @param k The <code>BigInteger</code> by which to Multiply <code>p</code>.
* @return <code>k * p</code>
*/
- public static F2mPoint MultiplyRTnaf(F2mPoint p, BigInteger k)
+ public static AbstractF2mPoint MultiplyRTnaf(AbstractF2mPoint p, BigInteger k)
{
- F2mCurve curve = (F2mCurve) p.Curve;
- int m = curve.M;
- sbyte a = (sbyte) curve.A.ToBigInteger().IntValue;
- sbyte mu = curve.GetMu();
+ AbstractF2mCurve curve = (AbstractF2mCurve)p.Curve;
+ int m = curve.FieldSize;
+ int a = curve.A.ToBigInteger().IntValue;
+ sbyte mu = GetMu(a);
BigInteger[] s = curve.GetSi();
- ZTauElement rho = PartModReduction(k, m, a, s, mu, (sbyte)10);
+ ZTauElement rho = PartModReduction(k, m, (sbyte)a, s, mu, (sbyte)10);
return MultiplyTnaf(p, rho);
}
/**
- * Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint}
+ * Multiplies a {@link org.bouncycastle.math.ec.AbstractF2mPoint AbstractF2mPoint}
* by an element <code>λ</code> of <code><b>Z</b>[τ]</code>
* using the <code>τ</code>-adic NAF (TNAF) method.
- * @param p The F2mPoint to Multiply.
+ * @param p The AbstractF2mPoint to Multiply.
* @param lambda The element <code>λ</code> of
* <code><b>Z</b>[τ]</code>.
* @return <code>λ * p</code>
*/
- public static F2mPoint MultiplyTnaf(F2mPoint p, ZTauElement lambda)
+ public static AbstractF2mPoint MultiplyTnaf(AbstractF2mPoint p, ZTauElement lambda)
{
- F2mCurve curve = (F2mCurve)p.Curve;
- sbyte mu = curve.GetMu();
+ AbstractF2mCurve curve = (AbstractF2mCurve)p.Curve;
+ sbyte mu = GetMu(curve.A);
sbyte[] u = TauAdicNaf(mu, lambda);
- F2mPoint q = MultiplyFromTnaf(p, u);
+ AbstractF2mPoint q = MultiplyFromTnaf(p, u);
return q;
}
/**
- * Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint}
+ * Multiplies a {@link org.bouncycastle.math.ec.AbstractF2mPoint AbstractF2mPoint}
* by an element <code>λ</code> of <code><b>Z</b>[τ]</code>
* using the <code>τ</code>-adic NAF (TNAF) method, given the TNAF
* of <code>λ</code>.
- * @param p The F2mPoint to Multiply.
+ * @param p The AbstractF2mPoint to Multiply.
* @param u The the TNAF of <code>λ</code>..
* @return <code>λ * p</code>
*/
- public static F2mPoint MultiplyFromTnaf(F2mPoint p, sbyte[] u)
+ public static AbstractF2mPoint MultiplyFromTnaf(AbstractF2mPoint p, sbyte[] u)
{
- F2mCurve curve = (F2mCurve)p.Curve;
- F2mPoint q = (F2mPoint) curve.Infinity;
+ ECCurve curve = p.Curve;
+ AbstractF2mPoint q = (AbstractF2mPoint)curve.Infinity;
+ AbstractF2mPoint pNeg = (AbstractF2mPoint)p.Negate();
+ int tauCount = 0;
for (int i = u.Length - 1; i >= 0; i--)
{
- q = Tau(q);
- if (u[i] == 1)
- {
- q = (F2mPoint)q.AddSimple(p);
- }
- else if (u[i] == -1)
+ ++tauCount;
+ sbyte ui = u[i];
+ if (ui != 0)
{
- q = (F2mPoint)q.SubtractSimple(p);
+ q = q.TauPow(tauCount);
+ tauCount = 0;
+
+ ECPoint x = ui > 0 ? p : pNeg;
+ q = (AbstractF2mPoint)q.Add(x);
}
}
+ if (tauCount > 0)
+ {
+ q = q.TauPow(tauCount);
+ }
return q;
}
@@ -800,28 +824,21 @@ namespace Org.BouncyCastle.Math.EC.Abc
* @param a The parameter <code>a</code> of the elliptic curve.
* @return The precomputation array for <code>p</code>.
*/
- public static F2mPoint[] GetPreComp(F2mPoint p, sbyte a)
+ public static AbstractF2mPoint[] GetPreComp(AbstractF2mPoint p, sbyte a)
{
- F2mPoint[] pu;
- pu = new F2mPoint[16];
- pu[1] = p;
- sbyte[][] alphaTnaf;
- if (a == 0)
- {
- alphaTnaf = Tnaf.Alpha0Tnaf;
- }
- else
- {
- // a == 1
- alphaTnaf = Tnaf.Alpha1Tnaf;
- }
+ sbyte[][] alphaTnaf = (a == 0) ? Tnaf.Alpha0Tnaf : Tnaf.Alpha1Tnaf;
+
+ AbstractF2mPoint[] pu = new AbstractF2mPoint[(uint)(alphaTnaf.Length + 1) >> 1];
+ pu[0] = p;
- int precompLen = alphaTnaf.Length;
- for (int i = 3; i < precompLen; i = i + 2)
+ uint precompLen = (uint)alphaTnaf.Length;
+ for (uint i = 3; i < precompLen; i += 2)
{
- pu[i] = Tnaf.MultiplyFromTnaf(p, alphaTnaf[i]);
+ pu[i >> 1] = Tnaf.MultiplyFromTnaf(p, alphaTnaf[i]);
}
-
+
+ p.Curve.NormalizeAll(pu);
+
return pu;
}
}
diff --git a/crypto/src/math/ec/multiplier/WTauNafMultiplier.cs b/crypto/src/math/ec/multiplier/WTauNafMultiplier.cs
index dda778eea..1e7ddae91 100644
--- a/crypto/src/math/ec/multiplier/WTauNafMultiplier.cs
+++ b/crypto/src/math/ec/multiplier/WTauNafMultiplier.cs
@@ -15,23 +15,23 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
internal static readonly string PRECOMP_NAME = "bc_wtnaf";
/**
- * Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint}
+ * Multiplies a {@link org.bouncycastle.math.ec.AbstractF2mPoint AbstractF2mPoint}
* by <code>k</code> using the reduced <code>τ</code>-adic NAF (RTNAF)
* method.
- * @param p The F2mPoint to multiply.
+ * @param p The AbstractF2mPoint to multiply.
* @param k The integer by which to multiply <code>k</code>.
* @return <code>p</code> multiplied by <code>k</code>.
*/
protected override ECPoint MultiplyPositive(ECPoint point, BigInteger k)
{
- if (!(point is F2mPoint))
- throw new ArgumentException("Only F2mPoint can be used in WTauNafMultiplier");
-
- F2mPoint p = (F2mPoint)point;
- F2mCurve curve = (F2mCurve)p.Curve;
- int m = curve.M;
- sbyte a = (sbyte) curve.A.ToBigInteger().IntValue;
- sbyte mu = curve.GetMu();
+ if (!(point is AbstractF2mPoint))
+ throw new ArgumentException("Only AbstractF2mPoint can be used in WTauNafMultiplier");
+
+ AbstractF2mPoint p = (AbstractF2mPoint)point;
+ AbstractF2mCurve curve = (AbstractF2mCurve)p.Curve;
+ int m = curve.FieldSize;
+ sbyte a = (sbyte)curve.A.ToBigInteger().IntValue;
+ sbyte mu = Tnaf.GetMu(a);
BigInteger[] s = curve.GetSi();
ZTauElement rho = Tnaf.PartModReduction(k, m, a, s, mu, (sbyte)10);
@@ -40,16 +40,16 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
}
/**
- * Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint}
+ * Multiplies a {@link org.bouncycastle.math.ec.AbstractF2mPoint AbstractF2mPoint}
* by an element <code>λ</code> of <code><b>Z</b>[τ]</code> using
* the <code>τ</code>-adic NAF (TNAF) method.
- * @param p The F2mPoint to multiply.
+ * @param p The AbstractF2mPoint to multiply.
* @param lambda The element <code>λ</code> of
* <code><b>Z</b>[τ]</code> of which to compute the
* <code>[τ]</code>-adic NAF.
* @return <code>p</code> multiplied by <code>λ</code>.
*/
- private F2mPoint MultiplyWTnaf(F2mPoint p, ZTauElement lambda,
+ private AbstractF2mPoint MultiplyWTnaf(AbstractF2mPoint p, ZTauElement lambda,
PreCompInfo preCompInfo, sbyte a, sbyte mu)
{
ZTauElement[] alpha = (a == 0) ? Tnaf.Alpha0 : Tnaf.Alpha1;
@@ -63,20 +63,20 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
}
/**
- * Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint}
+ * Multiplies a {@link org.bouncycastle.math.ec.AbstractF2mPoint AbstractF2mPoint}
* by an element <code>λ</code> of <code><b>Z</b>[τ]</code>
* using the window <code>τ</code>-adic NAF (TNAF) method, given the
* WTNAF of <code>λ</code>.
- * @param p The F2mPoint to multiply.
+ * @param p The AbstractF2mPoint to multiply.
* @param u The the WTNAF of <code>λ</code>..
* @return <code>λ * p</code>
*/
- private static F2mPoint MultiplyFromWTnaf(F2mPoint p, sbyte[] u, PreCompInfo preCompInfo)
+ private static AbstractF2mPoint MultiplyFromWTnaf(AbstractF2mPoint p, sbyte[] u, PreCompInfo preCompInfo)
{
- F2mCurve curve = (F2mCurve)p.Curve;
+ AbstractF2mCurve curve = (AbstractF2mCurve)p.Curve;
sbyte a = (sbyte)curve.A.ToBigInteger().IntValue;
- F2mPoint[] pu;
+ AbstractF2mPoint[] pu;
if ((preCompInfo == null) || !(preCompInfo is WTauNafPreCompInfo))
{
pu = Tnaf.GetPreComp(p, a);
@@ -90,26 +90,35 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
pu = ((WTauNafPreCompInfo)preCompInfo).PreComp;
}
+ // TODO Include negations in precomp (optionally) and use from here
+ AbstractF2mPoint[] puNeg = new AbstractF2mPoint[pu.Length];
+ for (int i = 0; i < pu.Length; ++i)
+ {
+ puNeg[i] = (AbstractF2mPoint)pu[i].Negate();
+ }
+
+
// q = infinity
- F2mPoint q = (F2mPoint)curve.Infinity;
+ AbstractF2mPoint q = (AbstractF2mPoint) p.Curve.Infinity;
+
+ int tauCount = 0;
for (int i = u.Length - 1; i >= 0; i--)
{
- q = Tnaf.Tau(q);
- sbyte ui = u[i];
+ ++tauCount;
+ int ui = u[i];
if (ui != 0)
{
- if (ui > 0)
- {
- q = q.AddSimple(pu[ui]);
- }
- else
- {
- // u[i] < 0
- q = q.SubtractSimple(pu[-ui]);
- }
+ q = q.TauPow(tauCount);
+ tauCount = 0;
+
+ ECPoint x = ui > 0 ? pu[ui >> 1] : puNeg[(-ui) >> 1];
+ q = (AbstractF2mPoint)q.Add(x);
}
}
-
+ if (tauCount > 0)
+ {
+ q = q.TauPow(tauCount);
+ }
return q;
}
}
diff --git a/crypto/src/math/ec/multiplier/WTauNafPreCompInfo.cs b/crypto/src/math/ec/multiplier/WTauNafPreCompInfo.cs
index 3c18404c0..72659b3ec 100644
--- a/crypto/src/math/ec/multiplier/WTauNafPreCompInfo.cs
+++ b/crypto/src/math/ec/multiplier/WTauNafPreCompInfo.cs
@@ -8,14 +8,14 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
: PreCompInfo
{
/**
- * Array holding the precomputed <code>F2mPoint</code>s used for the
+ * Array holding the precomputed <code>AbstractF2mPoint</code>s used for the
* WTNAF multiplication in <code>
* {@link org.bouncycastle.math.ec.multiplier.WTauNafMultiplier.multiply()
* WTauNafMultiplier.multiply()}</code>.
*/
- protected F2mPoint[] m_preComp;
+ protected AbstractF2mPoint[] m_preComp;
- public virtual F2mPoint[] PreComp
+ public virtual AbstractF2mPoint[] PreComp
{
get { return m_preComp; }
set { this.m_preComp = value; }
|