diff options
Diffstat (limited to 'crypto/src/math/ec/ECPoint.cs')
-rw-r--r-- | crypto/src/math/ec/ECPoint.cs | 610 |
1 files changed, 474 insertions, 136 deletions
diff --git a/crypto/src/math/ec/ECPoint.cs b/crypto/src/math/ec/ECPoint.cs index 7a4450ac1..86134f80c 100644 --- a/crypto/src/math/ec/ECPoint.cs +++ b/crypto/src/math/ec/ECPoint.cs @@ -1,6 +1,7 @@ using System; using System.Collections; using System.Diagnostics; +using System.Text; using Org.BouncyCastle.Math.EC.Multiplier; @@ -51,24 +52,18 @@ namespace Org.BouncyCastle.Math.EC protected internal PreCompInfo m_preCompInfo = null; - protected ECPoint( - ECCurve curve, - ECFieldElement x, - ECFieldElement y, - bool withCompression) + protected ECPoint(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression) + : this(curve, x, y, GetInitialZCoords(curve), withCompression) { - this.m_curve = curve; - this.m_x = x; - this.m_y = y; - this.m_withCompression = withCompression; } - protected ECPoint(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs) + internal ECPoint(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) { this.m_curve = curve; this.m_x = x; this.m_y = y; this.m_zs = zs; + this.m_withCompression = withCompression; } public virtual ECCurve Curve @@ -85,13 +80,85 @@ 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 m_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 + * @throws IllegalStateException if the point is not normalized + */ + public virtual ECFieldElement AffineXCoord + { + get + { + CheckNormalized(); + return XCoord; + } + } + + /** + * Returns the affine y-coordinate after checking that this point is normalized + * + * @return The affine y-coordinate of this point + * @throws IllegalStateException if the point is not normalized + */ + public virtual ECFieldElement AffineYCoord + { + get + { + CheckNormalized(); + return YCoord; + } + } + + /** + * Returns the x-coordinate. + * + * Caution: depending on the curve's coordinate system, this may not be the same value as in an + * affine coordinate system; use Normalize() to get a point where the coordinates have their + * affine values, or use AffineXCoord if you expect the point to already have been normalized. + * + * @return the x-coordinate of this point + */ + public virtual ECFieldElement XCoord + { + get { return m_x; } + } + + /** + * Returns the y-coordinate. + * + * Caution: depending on the curve's coordinate system, this may not be the same value as in an + * affine coordinate system; use Normalize() to get a point where the coordinates have their + * affine values, or use AffineYCoord if you expect the point to already have been normalized. + * + * @return the y-coordinate of this point + */ + public virtual ECFieldElement YCoord + { get { return m_y; } } @@ -112,6 +179,16 @@ namespace Org.BouncyCastle.Math.EC return copy; } + protected virtual ECFieldElement RawXCoord + { + get { return m_x; } + } + + protected virtual ECFieldElement RawYCoord + { + get { return m_y; } + } + protected virtual void CheckNormalized() { if (!IsNormalized()) @@ -124,8 +201,8 @@ namespace Org.BouncyCastle.Math.EC return coord == ECCurve.COORD_AFFINE || coord == ECCurve.COORD_LAMBDA_AFFINE - || IsInfinity; - //|| zs[0].isOne(); + || IsInfinity + || GetZCoord(0).IsOne; } /** @@ -163,27 +240,30 @@ namespace Org.BouncyCastle.Math.EC internal virtual ECPoint Normalize(ECFieldElement zInv) { - throw new InvalidOperationException("not a projective coordinate system"); - - //switch (this.CurveCoordinateSystem) - //{ - // case ECCurve.COORD_HOMOGENEOUS: - // case ECCurve.COORD_LAMBDA_PROJECTIVE: - // { - // return CreateScaledPoint(zInv, zInv); - // } - // case ECCurve.COORD_JACOBIAN: - // case ECCurve.COORD_JACOBIAN_CHUDNOVSKY: - // case ECCurve.COORD_JACOBIAN_MODIFIED: - // { - // ECFieldElement zInv2 = zInv.Square(), zInv3 = zInv2.Multiply(zInv); - // return CreateScaledPoint(zInv2, zInv3); - // } - // default: - // { - // throw new InvalidOperationException("not a projective coordinate system"); - // } - //} + switch (this.CurveCoordinateSystem) + { + case ECCurve.COORD_HOMOGENEOUS: + case ECCurve.COORD_LAMBDA_PROJECTIVE: + { + return CreateScaledPoint(zInv, zInv); + } + case ECCurve.COORD_JACOBIAN: + case ECCurve.COORD_JACOBIAN_CHUDNOVSKY: + case ECCurve.COORD_JACOBIAN_MODIFIED: + { + ECFieldElement zInv2 = zInv.Square(), zInv3 = zInv2.Multiply(zInv); + return CreateScaledPoint(zInv2, zInv3); + } + default: + { + throw new InvalidOperationException("not a projective coordinate system"); + } + } + } + + protected virtual ECPoint CreateScaledPoint(ECFieldElement sx, ECFieldElement sy) + { + return Curve.CreateRawPoint(RawXCoord.Multiply(sx), RawYCoord.Multiply(sy), IsCompressed); } public bool IsInfinity @@ -208,26 +288,87 @@ namespace Org.BouncyCastle.Math.EC if (null == other) return false; + ECCurve c1 = this.Curve, c2 = other.Curve; + bool n1 = (null == c1), n2 = (null == c2); bool i1 = IsInfinity, i2 = other.IsInfinity; + if (i1 || i2) { - return i1 && i2; + return (i1 && i2) && (n1 || n2 || c1.Equals(c2)); + } + + ECPoint p1 = this, p2 = other; + if (n1 && n2) + { + // Points with null curve are in affine form, so already normalized + } + else if (n1) + { + p2 = p2.Normalize(); + } + else if (n2) + { + p1 = p1.Normalize(); + } + else if (!c1.Equals(c2)) + { + return false; + } + else + { + // TODO Consider just requiring already normalized, to avoid silent performance degradation + + ECPoint[] points = new ECPoint[] { this, c1.ImportPoint(p2) }; + + // TODO This is a little strong, really only requires coZNormalizeAll to get Zs equal + c1.NormalizeAll(points); + + p1 = points[0]; + p2 = points[1]; } - return X.Equals(other.X) && Y.Equals(other.Y); + return p1.XCoord.Equals(p2.XCoord) && p1.YCoord.Equals(p2.YCoord); } public override int GetHashCode() { - int hc = 0; - if (!IsInfinity) + ECCurve c = this.Curve; + int hc = (null == c) ? 0 : ~c.GetHashCode(); + + if (!this.IsInfinity) { - hc ^= X.GetHashCode() * 17; - hc ^= Y.GetHashCode() * 257; + // TODO Consider just requiring already normalized, to avoid silent performance degradation + + ECPoint p = Normalize(); + + hc ^= p.XCoord.GetHashCode() * 17; + hc ^= p.YCoord.GetHashCode() * 257; } + return hc; } + public override string ToString() + { + if (this.IsInfinity) + { + return "INF"; + } + + StringBuilder sb = new StringBuilder(); + sb.Append('('); + sb.Append(RawXCoord); + sb.Append(','); + sb.Append(RawYCoord); + for (int i = 0; i < m_zs.Length; ++i) + { + sb.Append(','); + sb.Append(m_zs[i]); + } + sb.Append(')'); + return sb.ToString(); + } + public virtual byte[] GetEncoded() { return GetEncoded(m_withCompression); @@ -280,6 +421,11 @@ namespace Org.BouncyCastle.Math.EC { } + protected internal ECPointBase(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + : base(curve, x, y, zs, withCompression) + { + } + /** * return the field element encoded with point compression. (S 4.3.6) */ @@ -292,7 +438,7 @@ namespace Org.BouncyCastle.Math.EC ECPoint normed = Normalize(); - byte[] X = normed.X.GetEncoded(); + byte[] X = normed.XCoord.GetEncoded(); if (compressed) { @@ -302,7 +448,7 @@ namespace Org.BouncyCastle.Math.EC return PO; } - byte[] Y = normed.Y.GetEncoded(); + byte[] Y = normed.YCoord.GetEncoded(); { byte[] PO = new byte[X.Length + Y.Length + 1]; @@ -374,9 +520,14 @@ namespace Org.BouncyCastle.Math.EC throw new ArgumentException("Exactly one of the field elements is null"); } + internal FpPoint(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + : base(curve, x, y, zs, withCompression) + { + } + protected internal override bool CompressionYTilde { - get { return this.Y.TestBitZero(); } + get { return this.AffineYCoord.TestBitZero(); } } // B.3 pg 62 @@ -396,28 +547,84 @@ namespace Org.BouncyCastle.Math.EC return Twice(); } - ECFieldElement X1 = this.X, Y1 = this.Y; - ECFieldElement X2 = b.X, Y2 = b.Y; + ECCurve curve = this.Curve; + int coord = curve.CoordinateSystem; - ECFieldElement dx = X2.Subtract(X1), dy = Y2.Subtract(Y1); + ECFieldElement X1 = this.XCoord, Y1 = this.YCoord; + ECFieldElement X2 = b.XCoord, Y2 = b.YCoord; - if (dx.IsZero) + switch (coord) { - if (dy.IsZero) + case ECCurve.COORD_AFFINE: { - // this == b, i.e. this must be doubled - return Twice(); + ECFieldElement dx = X2.Subtract(X1), dy = Y2.Subtract(Y1); + + if (dx.IsZero) + { + if (dy.IsZero) + { + // this == b, i.e. this must be doubled + return Twice(); + } + + // this == -b, i.e. the result is the point at infinity + return Curve.Infinity; + } + + 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, IsCompressed); } - // this == -b, i.e. the result is the point at infinity - return Curve.Infinity; - } + case ECCurve.COORD_HOMOGENEOUS: + { + ECFieldElement Z1 = this.GetZCoord(0); + ECFieldElement Z2 = b.GetZCoord(0); + + bool Z1IsOne = Z1.IsOne; + bool Z2IsOne = Z2.IsOne; + + ECFieldElement u1 = Z1IsOne ? Y2 : Y2.Multiply(Z1); + ECFieldElement u2 = Z2IsOne ? Y1 : Y1.Multiply(Z2); + ECFieldElement u = u1.Subtract(u2); + ECFieldElement v1 = Z1IsOne ? X2 : X2.Multiply(Z1); + ECFieldElement v2 = Z2IsOne ? X1 : X1.Multiply(Z2); + ECFieldElement v = v1.Subtract(v2); + + // Check if b == this or b == -this + if (v.IsZero) + { + if (u.IsZero) + { + // this == b, i.e. this must be doubled + return this.Twice(); + } + + // this == -b, i.e. the result is the point at infinity + return curve.Infinity; + } + + // TODO Optimize for when w == 1 + ECFieldElement w = Z1IsOne ? Z2 : Z2IsOne ? Z1 : Z1.Multiply(Z2); + ECFieldElement vSquared = v.Square(); + ECFieldElement vCubed = vSquared.Multiply(v); + ECFieldElement vSquaredV2 = vSquared.Multiply(v2); + ECFieldElement A = u.Square().Multiply(w).Subtract(vCubed).Subtract(Two(vSquaredV2)); - ECFieldElement gamma = dy.Divide(dx); - ECFieldElement X3 = gamma.Square().Subtract(X1).Subtract(X2); - ECFieldElement Y3 = gamma.Multiply(X1.Subtract(X3)).Subtract(Y1); + ECFieldElement X3 = v.Multiply(A); + ECFieldElement Y3 = vSquaredV2.Subtract(A).Multiply(u).Subtract(vCubed.Multiply(u2)); + ECFieldElement Z3 = vCubed.Multiply(w); - return new FpPoint(Curve, X3, Y3, IsCompressed); + return new FpPoint(curve, X3, Y3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + default: + { + throw new InvalidOperationException("unsupported coordinate system"); + } + } } // B.3 pg 62 @@ -428,20 +635,65 @@ namespace Org.BouncyCastle.Math.EC return this; } - ECFieldElement Y1 = this.Y; + ECCurve curve = this.Curve; + + ECFieldElement Y1 = this.YCoord; if (Y1.IsZero) { - return Curve.Infinity; + return curve.Infinity; } - ECFieldElement X1 = this.X; + int coord = curve.CoordinateSystem; + + ECFieldElement X1 = this.XCoord; + + switch (coord) + { + case ECCurve.COORD_AFFINE: + { + 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); - 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, IsCompressed); + } + + case ECCurve.COORD_HOMOGENEOUS: + { + ECFieldElement Z1 = this.GetZCoord(0); + + bool Z1IsOne = Z1.IsOne; + + // TODO Optimize for small negative a4 and -3 + ECFieldElement w = curve.A; + if (!w.IsZero && !Z1IsOne) + { + w = w.Multiply(Z1.Square()); + } + w = w.Add(Three(X1.Square())); + + ECFieldElement s = Z1IsOne ? Y1 : Y1.Multiply(Z1); + ECFieldElement t = Z1IsOne ? Y1.Square() : s.Multiply(Y1); + ECFieldElement B = X1.Multiply(t); + ECFieldElement _4B = Four(B); + ECFieldElement h = w.Square().Subtract(Two(_4B)); + + ECFieldElement _2s = Two(s); + ECFieldElement X3 = h.Multiply(_2s); + ECFieldElement _2t = Two(t); + ECFieldElement Y3 = _4B.Subtract(h).Multiply(w).Subtract(Two(_2t.Square())); + ECFieldElement _4sSquared = Z1IsOne ? Two(_2t) : _2s.Square(); + ECFieldElement Z3 = Two(_4sSquared).Multiply(s); + + return new FpPoint(curve, X3, Y3, new ECFieldElement[] { Z3 }, IsCompressed); + } - return new FpPoint(Curve, X3, Y3, IsCompressed); + default: + { + throw new InvalidOperationException("unsupported coordinate system"); + } + } } public override ECPoint TwicePlus(ECPoint b) @@ -459,79 +711,106 @@ namespace Org.BouncyCastle.Math.EC return Twice(); } - ECFieldElement Y1 = this.Y; + ECFieldElement Y1 = this.YCoord; 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); + ECCurve curve = this.Curve; + int coord = curve.CoordinateSystem; - if (dx.IsZero) + switch (coord) { - if (dy.IsZero) + case ECCurve.COORD_AFFINE: { - // this == b i.e. the result is 3P - return ThreeTimes(); - } + ECFieldElement X1 = this.XCoord; + ECFieldElement X2 = b.XCoord, Y2 = b.YCoord; - // this == -b, i.e. the result is P - return this; - } + ECFieldElement dx = X2.Subtract(X1), dy = Y2.Subtract(Y1); - /* - * Optimized calculation of 2P + Q, as described in "Trading Inversions for - * Multiplications in Elliptic Curve Cryptography", by Ciet, Joye, Lauter, Montgomery. - */ + if (dx.IsZero) + { + if (dy.IsZero) + { + // this == b i.e. the result is 3P + return ThreeTimes(); + } - ECFieldElement X = dx.Square(), Y = dy.Square(); - ECFieldElement d = X.Multiply(Two(X1).Add(X2)).Subtract(Y); - if (d.IsZero) - { - return Curve.Infinity; - } + // this == -b, i.e. the result is P + return this; + } - 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); + /* + * Optimized calculation of 2P + Q, as described in "Trading Inversions for + * Multiplications in Elliptic Curve Cryptography", by Ciet, Joye, Lauter, Montgomery. + */ - return new FpPoint(Curve, X4, Y4, IsCompressed); + 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, IsCompressed); + } + default: + { + return Twice().Add(b); + } + } } public override ECPoint ThreeTimes() { - if (IsInfinity || this.Y.IsZero) + if (IsInfinity || this.YCoord.IsZero) { return this; } - ECFieldElement X1 = this.X, Y1 = this.Y; - - ECFieldElement _2Y1 = Two(Y1); - ECFieldElement X = _2Y1.Square(); - ECFieldElement Z = Three(X1.Square()).Add(Curve.A); - ECFieldElement Y = Z.Square(); + ECCurve curve = this.Curve; + int coord = curve.CoordinateSystem; - ECFieldElement d = Three(X1).Multiply(X).Subtract(Y); - if (d.IsZero) + switch (coord) { - return Curve.Infinity; - } + case ECCurve.COORD_AFFINE: + { + ECFieldElement X1 = this.XCoord, Y1 = this.YCoord; - 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 _2Y1 = Two(Y1); + ECFieldElement X = _2Y1.Square(); + ECFieldElement Z = Three(X1.Square()).Add(Curve.A); + ECFieldElement Y = Z.Square(); - 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, IsCompressed); + ECFieldElement d = Three(X1).Multiply(X).Subtract(Y); + if (d.IsZero) + { + return 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, IsCompressed); + } + default: + { + // NOTE: Be careful about recursions between twicePlus and threeTimes + return Twice().Add(this); + } + } } protected virtual ECFieldElement Two(ECFieldElement x) @@ -583,14 +862,14 @@ namespace Org.BouncyCastle.Math.EC } ECCurve curve = this.Curve; - //int coord = curve.CoordinateSystem; + int coord = curve.CoordinateSystem; - //if (ECCurve.COORD_AFFINE != coord) - //{ - // return new FpPoint(curve, X, Y.Negate(), this.m_zs, IsCompressed); - //} + if (ECCurve.COORD_AFFINE != coord) + { + return new FpPoint(curve, XCoord, YCoord.Negate(), this.m_zs, IsCompressed); + } - return new FpPoint(curve, X, Y.Negate(), IsCompressed); + return new FpPoint(curve, XCoord, YCoord.Negate(), IsCompressed); } } @@ -637,10 +916,18 @@ namespace Org.BouncyCastle.Math.EC F2mFieldElement.CheckFieldElements(x, y); // Check if x and a are elements of the same field - F2mFieldElement.CheckFieldElements(x, curve.A); + if (curve != null) + { + F2mFieldElement.CheckFieldElements(x, curve.A); + } } } + internal F2mPoint(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + : base(curve, x, y, zs, withCompression) + { + } + /** * Constructor for point at infinity */ @@ -655,10 +942,28 @@ namespace Org.BouncyCastle.Math.EC { get { - // X9.62 4.2.2 and 4.3.6: - // if x = 0 then ypTilde := 0, else ypTilde is the rightmost - // bit of y * x^(-1) - return !this.X.IsZero && this.Y.Divide(this.X).TestBitZero(); + ECFieldElement X = this.RawXCoord; + if (X.IsZero) + { + return false; + } + + ECFieldElement Y = this.RawYCoord; + + switch (this.CurveCoordinateSystem) + { + case ECCurve.COORD_LAMBDA_AFFINE: + case ECCurve.COORD_LAMBDA_PROJECTIVE: + { + // Y is actually Lambda (X + Y/X) here + return Y.Subtract(X).TestBitZero(); + } + default: + { + return Y.Divide(X).TestBitZero(); + } + } + } } @@ -706,30 +1011,30 @@ namespace Org.BouncyCastle.Math.EC if (b.IsInfinity) return this; - F2mFieldElement x2 = (F2mFieldElement) b.X; - F2mFieldElement y2 = (F2mFieldElement) b.Y; + F2mFieldElement x2 = (F2mFieldElement) b.XCoord; + F2mFieldElement y2 = (F2mFieldElement) b.YCoord; // Check if b == this or b == -this - if (this.X.Equals(x2)) + if (this.XCoord.Equals(x2)) { // this == b, i.e. this must be doubled - if (this.Y.Equals(y2)) + if (this.YCoord.Equals(y2)) return (F2mPoint) this.Twice(); // this = -other, i.e. the result is the point at infinity return (F2mPoint) Curve.Infinity; } - ECFieldElement xSum = this.X.Add(x2); + ECFieldElement xSum = this.XCoord.Add(x2); F2mFieldElement lambda - = (F2mFieldElement)(this.Y.Add(y2)).Divide(xSum); + = (F2mFieldElement)(this.YCoord.Add(y2)).Divide(xSum); F2mFieldElement x3 = (F2mFieldElement)lambda.Square().Add(lambda).Add(xSum).Add(Curve.A); F2mFieldElement y3 - = (F2mFieldElement)lambda.Multiply(this.X.Add(x3)).Add(x3).Add(this.Y); + = (F2mFieldElement)lambda.Multiply(this.XCoord.Add(x3)).Add(x3).Add(this.YCoord); return new F2mPoint(Curve, x3, y3, IsCompressed); } @@ -763,6 +1068,39 @@ namespace Org.BouncyCastle.Math.EC 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.XCoord; + + switch (coord) + { + case ECCurve.COORD_AFFINE: + case ECCurve.COORD_LAMBDA_AFFINE: + { + ECFieldElement Y1 = this.YCoord; + return new F2mPoint(curve, X1.Square(), Y1.Square(), IsCompressed); + } + case ECCurve.COORD_HOMOGENEOUS: + case ECCurve.COORD_LAMBDA_PROJECTIVE: + { + ECFieldElement Y1 = this.YCoord, Z1 = this.GetZCoord(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() */ @@ -774,15 +1112,15 @@ namespace Org.BouncyCastle.Math.EC // if x1 == 0, then (x1, y1) == (x1, x1 + y1) // and hence this = -this and thus 2(x1, y1) == infinity - if (this.X.IsZero) + if (this.XCoord.IsZero) { return Curve.Infinity; } - F2mFieldElement lambda = (F2mFieldElement) this.X.Add(this.Y.Divide(this.X)); + F2mFieldElement lambda = (F2mFieldElement) this.XCoord.Add(this.YCoord.Divide(this.XCoord)); F2mFieldElement x2 = (F2mFieldElement)lambda.Square().Add(lambda).Add(Curve.A); ECFieldElement ONE = Curve.FromBigInteger(BigInteger.One); - F2mFieldElement y2 = (F2mFieldElement)this.X.Square().Add( + F2mFieldElement y2 = (F2mFieldElement)this.XCoord.Square().Add( x2.Multiply(lambda.Add(ONE))); return new F2mPoint(Curve, x2, y2, IsCompressed); @@ -795,13 +1133,13 @@ namespace Org.BouncyCastle.Math.EC return this; } - ECFieldElement X1 = this.X; + ECFieldElement X1 = this.XCoord; if (X1.IsZero) { return this; } - return new F2mPoint(Curve, X1, X1.Add(this.Y), IsCompressed); + return new F2mPoint(Curve, X1, X1.Add(this.YCoord), IsCompressed); } } } |