diff --git a/crypto/src/math/ec/ECAlgorithms.cs b/crypto/src/math/ec/ECAlgorithms.cs
index 5d60de40f..b05c0201a 100644
--- a/crypto/src/math/ec/ECAlgorithms.cs
+++ b/crypto/src/math/ec/ECAlgorithms.cs
@@ -58,10 +58,10 @@ namespace Org.BouncyCastle.Math.EC
GlvEndomorphism glvEndomorphism = c.GetEndomorphism() as GlvEndomorphism;
if (glvEndomorphism != null)
{
- return ValidatePoint(ImplSumOfMultipliesGlv(imported, ks, glvEndomorphism));
+ return ImplCheckResult(ImplSumOfMultipliesGlv(imported, ks, glvEndomorphism));
}
- return ValidatePoint(ImplSumOfMultiplies(imported, ks));
+ return ImplCheckResult(ImplSumOfMultiplies(imported, ks));
}
public static ECPoint SumOfTwoMultiplies(ECPoint P, BigInteger a, ECPoint Q, BigInteger b)
@@ -74,18 +74,18 @@ namespace Org.BouncyCastle.Math.EC
AbstractF2mCurve f2mCurve = cp as AbstractF2mCurve;
if (f2mCurve != null && f2mCurve.IsKoblitz)
{
- return ValidatePoint(P.Multiply(a).Add(Q.Multiply(b)));
+ return ImplCheckResult(P.Multiply(a).Add(Q.Multiply(b)));
}
}
GlvEndomorphism glvEndomorphism = cp.GetEndomorphism() as GlvEndomorphism;
if (glvEndomorphism != null)
{
- return ValidatePoint(
+ return ImplCheckResult(
ImplSumOfMultipliesGlv(new ECPoint[] { P, Q }, new BigInteger[] { a, b }, glvEndomorphism));
}
- return ValidatePoint(ImplShamirsTrickWNaf(P, a, Q, b));
+ return ImplCheckResult(ImplShamirsTrickWNaf(P, a, Q, b));
}
/*
@@ -111,7 +111,7 @@ namespace Org.BouncyCastle.Math.EC
ECCurve cp = P.Curve;
Q = ImportPoint(cp, Q);
- return ValidatePoint(ImplShamirsTrickJsf(P, k, Q, l));
+ return ImplCheckResult(ImplShamirsTrickJsf(P, k, Q, l));
}
public static ECPoint ImportPoint(ECCurve c, ECPoint p)
@@ -202,7 +202,24 @@ namespace Org.BouncyCastle.Math.EC
public static ECPoint ValidatePoint(ECPoint p)
{
if (!p.IsValid())
- throw new ArgumentException("Invalid point", "p");
+ throw new InvalidOperationException("Invalid point");
+
+ return p;
+ }
+
+ public static ECPoint CleanPoint(ECCurve c, ECPoint p)
+ {
+ ECCurve cp = p.Curve;
+ if (!c.Equals(cp))
+ throw new ArgumentException("Point must be on the same curve", "p");
+
+ return c.DecodePoint(p.GetEncoded(false));
+ }
+
+ internal static ECPoint ImplCheckResult(ECPoint p)
+ {
+ if (!p.IsValidPartial())
+ throw new InvalidOperationException("Invalid result");
return p;
}
diff --git a/crypto/src/math/ec/ECCurve.cs b/crypto/src/math/ec/ECCurve.cs
index 6a9342722..993b69149 100644
--- a/crypto/src/math/ec/ECCurve.cs
+++ b/crypto/src/math/ec/ECCurve.cs
@@ -161,15 +161,24 @@ namespace Org.BouncyCastle.Math.EC
public virtual PreCompInfo GetPreCompInfo(ECPoint point, string name)
{
CheckPoint(point);
+
+ IDictionary table;
lock (point)
{
- IDictionary table = point.m_preCompTable;
- return table == null ? null : (PreCompInfo)table[name];
+ table = point.m_preCompTable;
+ }
+
+ if (null == table)
+ return null;
+
+ lock (table)
+ {
+ return (PreCompInfo)table[name];
}
}
/**
- * Adds <code>PreCompInfo</code> for a point on this curve, under a given name. Used by
+ * Compute a <code>PreCompInfo</code> for a point on this curve, under a given name. Used by
* <code>ECMultiplier</code>s to save the precomputation for this <code>ECPoint</code> for use
* by subsequent multiplication.
*
@@ -177,20 +186,34 @@ namespace Org.BouncyCastle.Math.EC
* The <code>ECPoint</code> to store precomputations for.
* @param name
* A <code>String</code> used to index precomputations of different types.
- * @param preCompInfo
- * The values precomputed by the <code>ECMultiplier</code>.
+ * @param callback
+ * Called to calculate the <code>PreCompInfo</code>.
*/
- public virtual void SetPreCompInfo(ECPoint point, string name, PreCompInfo preCompInfo)
+ public virtual PreCompInfo Precompute(ECPoint point, string name, IPreCompCallback callback)
{
CheckPoint(point);
+
+ IDictionary table;
lock (point)
{
- IDictionary table = point.m_preCompTable;
+ table = point.m_preCompTable;
if (null == table)
{
point.m_preCompTable = table = Platform.CreateHashtable(4);
}
- table[name] = preCompInfo;
+ }
+
+ lock (table)
+ {
+ PreCompInfo existing = (PreCompInfo)table[name];
+ PreCompInfo result = callback.Precompute(existing);
+
+ if (result != existing)
+ {
+ table[name] = result;
+ }
+
+ return result;
}
}
@@ -208,7 +231,7 @@ namespace Org.BouncyCastle.Math.EC
// TODO Default behaviour could be improved if the two curves have the same coordinate system by copying any Z coordinates.
p = p.Normalize();
- return ValidatePoint(p.XCoord.ToBigInteger(), p.YCoord.ToBigInteger(), p.IsCompressed);
+ return CreatePoint(p.XCoord.ToBigInteger(), p.YCoord.ToBigInteger(), p.IsCompressed);
}
/**
@@ -453,7 +476,7 @@ namespace Org.BouncyCastle.Math.EC
BigInteger X = new BigInteger(1, encoded, 1, expectedLength);
p = DecompressPoint(yTilde, X);
- if (!p.SatisfiesCofactor())
+ if (!p.ImplIsValid(true, true))
throw new ArgumentException("Invalid point");
break;
@@ -588,6 +611,7 @@ namespace Org.BouncyCastle.Math.EC
protected readonly BigInteger m_q, m_r;
protected readonly FpPoint m_infinity;
+ [Obsolete("Use constructor taking order/cofactor")]
public FpCurve(BigInteger q, BigInteger a, BigInteger b)
: this(q, a, b, null, null)
{
@@ -598,7 +622,7 @@ namespace Org.BouncyCastle.Math.EC
{
this.m_q = q;
this.m_r = FpFieldElement.CalculateResidue(q);
- this.m_infinity = new FpPoint(this, null, null);
+ this.m_infinity = new FpPoint(this, null, null, false);
this.m_a = FromBigInteger(a);
this.m_b = FromBigInteger(b);
@@ -607,6 +631,7 @@ namespace Org.BouncyCastle.Math.EC
this.m_coord = FP_DEFAULT_COORDS;
}
+ [Obsolete("Use constructor taking order/cofactor")]
protected FpCurve(BigInteger q, BigInteger r, ECFieldElement a, ECFieldElement b)
: this(q, r, a, b, null, null)
{
@@ -617,7 +642,7 @@ namespace Org.BouncyCastle.Math.EC
{
this.m_q = q;
this.m_r = r;
- this.m_infinity = new FpPoint(this, null, null);
+ this.m_infinity = new FpPoint(this, null, null, false);
this.m_a = a;
this.m_b = b;
@@ -794,7 +819,7 @@ namespace Org.BouncyCastle.Math.EC
else
{
ECFieldElement beta = xp.Square().Invert().Multiply(B).Add(A).Add(xp);
- ECFieldElement z = SolveQuadradicEquation(beta);
+ ECFieldElement z = SolveQuadraticEquation(beta);
if (z != null)
{
@@ -831,11 +856,11 @@ namespace Org.BouncyCastle.Math.EC
* D.1.6) The other solution is <code>z + 1</code>.
*
* @param beta
- * The value to solve the qradratic equation for.
+ * The value to solve the quadratic equation for.
* @return the solution for <code>z<sup>2</sup> + z = beta</code> or
* <code>null</code> if no solution exists.
*/
- private ECFieldElement SolveQuadradicEquation(ECFieldElement beta)
+ internal ECFieldElement SolveQuadraticEquation(ECFieldElement beta)
{
if (beta.IsZero)
return beta;
@@ -957,6 +982,7 @@ namespace Org.BouncyCastle.Math.EC
* for non-supersingular elliptic curves over
* <code>F<sub>2<sup>m</sup></sub></code>.
*/
+ [Obsolete("Use constructor taking order/cofactor")]
public F2mCurve(
int m,
int k,
@@ -1014,6 +1040,7 @@ namespace Org.BouncyCastle.Math.EC
* for non-supersingular elliptic curves over
* <code>F<sub>2<sup>m</sup></sub></code>.
*/
+ [Obsolete("Use constructor taking order/cofactor")]
public F2mCurve(
int m,
int k1,
@@ -1065,7 +1092,7 @@ namespace Org.BouncyCastle.Math.EC
this.k3 = k3;
this.m_order = order;
this.m_cofactor = cofactor;
- this.m_infinity = new F2mPoint(this, null, null);
+ this.m_infinity = new F2mPoint(this, null, null, false);
if (k1 == 0)
throw new ArgumentException("k1 must be > 0");
@@ -1099,7 +1126,7 @@ namespace Org.BouncyCastle.Math.EC
this.m_order = order;
this.m_cofactor = cofactor;
- this.m_infinity = new F2mPoint(this, null, null);
+ this.m_infinity = new F2mPoint(this, null, null, false);
this.m_a = a;
this.m_b = b;
this.m_coord = F2M_DEFAULT_COORDS;
@@ -1188,18 +1215,6 @@ namespace Org.BouncyCastle.Math.EC
get { return k3; }
}
- [Obsolete("Use 'Order' property instead")]
- public BigInteger N
- {
- get { return m_order; }
- }
-
- [Obsolete("Use 'Cofactor' property instead")]
- public BigInteger H
- {
- get { return m_cofactor; }
- }
-
public override ECLookupTable CreateCacheSafeLookupTable(ECPoint[] points, int off, int len)
{
int FE_LONGS = (m + 63) / 64;
diff --git a/crypto/src/math/ec/ECFieldElement.cs b/crypto/src/math/ec/ECFieldElement.cs
index 3676c81b1..350e8c6d4 100644
--- a/crypto/src/math/ec/ECFieldElement.cs
+++ b/crypto/src/math/ec/ECFieldElement.cs
@@ -101,9 +101,14 @@ namespace Org.BouncyCastle.Math.EC
}
}
- public class FpFieldElement
+ public abstract class AbstractFpFieldElement
: ECFieldElement
{
+ }
+
+ public class FpFieldElement
+ : AbstractFpFieldElement
+ {
private readonly BigInteger q, r, x;
internal static BigInteger CalculateResidue(BigInteger p)
@@ -536,6 +541,45 @@ namespace Org.BouncyCastle.Math.EC
}
}
+ public abstract class AbstractF2mFieldElement
+ : ECFieldElement
+ {
+ public virtual ECFieldElement HalfTrace()
+ {
+ int m = FieldSize;
+ if ((m & 1) == 0)
+ throw new InvalidOperationException("Half-trace only defined for odd m");
+
+ ECFieldElement fe = this;
+ ECFieldElement ht = fe;
+ for (int i = 2; i < m; i += 2)
+ {
+ fe = fe.SquarePow(2);
+ ht = ht.Add(fe);
+ }
+
+ return ht;
+ }
+
+ public virtual int Trace()
+ {
+ int m = FieldSize;
+ ECFieldElement fe = this;
+ ECFieldElement tr = fe;
+ for (int i = 1; i < m; ++i)
+ {
+ fe = fe.Square();
+ tr = tr.Add(fe);
+ }
+ if (tr.IsZero)
+ return 0;
+ if (tr.IsOne)
+ return 1;
+
+ throw new InvalidOperationException("Internal error in trace calculation");
+ }
+ }
+
/**
* Class representing the Elements of the finite field
* <code>F<sub>2<sup>m</sup></sub></code> in polynomial basis (PB)
@@ -544,7 +588,7 @@ namespace Org.BouncyCastle.Math.EC
* representation is not supported.
*/
public class F2mFieldElement
- : ECFieldElement
+ : AbstractF2mFieldElement
{
/**
* Indicates gaussian normal basis representation (GNB). Number chosen
@@ -582,20 +626,21 @@ namespace Org.BouncyCastle.Math.EC
internal LongArray x;
/**
- * Constructor for Ppb.
- * @param m The exponent <code>m</code> of
- * <code>F<sub>2<sup>m</sup></sub></code>.
- * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
- * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
- * represents the reduction polynomial <code>f(z)</code>.
- * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
- * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
- * represents the reduction polynomial <code>f(z)</code>.
- * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
- * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
- * represents the reduction polynomial <code>f(z)</code>.
- * @param x The BigInteger representing the value of the field element.
- */
+ * Constructor for Ppb.
+ * @param m The exponent <code>m</code> of
+ * <code>F<sub>2<sup>m</sup></sub></code>.
+ * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
+ * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+ * represents the reduction polynomial <code>f(z)</code>.
+ * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
+ * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+ * represents the reduction polynomial <code>f(z)</code>.
+ * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
+ * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+ * represents the reduction polynomial <code>f(z)</code>.
+ * @param x The BigInteger representing the value of the field element.
+ */
+ [Obsolete("Use ECCurve.FromBigInteger to construct field elements")]
public F2mFieldElement(
int m,
int k1,
@@ -627,14 +672,15 @@ namespace Org.BouncyCastle.Math.EC
}
/**
- * Constructor for Tpb.
- * @param m The exponent <code>m</code> of
- * <code>F<sub>2<sup>m</sup></sub></code>.
- * @param k The integer <code>k</code> where <code>x<sup>m</sup> +
- * x<sup>k</sup> + 1</code> represents the reduction
- * polynomial <code>f(z)</code>.
- * @param x The BigInteger representing the value of the field element.
- */
+ * Constructor for Tpb.
+ * @param m The exponent <code>m</code> of
+ * <code>F<sub>2<sup>m</sup></sub></code>.
+ * @param k The integer <code>k</code> where <code>x<sup>m</sup> +
+ * x<sup>k</sup> + 1</code> represents the reduction
+ * polynomial <code>f(z)</code>.
+ * @param x The BigInteger representing the value of the field element.
+ */
+ [Obsolete("Use ECCurve.FromBigInteger to construct field elements")]
public F2mFieldElement(
int m,
int k,
diff --git a/crypto/src/math/ec/ECPoint.cs b/crypto/src/math/ec/ECPoint.cs
index a5ba515c5..2acc9f5c0 100644
--- a/crypto/src/math/ec/ECPoint.cs
+++ b/crypto/src/math/ec/ECPoint.cs
@@ -67,13 +67,19 @@ namespace Org.BouncyCastle.Math.EC
this.m_withCompression = withCompression;
}
- protected internal bool SatisfiesCofactor()
+ protected abstract bool SatisfiesCurveEquation();
+
+ protected virtual bool SatisfiesOrder()
{
- BigInteger h = Curve.Cofactor;
- return h == null || h.Equals(BigInteger.One) || !ECAlgorithms.ReferenceMultiply(this, h).IsInfinity;
- }
+ if (BigInteger.One.Equals(Curve.Cofactor))
+ return true;
- protected abstract bool SatisfiesCurveEquation();
+ BigInteger n = Curve.Order;
+
+ // TODO Require order to be available for all curves
+
+ return n == null || ECAlgorithms.ReferenceMultiply(this, n).IsInfinity;
+ }
public ECPoint GetDetachedPoint()
{
@@ -97,30 +103,6 @@ namespace Org.BouncyCastle.Math.EC
}
/**
- * Normalizes this point, and then returns the affine x-coordinate.
- *
- * Note: normalization can be expensive, this method is deprecated in favour
- * of caller-controlled normalization.
- */
- [Obsolete("Use AffineXCoord, or Normalize() and XCoord, instead")]
- public virtual ECFieldElement X
- {
- get { return Normalize().XCoord; }
- }
-
- /**
- * Normalizes this point, and then returns the affine y-coordinate.
- *
- * Note: normalization can be expensive, this method is deprecated in favour
- * of caller-controlled normalization.
- */
- [Obsolete("Use AffineYCoord, or Normalize() and YCoord, instead")]
- public virtual ECFieldElement Y
- {
- get { return Normalize().YCoord; }
- }
-
- /**
* Returns the affine x-coordinate after checking that this point is normalized.
*
* @return The affine x-coordinate of this point
@@ -299,22 +281,22 @@ namespace Org.BouncyCastle.Math.EC
public bool IsValid()
{
- if (IsInfinity)
- return true;
-
- // TODO Sanity-check the field elements
+ return ImplIsValid(false, true);
+ }
- ECCurve curve = Curve;
- if (curve != null)
- {
- if (!SatisfiesCurveEquation())
- return false;
+ internal bool IsValidPartial()
+ {
+ return ImplIsValid(false, false);
+ }
- if (!SatisfiesCofactor())
- return false;
- }
+ internal bool ImplIsValid(bool decompressed, bool checkOrder)
+ {
+ if (IsInfinity)
+ return true;
- return true;
+ ValidityCallback callback = new ValidityCallback(this, decompressed, checkOrder);
+ ValidityPreCompInfo validity = (ValidityPreCompInfo)Curve.Precompute(this, ValidityPreCompInfo.PRECOMP_NAME, callback);
+ return !validity.HasFailed();
}
public virtual ECPoint ScaleX(ECFieldElement scale)
@@ -462,6 +444,52 @@ namespace Org.BouncyCastle.Math.EC
{
return TwicePlus(this);
}
+
+ private class ValidityCallback
+ : IPreCompCallback
+ {
+ private readonly ECPoint m_outer;
+ private readonly bool m_decompressed, m_checkOrder;
+
+ internal ValidityCallback(ECPoint outer, bool decompressed, bool checkOrder)
+ {
+ this.m_outer = outer;
+ this.m_decompressed = decompressed;
+ this.m_checkOrder = checkOrder;
+ }
+
+ public PreCompInfo Precompute(PreCompInfo existing)
+ {
+ ValidityPreCompInfo info = existing as ValidityPreCompInfo;
+ if (info == null)
+ {
+ info = new ValidityPreCompInfo();
+ }
+
+ if (info.HasFailed())
+ return info;
+
+ if (!info.HasCurveEquationPassed())
+ {
+ if (!m_decompressed && !m_outer.SatisfiesCurveEquation())
+ {
+ info.ReportFailed();
+ return info;
+ }
+ info.ReportCurveEquationPassed();
+ }
+ if (m_checkOrder && !info.HasOrderPassed())
+ {
+ if (!m_outer.SatisfiesOrder())
+ {
+ info.ReportFailed();
+ return info;
+ }
+ info.ReportOrderPassed();
+ }
+ return info;
+ }
+ }
}
public abstract class ECPointBase
@@ -608,6 +636,7 @@ namespace Org.BouncyCastle.Math.EC
* @param x affine x co-ordinate
* @param y affine y co-ordinate
*/
+ [Obsolete("Use ECCurve.CreatePoint to construct points")]
public FpPoint(ECCurve curve, ECFieldElement x, ECFieldElement y)
: this(curve, x, y, false)
{
@@ -621,6 +650,7 @@ namespace Org.BouncyCastle.Math.EC
* @param y affine y co-ordinate
* @param withCompression if true encode with point compression
*/
+ [Obsolete("Per-point compression property will be removed, see GetEncoded(bool)")]
public FpPoint(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression)
: base(curve, x, y, withCompression)
{
@@ -635,7 +665,7 @@ namespace Org.BouncyCastle.Math.EC
protected override ECPoint Detach()
{
- return new FpPoint(null, AffineXCoord, AffineYCoord);
+ return new FpPoint(null, AffineXCoord, AffineYCoord, false);
}
public override ECFieldElement GetZCoord(int index)
@@ -1384,6 +1414,46 @@ namespace Org.BouncyCastle.Math.EC
return lhs.Equals(rhs);
}
+ protected override bool SatisfiesOrder()
+ {
+ ECCurve curve = Curve;
+ BigInteger cofactor = curve.Cofactor;
+ if (BigInteger.Two.Equals(cofactor))
+ {
+ /*
+ * Check that the trace of (X + A) is 0, then there exists a solution to L^2 + L = X + A,
+ * and so a halving is possible, so this point is the double of another.
+ */
+ ECPoint N = this.Normalize();
+ ECFieldElement X = N.AffineXCoord;
+ ECFieldElement rhs = X.Add(curve.A);
+ return ((AbstractF2mFieldElement)rhs).Trace() == 0;
+ }
+ if (BigInteger.ValueOf(4).Equals(cofactor))
+ {
+ /*
+ * Solve L^2 + L = X + A to find the half of this point, if it exists (fail if not).
+ * Generate both possibilities for the square of the half-point's x-coordinate (w),
+ * and check if Tr(w + A) == 0 for at least one; then a second halving is possible
+ * (see comments for cofactor 2 above), so this point is four times another.
+ *
+ * Note: Tr(x^2) == Tr(x).
+ */
+ ECPoint N = this.Normalize();
+ ECFieldElement X = N.AffineXCoord;
+ ECFieldElement lambda = ((AbstractF2mCurve)curve).SolveQuadraticEquation(X.Add(curve.A));
+ if (lambda == null)
+ return false;
+
+ ECFieldElement w = X.Multiply(lambda).Add(N.AffineYCoord);
+ ECFieldElement t = w.Add(curve.A);
+ return ((AbstractF2mFieldElement)t).Trace() == 0
+ || ((AbstractF2mFieldElement)(t.Add(X))).Trace() == 0;
+ }
+
+ return base.SatisfiesOrder();
+ }
+
public override ECPoint ScaleX(ECFieldElement scale)
{
if (this.IsInfinity)
@@ -1529,6 +1599,7 @@ namespace Org.BouncyCastle.Math.EC
* @param x x point
* @param y y point
*/
+ [Obsolete("Use ECCurve.CreatePoint to construct points")]
public F2mPoint(
ECCurve curve,
ECFieldElement x,
@@ -1543,6 +1614,7 @@ namespace Org.BouncyCastle.Math.EC
* @param y y point
* @param withCompression true if encode with point compression.
*/
+ [Obsolete("Per-point compression property will be removed, see GetEncoded(bool)")]
public F2mPoint(
ECCurve curve,
ECFieldElement x,
@@ -1573,19 +1645,9 @@ namespace Org.BouncyCastle.Math.EC
{
}
- /**
- * Constructor for point at infinity
- */
- [Obsolete("Use ECCurve.Infinity property")]
- public F2mPoint(
- ECCurve curve)
- : this(curve, null, null)
- {
- }
-
protected override ECPoint Detach()
{
- return new F2mPoint(null, AffineXCoord, AffineYCoord);
+ return new F2mPoint(null, AffineXCoord, AffineYCoord, false);
}
public override ECFieldElement YCoord
diff --git a/crypto/src/math/ec/custom/djb/Curve25519FieldElement.cs b/crypto/src/math/ec/custom/djb/Curve25519FieldElement.cs
index 732e9e468..37256a550 100644
--- a/crypto/src/math/ec/custom/djb/Curve25519FieldElement.cs
+++ b/crypto/src/math/ec/custom/djb/Curve25519FieldElement.cs
@@ -6,7 +6,7 @@ using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Math.EC.Custom.Djb
{
internal class Curve25519FieldElement
- : ECFieldElement
+ : AbstractFpFieldElement
{
public static readonly BigInteger Q = Curve25519.q;
diff --git a/crypto/src/math/ec/custom/gm/SM2P256V1FieldElement.cs b/crypto/src/math/ec/custom/gm/SM2P256V1FieldElement.cs
index 4f6428f9e..087a040f2 100644
--- a/crypto/src/math/ec/custom/gm/SM2P256V1FieldElement.cs
+++ b/crypto/src/math/ec/custom/gm/SM2P256V1FieldElement.cs
@@ -6,7 +6,7 @@ using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Math.EC.Custom.GM
{
internal class SM2P256V1FieldElement
- : ECFieldElement
+ : AbstractFpFieldElement
{
public static readonly BigInteger Q = SM2P256V1Curve.q;
diff --git a/crypto/src/math/ec/custom/sec/SecP128R1FieldElement.cs b/crypto/src/math/ec/custom/sec/SecP128R1FieldElement.cs
index fa7951d5d..5912a87e8 100644
--- a/crypto/src/math/ec/custom/sec/SecP128R1FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecP128R1FieldElement.cs
@@ -6,7 +6,7 @@ using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Math.EC.Custom.Sec
{
internal class SecP128R1FieldElement
- : ECFieldElement
+ : AbstractFpFieldElement
{
public static readonly BigInteger Q = SecP128R1Curve.q;
diff --git a/crypto/src/math/ec/custom/sec/SecP160R1FieldElement.cs b/crypto/src/math/ec/custom/sec/SecP160R1FieldElement.cs
index d1fc75644..3ab11bdae 100644
--- a/crypto/src/math/ec/custom/sec/SecP160R1FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecP160R1FieldElement.cs
@@ -6,7 +6,7 @@ using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Math.EC.Custom.Sec
{
internal class SecP160R1FieldElement
- : ECFieldElement
+ : AbstractFpFieldElement
{
public static readonly BigInteger Q = SecP160R1Curve.q;
diff --git a/crypto/src/math/ec/custom/sec/SecP160R2FieldElement.cs b/crypto/src/math/ec/custom/sec/SecP160R2FieldElement.cs
index bdb5245b2..9d8131857 100644
--- a/crypto/src/math/ec/custom/sec/SecP160R2FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecP160R2FieldElement.cs
@@ -6,7 +6,7 @@ using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Math.EC.Custom.Sec
{
internal class SecP160R2FieldElement
- : ECFieldElement
+ : AbstractFpFieldElement
{
public static readonly BigInteger Q = SecP160R2Curve.q;
diff --git a/crypto/src/math/ec/custom/sec/SecP192K1FieldElement.cs b/crypto/src/math/ec/custom/sec/SecP192K1FieldElement.cs
index dce377035..54b72573c 100644
--- a/crypto/src/math/ec/custom/sec/SecP192K1FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecP192K1FieldElement.cs
@@ -7,7 +7,7 @@ using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Math.EC.Custom.Sec
{
internal class SecP192K1FieldElement
- : ECFieldElement
+ : AbstractFpFieldElement
{
public static readonly BigInteger Q = SecP192K1Curve.q;
diff --git a/crypto/src/math/ec/custom/sec/SecP192R1FieldElement.cs b/crypto/src/math/ec/custom/sec/SecP192R1FieldElement.cs
index 45bcb00f0..f3e12b542 100644
--- a/crypto/src/math/ec/custom/sec/SecP192R1FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecP192R1FieldElement.cs
@@ -6,7 +6,7 @@ using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Math.EC.Custom.Sec
{
internal class SecP192R1FieldElement
- : ECFieldElement
+ : AbstractFpFieldElement
{
public static readonly BigInteger Q = SecP192R1Curve.q;
diff --git a/crypto/src/math/ec/custom/sec/SecP224K1FieldElement.cs b/crypto/src/math/ec/custom/sec/SecP224K1FieldElement.cs
index fec07436a..ef53a88d6 100644
--- a/crypto/src/math/ec/custom/sec/SecP224K1FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecP224K1FieldElement.cs
@@ -7,7 +7,7 @@ using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Math.EC.Custom.Sec
{
internal class SecP224K1FieldElement
- : ECFieldElement
+ : AbstractFpFieldElement
{
public static readonly BigInteger Q = SecP224K1Curve.q;
diff --git a/crypto/src/math/ec/custom/sec/SecP224R1FieldElement.cs b/crypto/src/math/ec/custom/sec/SecP224R1FieldElement.cs
index 2b9a06564..5780b7481 100644
--- a/crypto/src/math/ec/custom/sec/SecP224R1FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecP224R1FieldElement.cs
@@ -6,7 +6,7 @@ using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Math.EC.Custom.Sec
{
internal class SecP224R1FieldElement
- : ECFieldElement
+ : AbstractFpFieldElement
{
public static readonly BigInteger Q = SecP224R1Curve.q;
diff --git a/crypto/src/math/ec/custom/sec/SecP256K1FieldElement.cs b/crypto/src/math/ec/custom/sec/SecP256K1FieldElement.cs
index 473113d0f..9a604bdb7 100644
--- a/crypto/src/math/ec/custom/sec/SecP256K1FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecP256K1FieldElement.cs
@@ -7,7 +7,7 @@ using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Math.EC.Custom.Sec
{
internal class SecP256K1FieldElement
- : ECFieldElement
+ : AbstractFpFieldElement
{
public static readonly BigInteger Q = SecP256K1Curve.q;
diff --git a/crypto/src/math/ec/custom/sec/SecP256R1FieldElement.cs b/crypto/src/math/ec/custom/sec/SecP256R1FieldElement.cs
index d7838aead..808e99ea6 100644
--- a/crypto/src/math/ec/custom/sec/SecP256R1FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecP256R1FieldElement.cs
@@ -6,7 +6,7 @@ using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Math.EC.Custom.Sec
{
internal class SecP256R1FieldElement
- : ECFieldElement
+ : AbstractFpFieldElement
{
public static readonly BigInteger Q = SecP256R1Curve.q;
diff --git a/crypto/src/math/ec/custom/sec/SecP384R1FieldElement.cs b/crypto/src/math/ec/custom/sec/SecP384R1FieldElement.cs
index 18d48a57d..7eedccae6 100644
--- a/crypto/src/math/ec/custom/sec/SecP384R1FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecP384R1FieldElement.cs
@@ -6,7 +6,7 @@ using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Math.EC.Custom.Sec
{
internal class SecP384R1FieldElement
- : ECFieldElement
+ : AbstractFpFieldElement
{
public static readonly BigInteger Q = SecP384R1Curve.q;
diff --git a/crypto/src/math/ec/custom/sec/SecP521R1FieldElement.cs b/crypto/src/math/ec/custom/sec/SecP521R1FieldElement.cs
index 6f02a7eb5..96658a8e5 100644
--- a/crypto/src/math/ec/custom/sec/SecP521R1FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecP521R1FieldElement.cs
@@ -6,7 +6,7 @@ using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Math.EC.Custom.Sec
{
internal class SecP521R1FieldElement
- : ECFieldElement
+ : AbstractFpFieldElement
{
public static readonly BigInteger Q = SecP521R1Curve.q;
diff --git a/crypto/src/math/ec/custom/sec/SecT113FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT113FieldElement.cs
index 9ba25d987..bb87b00fc 100644
--- a/crypto/src/math/ec/custom/sec/SecT113FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecT113FieldElement.cs
@@ -6,7 +6,7 @@ using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Math.EC.Custom.Sec
{
internal class SecT113FieldElement
- : ECFieldElement
+ : AbstractF2mFieldElement
{
protected internal readonly ulong[] x;
@@ -150,6 +150,11 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
return new SecT113FieldElement(z);
}
+ public override int Trace()
+ {
+ return (int)SecT113Field.Trace(x);
+ }
+
public override ECFieldElement Invert()
{
ulong[] z = Nat128.Create64();
diff --git a/crypto/src/math/ec/custom/sec/SecT131FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT131FieldElement.cs
index c38e8eb0a..f96c7ca39 100644
--- a/crypto/src/math/ec/custom/sec/SecT131FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecT131FieldElement.cs
@@ -6,7 +6,7 @@ using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Math.EC.Custom.Sec
{
internal class SecT131FieldElement
- : ECFieldElement
+ : AbstractF2mFieldElement
{
protected internal readonly ulong[] x;
@@ -150,6 +150,11 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
return new SecT131FieldElement(z);
}
+ public override int Trace()
+ {
+ return (int)SecT131Field.Trace(x);
+ }
+
public override ECFieldElement Invert()
{
ulong[] z = Nat192.Create64();
diff --git a/crypto/src/math/ec/custom/sec/SecT163FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT163FieldElement.cs
index 07bd07652..903645999 100644
--- a/crypto/src/math/ec/custom/sec/SecT163FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecT163FieldElement.cs
@@ -6,7 +6,7 @@ using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Math.EC.Custom.Sec
{
internal class SecT163FieldElement
- : ECFieldElement
+ : AbstractF2mFieldElement
{
protected internal readonly ulong[] x;
@@ -150,6 +150,11 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
return new SecT163FieldElement(z);
}
+ public override int Trace()
+ {
+ return (int)SecT163Field.Trace(x);
+ }
+
public override ECFieldElement Invert()
{
ulong[] z = Nat192.Create64();
diff --git a/crypto/src/math/ec/custom/sec/SecT193FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT193FieldElement.cs
index d04e68d3f..9813bcb01 100644
--- a/crypto/src/math/ec/custom/sec/SecT193FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecT193FieldElement.cs
@@ -6,7 +6,7 @@ using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Math.EC.Custom.Sec
{
internal class SecT193FieldElement
- : ECFieldElement
+ : AbstractF2mFieldElement
{
protected internal readonly ulong[] x;
@@ -150,6 +150,11 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
return new SecT193FieldElement(z);
}
+ public override int Trace()
+ {
+ return (int)SecT193Field.Trace(x);
+ }
+
public override ECFieldElement Invert()
{
ulong[] z = Nat256.Create64();
diff --git a/crypto/src/math/ec/custom/sec/SecT233FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT233FieldElement.cs
index 64d09bd6d..fbfe35e13 100644
--- a/crypto/src/math/ec/custom/sec/SecT233FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecT233FieldElement.cs
@@ -6,7 +6,7 @@ using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Math.EC.Custom.Sec
{
internal class SecT233FieldElement
- : ECFieldElement
+ : AbstractF2mFieldElement
{
protected internal readonly ulong[] x;
@@ -150,6 +150,11 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
return new SecT233FieldElement(z);
}
+ public override int Trace()
+ {
+ return (int)SecT233Field.Trace(x);
+ }
+
public override ECFieldElement Invert()
{
ulong[] z = Nat256.Create64();
diff --git a/crypto/src/math/ec/custom/sec/SecT239FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT239FieldElement.cs
index 18563f746..b1b58e89b 100644
--- a/crypto/src/math/ec/custom/sec/SecT239FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecT239FieldElement.cs
@@ -6,7 +6,7 @@ using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Math.EC.Custom.Sec
{
internal class SecT239FieldElement
- : ECFieldElement
+ : AbstractF2mFieldElement
{
protected internal readonly ulong[] x;
@@ -150,6 +150,11 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
return new SecT239FieldElement(z);
}
+ public override int Trace()
+ {
+ return (int)SecT239Field.Trace(x);
+ }
+
public override ECFieldElement Invert()
{
ulong[] z = Nat256.Create64();
diff --git a/crypto/src/math/ec/custom/sec/SecT283FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT283FieldElement.cs
index b054bedfb..c1bb2e30c 100644
--- a/crypto/src/math/ec/custom/sec/SecT283FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecT283FieldElement.cs
@@ -6,7 +6,7 @@ using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Math.EC.Custom.Sec
{
internal class SecT283FieldElement
- : ECFieldElement
+ : AbstractF2mFieldElement
{
protected internal readonly ulong[] x;
@@ -150,6 +150,11 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
return new SecT283FieldElement(z);
}
+ public override int Trace()
+ {
+ return (int)SecT283Field.Trace(x);
+ }
+
public override ECFieldElement Invert()
{
ulong[] z = Nat320.Create64();
diff --git a/crypto/src/math/ec/custom/sec/SecT409FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT409FieldElement.cs
index 7076905bb..68a63312d 100644
--- a/crypto/src/math/ec/custom/sec/SecT409FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecT409FieldElement.cs
@@ -6,7 +6,7 @@ using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Math.EC.Custom.Sec
{
internal class SecT409FieldElement
- : ECFieldElement
+ : AbstractF2mFieldElement
{
protected internal readonly ulong[] x;
@@ -150,6 +150,11 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
return new SecT409FieldElement(z);
}
+ public override int Trace()
+ {
+ return (int)SecT409Field.Trace(x);
+ }
+
public override ECFieldElement Invert()
{
ulong[] z = Nat448.Create64();
diff --git a/crypto/src/math/ec/custom/sec/SecT571FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT571FieldElement.cs
index 5f28c01be..c9f3aa5c0 100644
--- a/crypto/src/math/ec/custom/sec/SecT571FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecT571FieldElement.cs
@@ -6,7 +6,7 @@ using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Math.EC.Custom.Sec
{
internal class SecT571FieldElement
- : ECFieldElement
+ : AbstractF2mFieldElement
{
protected internal readonly ulong[] x;
@@ -150,6 +150,11 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
return new SecT571FieldElement(z);
}
+ public override int Trace()
+ {
+ return (int)SecT571Field.Trace(x);
+ }
+
public override ECFieldElement Invert()
{
ulong[] z = Nat576.Create64();
diff --git a/crypto/src/math/ec/multiplier/AbstractECMultiplier.cs b/crypto/src/math/ec/multiplier/AbstractECMultiplier.cs
index 517881323..c2580c852 100644
--- a/crypto/src/math/ec/multiplier/AbstractECMultiplier.cs
+++ b/crypto/src/math/ec/multiplier/AbstractECMultiplier.cs
@@ -16,9 +16,14 @@
* Although the various multipliers ought not to produce invalid output under normal
* circumstances, a final check here is advised to guard against fault attacks.
*/
- return ECAlgorithms.ValidatePoint(result);
+ return CheckResult(result);
}
protected abstract ECPoint MultiplyPositive(ECPoint p, BigInteger k);
+
+ protected virtual ECPoint CheckResult(ECPoint p)
+ {
+ return ECAlgorithms.ImplCheckResult(p);
+ }
}
}
diff --git a/crypto/src/math/ec/multiplier/FixedPointCombMultiplier.cs b/crypto/src/math/ec/multiplier/FixedPointCombMultiplier.cs
index adaedb809..505832442 100644
--- a/crypto/src/math/ec/multiplier/FixedPointCombMultiplier.cs
+++ b/crypto/src/math/ec/multiplier/FixedPointCombMultiplier.cs
@@ -52,11 +52,5 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
return R.Add(info.Offset);
}
-
- [Obsolete("Is no longer used; remove any overrides in subclasses.")]
- protected virtual int GetWidthForCombSize(int combSize)
- {
- return combSize > 257 ? 6 : 5;
- }
}
}
diff --git a/crypto/src/math/ec/multiplier/FixedPointPreCompInfo.cs b/crypto/src/math/ec/multiplier/FixedPointPreCompInfo.cs
index 4c0b404df..5d6af9e5d 100644
--- a/crypto/src/math/ec/multiplier/FixedPointPreCompInfo.cs
+++ b/crypto/src/math/ec/multiplier/FixedPointPreCompInfo.cs
@@ -11,13 +11,6 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
protected ECPoint m_offset = null;
/**
- * Array holding the precomputed <code>ECPoint</code>s used for a fixed
- * point multiplication.
- */
- [Obsolete("Will be removed")]
- protected ECPoint[] m_preComp = null;
-
- /**
* Lookup table for the precomputed <code>ECPoint</code>s used for a fixed point multiplication.
*/
protected ECLookupTable m_lookupTable = null;
@@ -41,13 +34,6 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
set { this.m_offset = value; }
}
- [Obsolete("Use 'LookupTable' property instead.")]
- public virtual ECPoint[] PreComp
- {
- get { return m_preComp; }
- set { this.m_preComp = value; }
- }
-
public virtual int Width
{
get { return m_width; }
diff --git a/crypto/src/math/ec/multiplier/FixedPointUtilities.cs b/crypto/src/math/ec/multiplier/FixedPointUtilities.cs
index cc7203314..88f178e24 100644
--- a/crypto/src/math/ec/multiplier/FixedPointUtilities.cs
+++ b/crypto/src/math/ec/multiplier/FixedPointUtilities.cs
@@ -14,36 +14,40 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
public static FixedPointPreCompInfo GetFixedPointPreCompInfo(PreCompInfo preCompInfo)
{
- if ((preCompInfo != null) && (preCompInfo is FixedPointPreCompInfo))
- {
- return (FixedPointPreCompInfo)preCompInfo;
- }
-
- return new FixedPointPreCompInfo();
+ return preCompInfo as FixedPointPreCompInfo;
}
- [Obsolete("Use 'Precompute(ECPoint)' instead, as minWidth parameter is now ignored")]
- public static FixedPointPreCompInfo Precompute(ECPoint p, int minWidth)
+ public static FixedPointPreCompInfo Precompute(ECPoint p)
{
- return Precompute(p);
+ return (FixedPointPreCompInfo)p.Curve.Precompute(p, PRECOMP_NAME, new FixedPointCallback(p));
}
- public static FixedPointPreCompInfo Precompute(ECPoint p)
+ private class FixedPointCallback
+ : IPreCompCallback
{
- ECCurve c = p.Curve;
- int minWidth = GetCombSize(c) > 257 ? 6 : 5;
+ private readonly ECPoint m_p;
- int n = 1 << minWidth;
- FixedPointPreCompInfo info = GetFixedPointPreCompInfo(c.GetPreCompInfo(p, PRECOMP_NAME));
- ECPoint[] lookupTable = info.PreComp;
+ internal FixedPointCallback(ECPoint p)
+ {
+ this.m_p = p;
+ }
- if (lookupTable == null || lookupTable.Length < n)
+ public PreCompInfo Precompute(PreCompInfo existing)
{
- int bits = GetCombSize(c);
+ FixedPointPreCompInfo existingFP = (existing is FixedPointPreCompInfo) ? (FixedPointPreCompInfo)existing : null;
+
+ ECCurve c = m_p.Curve;
+ int bits = FixedPointUtilities.GetCombSize(c);
+ int minWidth = bits > 250 ? 6 : 5;
+ int n = 1 << minWidth;
+
+ if (CheckExisting(existingFP, n))
+ return existingFP;
+
int d = (bits + minWidth - 1) / minWidth;
ECPoint[] pow2Table = new ECPoint[minWidth + 1];
- pow2Table[0] = p;
+ pow2Table[0] = m_p;
for (int i = 1; i < minWidth; ++i)
{
pow2Table[i] = pow2Table[i - 1].TimesPow2(d);
@@ -53,8 +57,8 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
pow2Table[minWidth] = pow2Table[0].Subtract(pow2Table[1]);
c.NormalizeAll(pow2Table);
-
- lookupTable = new ECPoint[n];
+
+ ECPoint[] lookupTable = new ECPoint[n];
lookupTable[0] = pow2Table[0];
for (int bit = minWidth - 1; bit >= 0; --bit)
@@ -70,15 +74,22 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
c.NormalizeAll(lookupTable);
- info.LookupTable = c.CreateCacheSafeLookupTable(lookupTable, 0, lookupTable.Length);
- info.Offset = pow2Table[minWidth];
- info.PreComp = lookupTable;
- info.Width = minWidth;
+ FixedPointPreCompInfo result = new FixedPointPreCompInfo();
+ result.LookupTable = c.CreateCacheSafeLookupTable(lookupTable, 0, lookupTable.Length);
+ result.Offset = pow2Table[minWidth];
+ result.Width = minWidth;
+ return result;
+ }
- c.SetPreCompInfo(p, PRECOMP_NAME, info);
+ private bool CheckExisting(FixedPointPreCompInfo existingFP, int n)
+ {
+ return existingFP != null && CheckTable(existingFP.LookupTable, n);
}
- return info;
+ private bool CheckTable(ECLookupTable table, int n)
+ {
+ return table != null && table.Size >= n;
+ }
}
}
}
diff --git a/crypto/src/math/ec/multiplier/IPreCompCallback.cs b/crypto/src/math/ec/multiplier/IPreCompCallback.cs
new file mode 100644
index 000000000..e64ae834d
--- /dev/null
+++ b/crypto/src/math/ec/multiplier/IPreCompCallback.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Multiplier
+{
+ public interface IPreCompCallback
+ {
+ PreCompInfo Precompute(PreCompInfo existing);
+ }
+}
diff --git a/crypto/src/math/ec/multiplier/ValidityPreCompInfo.cs b/crypto/src/math/ec/multiplier/ValidityPreCompInfo.cs
new file mode 100644
index 000000000..7ec2cbb95
--- /dev/null
+++ b/crypto/src/math/ec/multiplier/ValidityPreCompInfo.cs
@@ -0,0 +1,44 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Multiplier
+{
+ internal class ValidityPreCompInfo
+ : PreCompInfo
+ {
+ internal static readonly string PRECOMP_NAME = "bc_validity";
+
+ private bool failed = false;
+ private bool curveEquationPassed = false;
+ private bool orderPassed = false;
+
+ internal bool HasFailed()
+ {
+ return failed;
+ }
+
+ internal void ReportFailed()
+ {
+ failed = true;
+ }
+
+ internal bool HasCurveEquationPassed()
+ {
+ return curveEquationPassed;
+ }
+
+ internal void ReportCurveEquationPassed()
+ {
+ curveEquationPassed = true;
+ }
+
+ internal bool HasOrderPassed()
+ {
+ return orderPassed;
+ }
+
+ internal void ReportOrderPassed()
+ {
+ orderPassed = true;
+ }
+ }
+}
diff --git a/crypto/src/math/ec/multiplier/WNafUtilities.cs b/crypto/src/math/ec/multiplier/WNafUtilities.cs
index 7d565dfbd..e893abd49 100644
--- a/crypto/src/math/ec/multiplier/WNafUtilities.cs
+++ b/crypto/src/math/ec/multiplier/WNafUtilities.cs
@@ -287,12 +287,7 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
public static WNafPreCompInfo GetWNafPreCompInfo(PreCompInfo preCompInfo)
{
- if ((preCompInfo != null) && (preCompInfo is WNafPreCompInfo))
- {
- return (WNafPreCompInfo)preCompInfo;
- }
-
- return new WNafPreCompInfo();
+ return preCompInfo as WNafPreCompInfo;
}
/**
@@ -333,106 +328,178 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
WNafPreCompInfo wnafPreCompP = Precompute(p, width, includeNegated);
ECPoint q = pointMap.Map(p);
- WNafPreCompInfo wnafPreCompQ = GetWNafPreCompInfo(c.GetPreCompInfo(q, PRECOMP_NAME));
+ c.Precompute(q, PRECOMP_NAME, new MapPointCallback(wnafPreCompP, includeNegated, pointMap));
+ return q;
+ }
- ECPoint twiceP = wnafPreCompP.Twice;
- if (twiceP != null)
- {
- ECPoint twiceQ = pointMap.Map(twiceP);
- wnafPreCompQ.Twice = twiceQ;
- }
+ public static WNafPreCompInfo Precompute(ECPoint p, int width, bool includeNegated)
+ {
+ return (WNafPreCompInfo)p.Curve.Precompute(p, PRECOMP_NAME, new WNafCallback(p, width, includeNegated));
+ }
+
+ private static byte[] Trim(byte[] a, int length)
+ {
+ byte[] result = new byte[length];
+ Array.Copy(a, 0, result, 0, result.Length);
+ return result;
+ }
+
+ private static int[] Trim(int[] a, int length)
+ {
+ int[] result = new int[length];
+ Array.Copy(a, 0, result, 0, result.Length);
+ return result;
+ }
+
+ private static ECPoint[] ResizeTable(ECPoint[] a, int length)
+ {
+ ECPoint[] result = new ECPoint[length];
+ Array.Copy(a, 0, result, 0, a.Length);
+ return result;
+ }
+
+ private class MapPointCallback
+ : IPreCompCallback
+ {
+ private readonly WNafPreCompInfo m_wnafPreCompP;
+ private readonly bool m_includeNegated;
+ private readonly ECPointMap m_pointMap;
- ECPoint[] preCompP = wnafPreCompP.PreComp;
- ECPoint[] preCompQ = new ECPoint[preCompP.Length];
- for (int i = 0; i < preCompP.Length; ++i)
+ internal MapPointCallback(WNafPreCompInfo wnafPreCompP, bool includeNegated, ECPointMap pointMap)
{
- preCompQ[i] = pointMap.Map(preCompP[i]);
+ this.m_wnafPreCompP = wnafPreCompP;
+ this.m_includeNegated = includeNegated;
+ this.m_pointMap = pointMap;
}
- wnafPreCompQ.PreComp = preCompQ;
- if (includeNegated)
+ public PreCompInfo Precompute(PreCompInfo existing)
{
- ECPoint[] preCompNegQ = new ECPoint[preCompQ.Length];
- for (int i = 0; i < preCompNegQ.Length; ++i)
+ WNafPreCompInfo result = new WNafPreCompInfo();
+
+ ECPoint twiceP = m_wnafPreCompP.Twice;
+ if (twiceP != null)
{
- preCompNegQ[i] = preCompQ[i].Negate();
+ ECPoint twiceQ = m_pointMap.Map(twiceP);
+ result.Twice = twiceQ;
}
- wnafPreCompQ.PreCompNeg = preCompNegQ;
- }
- c.SetPreCompInfo(q, PRECOMP_NAME, wnafPreCompQ);
+ ECPoint[] preCompP = m_wnafPreCompP.PreComp;
+ ECPoint[] preCompQ = new ECPoint[preCompP.Length];
+ for (int i = 0; i < preCompP.Length; ++i)
+ {
+ preCompQ[i] = m_pointMap.Map(preCompP[i]);
+ }
+ result.PreComp = preCompQ;
- return q;
+ if (m_includeNegated)
+ {
+ ECPoint[] preCompNegQ = new ECPoint[preCompQ.Length];
+ for (int i = 0; i < preCompNegQ.Length; ++i)
+ {
+ preCompNegQ[i] = preCompQ[i].Negate();
+ }
+ result.PreCompNeg = preCompNegQ;
+ }
+
+ return result;
+ }
}
- public static WNafPreCompInfo Precompute(ECPoint p, int width, bool includeNegated)
+ private class WNafCallback
+ : IPreCompCallback
{
- ECCurve c = p.Curve;
- WNafPreCompInfo wnafPreCompInfo = GetWNafPreCompInfo(c.GetPreCompInfo(p, PRECOMP_NAME));
+ private readonly ECPoint m_p;
+ private readonly int m_width;
+ private readonly bool m_includeNegated;
- int iniPreCompLen = 0, reqPreCompLen = 1 << System.Math.Max(0, width - 2);
-
- ECPoint[] preComp = wnafPreCompInfo.PreComp;
- if (preComp == null)
+ internal WNafCallback(ECPoint p, int width, bool includeNegated)
{
- preComp = EMPTY_POINTS;
- }
- else
- {
- iniPreCompLen = preComp.Length;
+ this.m_p = p;
+ this.m_width = width;
+ this.m_includeNegated = includeNegated;
}
- if (iniPreCompLen < reqPreCompLen)
+ public PreCompInfo Precompute(PreCompInfo existing)
{
- preComp = ResizeTable(preComp, reqPreCompLen);
+ WNafPreCompInfo existingWNaf = existing as WNafPreCompInfo;
+
+ int reqPreCompLen = 1 << System.Math.Max(0, m_width - 2);
+
+ if (CheckExisting(existingWNaf, reqPreCompLen, m_includeNegated))
+ return existingWNaf;
- if (reqPreCompLen == 1)
+ 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[0] = p.Normalize();
+ preComp = EMPTY_POINTS;
}
else
{
- int curPreCompLen = iniPreCompLen;
- if (curPreCompLen == 0)
- {
- preComp[0] = p;
- curPreCompLen = 1;
- }
+ iniPreCompLen = preComp.Length;
+ }
- ECFieldElement iso = null;
+ if (iniPreCompLen < reqPreCompLen)
+ {
+ preComp = WNafUtilities.ResizeTable(preComp, reqPreCompLen);
- if (reqPreCompLen == 2)
+ if (reqPreCompLen == 1)
{
- preComp[1] = p.ThreeTimes();
+ preComp[0] = m_p.Normalize();
}
else
{
- ECPoint twiceP = wnafPreCompInfo.Twice, last = preComp[curPreCompLen - 1];
- if (twiceP == null)
+ int curPreCompLen = iniPreCompLen;
+ if (curPreCompLen == 0)
+ {
+ preComp[0] = m_p;
+ curPreCompLen = 1;
+ }
+
+ ECFieldElement iso = null;
+
+ if (reqPreCompLen == 2)
+ {
+ preComp[1] = m_p.ThreeTimes();
+ }
+ else
{
- twiceP = preComp[0].Twice();
- wnafPreCompInfo.Twice = twiceP;
-
- /*
- * 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)
+ ECPoint isoTwiceP = twiceP, last = preComp[curPreCompLen - 1];
+ if (isoTwiceP == null)
{
- switch (c.CoordinateSystem)
+ 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);
- twiceP = c.CreatePoint(twiceP.XCoord.ToBigInteger(),
+ isoTwiceP = c.CreatePoint(twiceP.XCoord.ToBigInteger(),
twiceP.YCoord.ToBigInteger());
ECFieldElement iso2 = iso.Square(), iso3 = iso2.Multiply(iso);
@@ -444,81 +511,69 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
}
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(twiceP);
+ 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);
+ /*
+ * Having oft-used operands in affine form makes operations faster.
+ */
+ c.NormalizeAll(preComp, iniPreCompLen, reqPreCompLen - iniPreCompLen, iso);
+ }
}
- }
-
- wnafPreCompInfo.PreComp = preComp;
-
- if (includeNegated)
- {
- ECPoint[] preCompNeg = wnafPreCompInfo.PreCompNeg;
- int pos;
- if (preCompNeg == null)
- {
- pos = 0;
- preCompNeg = new ECPoint[reqPreCompLen];
- }
- else
+ if (m_includeNegated)
{
- pos = preCompNeg.Length;
- if (pos < reqPreCompLen)
+ int pos;
+ if (preCompNeg == null)
{
- preCompNeg = ResizeTable(preCompNeg, reqPreCompLen);
+ 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;
+ while (pos < reqPreCompLen)
+ {
+ preCompNeg[pos] = preComp[pos].Negate();
+ ++pos;
+ }
}
- wnafPreCompInfo.PreCompNeg = preCompNeg;
+ WNafPreCompInfo result = new WNafPreCompInfo();
+ result.PreComp = preComp;
+ result.PreCompNeg = preCompNeg;
+ result.Twice = twiceP;
+ return result;
}
- c.SetPreCompInfo(p, PRECOMP_NAME, wnafPreCompInfo);
-
- return wnafPreCompInfo;
- }
-
- private static byte[] Trim(byte[] a, int length)
- {
- byte[] result = new byte[length];
- Array.Copy(a, 0, result, 0, result.Length);
- return result;
- }
-
- private static int[] Trim(int[] a, int length)
- {
- int[] result = new int[length];
- Array.Copy(a, 0, result, 0, result.Length);
- return result;
- }
+ private bool CheckExisting(WNafPreCompInfo existingWNaf, int reqPreCompLen, bool includeNegated)
+ {
+ return existingWNaf != null
+ && CheckTable(existingWNaf.PreComp, reqPreCompLen)
+ && (!includeNegated || CheckTable(existingWNaf.PreCompNeg, reqPreCompLen));
+ }
- private static ECPoint[] ResizeTable(ECPoint[] a, int length)
- {
- ECPoint[] result = new ECPoint[length];
- Array.Copy(a, 0, result, 0, a.Length);
- return result;
+ private bool CheckTable(ECPoint[] table, int reqLen)
+ {
+ return table != null && table.Length >= reqLen;
+ }
}
}
}
diff --git a/crypto/src/math/ec/multiplier/WTauNafMultiplier.cs b/crypto/src/math/ec/multiplier/WTauNafMultiplier.cs
index 1e7ddae91..4dce54440 100644
--- a/crypto/src/math/ec/multiplier/WTauNafMultiplier.cs
+++ b/crypto/src/math/ec/multiplier/WTauNafMultiplier.cs
@@ -36,7 +36,7 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
ZTauElement rho = Tnaf.PartModReduction(k, m, a, s, mu, (sbyte)10);
- return MultiplyWTnaf(p, rho, curve.GetPreCompInfo(p, PRECOMP_NAME), a, mu);
+ return MultiplyWTnaf(p, rho, a, mu);
}
/**
@@ -50,7 +50,7 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
* @return <code>p</code> multiplied by <code>λ</code>.
*/
private AbstractF2mPoint MultiplyWTnaf(AbstractF2mPoint p, ZTauElement lambda,
- PreCompInfo preCompInfo, sbyte a, sbyte mu)
+ sbyte a, sbyte mu)
{
ZTauElement[] alpha = (a == 0) ? Tnaf.Alpha0 : Tnaf.Alpha1;
@@ -59,7 +59,7 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
sbyte[]u = Tnaf.TauAdicWNaf(mu, lambda, Tnaf.Width,
BigInteger.ValueOf(Tnaf.Pow2Width), tw, alpha);
- return MultiplyFromWTnaf(p, u, preCompInfo);
+ return MultiplyFromWTnaf(p, u);
}
/**
@@ -71,24 +71,14 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
* @param u The the WTNAF of <code>λ</code>..
* @return <code>λ * p</code>
*/
- private static AbstractF2mPoint MultiplyFromWTnaf(AbstractF2mPoint p, sbyte[] u, PreCompInfo preCompInfo)
+ private static AbstractF2mPoint MultiplyFromWTnaf(AbstractF2mPoint p, sbyte[] u)
{
AbstractF2mCurve curve = (AbstractF2mCurve)p.Curve;
sbyte a = (sbyte)curve.A.ToBigInteger().IntValue;
- AbstractF2mPoint[] pu;
- if ((preCompInfo == null) || !(preCompInfo is WTauNafPreCompInfo))
- {
- pu = Tnaf.GetPreComp(p, a);
-
- WTauNafPreCompInfo pre = new WTauNafPreCompInfo();
- pre.PreComp = pu;
- curve.SetPreCompInfo(p, PRECOMP_NAME, pre);
- }
- else
- {
- pu = ((WTauNafPreCompInfo)preCompInfo).PreComp;
- }
+ WTauNafCallback callback = new WTauNafCallback(p, a);
+ WTauNafPreCompInfo preCompInfo = (WTauNafPreCompInfo)curve.Precompute(p, PRECOMP_NAME, callback);
+ AbstractF2mPoint[] pu = preCompInfo.PreComp;
// TODO Include negations in precomp (optionally) and use from here
AbstractF2mPoint[] puNeg = new AbstractF2mPoint[pu.Length];
@@ -121,5 +111,28 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
}
return q;
}
+
+ private class WTauNafCallback
+ : IPreCompCallback
+ {
+ private readonly AbstractF2mPoint m_p;
+ private readonly sbyte m_a;
+
+ internal WTauNafCallback(AbstractF2mPoint p, sbyte a)
+ {
+ this.m_p = p;
+ this.m_a = a;
+ }
+
+ public PreCompInfo Precompute(PreCompInfo existing)
+ {
+ if (existing is WTauNafPreCompInfo)
+ return existing;
+
+ WTauNafPreCompInfo result = new WTauNafPreCompInfo();
+ result.PreComp = Tnaf.GetPreComp(m_p, m_a);
+ return result;
+ }
+ }
}
}
|