604 lines
21 KiB
C#
604 lines
21 KiB
C#
using System;
|
|
|
|
namespace Org.BouncyCastle.Math.EC;
|
|
|
|
public class FpPoint : AbstractFpPoint
|
|
{
|
|
[Obsolete("Use ECCurve.CreatePoint to construct points")]
|
|
public FpPoint(ECCurve curve, ECFieldElement x, ECFieldElement y)
|
|
: this(curve, x, y, withCompression: false)
|
|
{
|
|
}
|
|
|
|
[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)
|
|
{
|
|
if (x == null != (y == null))
|
|
{
|
|
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 override ECPoint Detach()
|
|
{
|
|
return new FpPoint(null, AffineXCoord, AffineYCoord, withCompression: false);
|
|
}
|
|
|
|
public override ECFieldElement GetZCoord(int index)
|
|
{
|
|
if (index == 1 && 4 == CurveCoordinateSystem)
|
|
{
|
|
return GetJacobianModifiedW();
|
|
}
|
|
return base.GetZCoord(index);
|
|
}
|
|
|
|
public override ECPoint Add(ECPoint b)
|
|
{
|
|
if (base.IsInfinity)
|
|
{
|
|
return b;
|
|
}
|
|
if (b.IsInfinity)
|
|
{
|
|
return this;
|
|
}
|
|
if (this == b)
|
|
{
|
|
return Twice();
|
|
}
|
|
ECCurve curve = Curve;
|
|
int coordinateSystem = curve.CoordinateSystem;
|
|
ECFieldElement rawXCoord = base.RawXCoord;
|
|
ECFieldElement rawYCoord = base.RawYCoord;
|
|
ECFieldElement rawXCoord2 = b.RawXCoord;
|
|
ECFieldElement rawYCoord2 = b.RawYCoord;
|
|
switch (coordinateSystem)
|
|
{
|
|
case 0:
|
|
{
|
|
ECFieldElement eCFieldElement32 = rawXCoord2.Subtract(rawXCoord);
|
|
ECFieldElement eCFieldElement33 = rawYCoord2.Subtract(rawYCoord);
|
|
if (eCFieldElement32.IsZero)
|
|
{
|
|
if (eCFieldElement33.IsZero)
|
|
{
|
|
return Twice();
|
|
}
|
|
return Curve.Infinity;
|
|
}
|
|
ECFieldElement eCFieldElement34 = eCFieldElement33.Divide(eCFieldElement32);
|
|
ECFieldElement eCFieldElement35 = eCFieldElement34.Square().Subtract(rawXCoord).Subtract(rawXCoord2);
|
|
ECFieldElement y3 = eCFieldElement34.Multiply(rawXCoord.Subtract(eCFieldElement35)).Subtract(rawYCoord);
|
|
return new FpPoint(Curve, eCFieldElement35, y3, base.IsCompressed);
|
|
}
|
|
case 1:
|
|
{
|
|
ECFieldElement eCFieldElement21 = base.RawZCoords[0];
|
|
ECFieldElement eCFieldElement22 = b.RawZCoords[0];
|
|
bool isOne3 = eCFieldElement21.IsOne;
|
|
bool isOne4 = eCFieldElement22.IsOne;
|
|
ECFieldElement eCFieldElement23 = (isOne3 ? rawYCoord2 : rawYCoord2.Multiply(eCFieldElement21));
|
|
ECFieldElement eCFieldElement24 = (isOne4 ? rawYCoord : rawYCoord.Multiply(eCFieldElement22));
|
|
ECFieldElement eCFieldElement25 = eCFieldElement23.Subtract(eCFieldElement24);
|
|
ECFieldElement eCFieldElement26 = (isOne3 ? rawXCoord2 : rawXCoord2.Multiply(eCFieldElement21));
|
|
ECFieldElement b6 = (isOne4 ? rawXCoord : rawXCoord.Multiply(eCFieldElement22));
|
|
ECFieldElement eCFieldElement27 = eCFieldElement26.Subtract(b6);
|
|
if (eCFieldElement27.IsZero)
|
|
{
|
|
if (eCFieldElement25.IsZero)
|
|
{
|
|
return Twice();
|
|
}
|
|
return curve.Infinity;
|
|
}
|
|
ECFieldElement b7 = (isOne3 ? eCFieldElement22 : (isOne4 ? eCFieldElement21 : eCFieldElement21.Multiply(eCFieldElement22)));
|
|
ECFieldElement eCFieldElement28 = eCFieldElement27.Square();
|
|
ECFieldElement eCFieldElement29 = eCFieldElement28.Multiply(eCFieldElement27);
|
|
ECFieldElement eCFieldElement30 = eCFieldElement28.Multiply(b6);
|
|
ECFieldElement b8 = eCFieldElement25.Square().Multiply(b7).Subtract(eCFieldElement29)
|
|
.Subtract(Two(eCFieldElement30));
|
|
ECFieldElement x = eCFieldElement27.Multiply(b8);
|
|
ECFieldElement y2 = eCFieldElement30.Subtract(b8).MultiplyMinusProduct(eCFieldElement25, eCFieldElement24, eCFieldElement29);
|
|
ECFieldElement eCFieldElement31 = eCFieldElement29.Multiply(b7);
|
|
return new FpPoint(curve, x, y2, new ECFieldElement[1] { eCFieldElement31 }, base.IsCompressed);
|
|
}
|
|
case 2:
|
|
case 4:
|
|
{
|
|
ECFieldElement eCFieldElement = base.RawZCoords[0];
|
|
ECFieldElement eCFieldElement2 = b.RawZCoords[0];
|
|
bool isOne = eCFieldElement.IsOne;
|
|
ECFieldElement zSquared = null;
|
|
ECFieldElement eCFieldElement7;
|
|
ECFieldElement y;
|
|
ECFieldElement eCFieldElement8;
|
|
if (!isOne && eCFieldElement.Equals(eCFieldElement2))
|
|
{
|
|
ECFieldElement eCFieldElement3 = rawXCoord.Subtract(rawXCoord2);
|
|
ECFieldElement eCFieldElement4 = rawYCoord.Subtract(rawYCoord2);
|
|
if (eCFieldElement3.IsZero)
|
|
{
|
|
if (eCFieldElement4.IsZero)
|
|
{
|
|
return Twice();
|
|
}
|
|
return curve.Infinity;
|
|
}
|
|
ECFieldElement eCFieldElement5 = eCFieldElement3.Square();
|
|
ECFieldElement eCFieldElement6 = rawXCoord.Multiply(eCFieldElement5);
|
|
ECFieldElement b2 = rawXCoord2.Multiply(eCFieldElement5);
|
|
ECFieldElement b3 = eCFieldElement6.Subtract(b2).Multiply(rawYCoord);
|
|
eCFieldElement7 = eCFieldElement4.Square().Subtract(eCFieldElement6).Subtract(b2);
|
|
y = eCFieldElement6.Subtract(eCFieldElement7).Multiply(eCFieldElement4).Subtract(b3);
|
|
eCFieldElement8 = eCFieldElement3;
|
|
if (isOne)
|
|
{
|
|
zSquared = eCFieldElement5;
|
|
}
|
|
else
|
|
{
|
|
eCFieldElement8 = eCFieldElement8.Multiply(eCFieldElement);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ECFieldElement b4;
|
|
ECFieldElement b5;
|
|
if (isOne)
|
|
{
|
|
ECFieldElement eCFieldElement9 = eCFieldElement;
|
|
b4 = rawXCoord2;
|
|
b5 = rawYCoord2;
|
|
}
|
|
else
|
|
{
|
|
ECFieldElement eCFieldElement9 = eCFieldElement.Square();
|
|
b4 = eCFieldElement9.Multiply(rawXCoord2);
|
|
ECFieldElement eCFieldElement10 = eCFieldElement9.Multiply(eCFieldElement);
|
|
b5 = eCFieldElement10.Multiply(rawYCoord2);
|
|
}
|
|
bool isOne2 = eCFieldElement2.IsOne;
|
|
ECFieldElement eCFieldElement12;
|
|
ECFieldElement eCFieldElement13;
|
|
if (isOne2)
|
|
{
|
|
ECFieldElement eCFieldElement11 = eCFieldElement2;
|
|
eCFieldElement12 = rawXCoord;
|
|
eCFieldElement13 = rawYCoord;
|
|
}
|
|
else
|
|
{
|
|
ECFieldElement eCFieldElement11 = eCFieldElement2.Square();
|
|
eCFieldElement12 = eCFieldElement11.Multiply(rawXCoord);
|
|
ECFieldElement eCFieldElement14 = eCFieldElement11.Multiply(eCFieldElement2);
|
|
eCFieldElement13 = eCFieldElement14.Multiply(rawYCoord);
|
|
}
|
|
ECFieldElement eCFieldElement15 = eCFieldElement12.Subtract(b4);
|
|
ECFieldElement eCFieldElement16 = eCFieldElement13.Subtract(b5);
|
|
if (eCFieldElement15.IsZero)
|
|
{
|
|
if (eCFieldElement16.IsZero)
|
|
{
|
|
return Twice();
|
|
}
|
|
return curve.Infinity;
|
|
}
|
|
ECFieldElement eCFieldElement17 = eCFieldElement15.Square();
|
|
ECFieldElement eCFieldElement18 = eCFieldElement17.Multiply(eCFieldElement15);
|
|
ECFieldElement eCFieldElement19 = eCFieldElement17.Multiply(eCFieldElement12);
|
|
eCFieldElement7 = eCFieldElement16.Square().Add(eCFieldElement18).Subtract(Two(eCFieldElement19));
|
|
y = eCFieldElement19.Subtract(eCFieldElement7).MultiplyMinusProduct(eCFieldElement16, eCFieldElement18, eCFieldElement13);
|
|
eCFieldElement8 = eCFieldElement15;
|
|
if (!isOne)
|
|
{
|
|
eCFieldElement8 = eCFieldElement8.Multiply(eCFieldElement);
|
|
}
|
|
if (!isOne2)
|
|
{
|
|
eCFieldElement8 = eCFieldElement8.Multiply(eCFieldElement2);
|
|
}
|
|
if (eCFieldElement8 == eCFieldElement15)
|
|
{
|
|
zSquared = eCFieldElement17;
|
|
}
|
|
}
|
|
ECFieldElement[] zs;
|
|
if (coordinateSystem == 4)
|
|
{
|
|
ECFieldElement eCFieldElement20 = CalculateJacobianModifiedW(eCFieldElement8, zSquared);
|
|
zs = new ECFieldElement[2] { eCFieldElement8, eCFieldElement20 };
|
|
}
|
|
else
|
|
{
|
|
zs = new ECFieldElement[1] { eCFieldElement8 };
|
|
}
|
|
return new FpPoint(curve, eCFieldElement7, y, zs, base.IsCompressed);
|
|
}
|
|
default:
|
|
throw new InvalidOperationException("unsupported coordinate system");
|
|
}
|
|
}
|
|
|
|
public override ECPoint Twice()
|
|
{
|
|
if (base.IsInfinity)
|
|
{
|
|
return this;
|
|
}
|
|
ECCurve curve = Curve;
|
|
ECFieldElement rawYCoord = base.RawYCoord;
|
|
if (rawYCoord.IsZero)
|
|
{
|
|
return curve.Infinity;
|
|
}
|
|
int coordinateSystem = curve.CoordinateSystem;
|
|
ECFieldElement rawXCoord = base.RawXCoord;
|
|
switch (coordinateSystem)
|
|
{
|
|
case 0:
|
|
{
|
|
ECFieldElement x3 = rawXCoord.Square();
|
|
ECFieldElement eCFieldElement10 = Three(x3).Add(Curve.A).Divide(Two(rawYCoord));
|
|
ECFieldElement eCFieldElement11 = eCFieldElement10.Square().Subtract(Two(rawXCoord));
|
|
ECFieldElement y2 = eCFieldElement10.Multiply(rawXCoord.Subtract(eCFieldElement11)).Subtract(rawYCoord);
|
|
return new FpPoint(Curve, eCFieldElement11, y2, base.IsCompressed);
|
|
}
|
|
case 1:
|
|
{
|
|
ECFieldElement eCFieldElement12 = base.RawZCoords[0];
|
|
bool isOne2 = eCFieldElement12.IsOne;
|
|
ECFieldElement eCFieldElement13 = curve.A;
|
|
if (!eCFieldElement13.IsZero && !isOne2)
|
|
{
|
|
eCFieldElement13 = eCFieldElement13.Multiply(eCFieldElement12.Square());
|
|
}
|
|
eCFieldElement13 = eCFieldElement13.Add(Three(rawXCoord.Square()));
|
|
ECFieldElement eCFieldElement14 = (isOne2 ? rawYCoord : rawYCoord.Multiply(eCFieldElement12));
|
|
ECFieldElement eCFieldElement15 = (isOne2 ? rawYCoord.Square() : eCFieldElement14.Multiply(rawYCoord));
|
|
ECFieldElement x4 = rawXCoord.Multiply(eCFieldElement15);
|
|
ECFieldElement eCFieldElement16 = Four(x4);
|
|
ECFieldElement eCFieldElement17 = eCFieldElement13.Square().Subtract(Two(eCFieldElement16));
|
|
ECFieldElement eCFieldElement18 = Two(eCFieldElement14);
|
|
ECFieldElement x5 = eCFieldElement17.Multiply(eCFieldElement18);
|
|
ECFieldElement eCFieldElement19 = Two(eCFieldElement15);
|
|
ECFieldElement y3 = eCFieldElement16.Subtract(eCFieldElement17).Multiply(eCFieldElement13).Subtract(Two(eCFieldElement19.Square()));
|
|
ECFieldElement x6 = (isOne2 ? Two(eCFieldElement19) : eCFieldElement18.Square());
|
|
ECFieldElement eCFieldElement20 = Two(x6).Multiply(eCFieldElement14);
|
|
return new FpPoint(curve, x5, y3, new ECFieldElement[1] { eCFieldElement20 }, base.IsCompressed);
|
|
}
|
|
case 2:
|
|
{
|
|
ECFieldElement eCFieldElement = base.RawZCoords[0];
|
|
bool isOne = eCFieldElement.IsOne;
|
|
ECFieldElement eCFieldElement2 = rawYCoord.Square();
|
|
ECFieldElement x = eCFieldElement2.Square();
|
|
ECFieldElement a = curve.A;
|
|
ECFieldElement eCFieldElement3 = a.Negate();
|
|
ECFieldElement eCFieldElement4;
|
|
ECFieldElement eCFieldElement5;
|
|
if (eCFieldElement3.ToBigInteger().Equals(BigInteger.ValueOf(3L)))
|
|
{
|
|
ECFieldElement b = (isOne ? eCFieldElement : eCFieldElement.Square());
|
|
eCFieldElement4 = Three(rawXCoord.Add(b).Multiply(rawXCoord.Subtract(b)));
|
|
eCFieldElement5 = Four(eCFieldElement2.Multiply(rawXCoord));
|
|
}
|
|
else
|
|
{
|
|
ECFieldElement x2 = rawXCoord.Square();
|
|
eCFieldElement4 = Three(x2);
|
|
if (isOne)
|
|
{
|
|
eCFieldElement4 = eCFieldElement4.Add(a);
|
|
}
|
|
else if (!a.IsZero)
|
|
{
|
|
ECFieldElement eCFieldElement6 = (isOne ? eCFieldElement : eCFieldElement.Square());
|
|
ECFieldElement eCFieldElement7 = eCFieldElement6.Square();
|
|
eCFieldElement4 = ((eCFieldElement3.BitLength >= a.BitLength) ? eCFieldElement4.Add(eCFieldElement7.Multiply(a)) : eCFieldElement4.Subtract(eCFieldElement7.Multiply(eCFieldElement3)));
|
|
}
|
|
eCFieldElement5 = Four(rawXCoord.Multiply(eCFieldElement2));
|
|
}
|
|
ECFieldElement eCFieldElement8 = eCFieldElement4.Square().Subtract(Two(eCFieldElement5));
|
|
ECFieldElement y = eCFieldElement5.Subtract(eCFieldElement8).Multiply(eCFieldElement4).Subtract(Eight(x));
|
|
ECFieldElement eCFieldElement9 = Two(rawYCoord);
|
|
if (!isOne)
|
|
{
|
|
eCFieldElement9 = eCFieldElement9.Multiply(eCFieldElement);
|
|
}
|
|
return new FpPoint(curve, eCFieldElement8, y, new ECFieldElement[1] { eCFieldElement9 }, base.IsCompressed);
|
|
}
|
|
case 4:
|
|
return TwiceJacobianModified(calculateW: true);
|
|
default:
|
|
throw new InvalidOperationException("unsupported coordinate system");
|
|
}
|
|
}
|
|
|
|
public override ECPoint TwicePlus(ECPoint b)
|
|
{
|
|
if (this == b)
|
|
{
|
|
return ThreeTimes();
|
|
}
|
|
if (base.IsInfinity)
|
|
{
|
|
return b;
|
|
}
|
|
if (b.IsInfinity)
|
|
{
|
|
return Twice();
|
|
}
|
|
ECFieldElement rawYCoord = base.RawYCoord;
|
|
if (rawYCoord.IsZero)
|
|
{
|
|
return b;
|
|
}
|
|
ECCurve curve = Curve;
|
|
switch (curve.CoordinateSystem)
|
|
{
|
|
case 0:
|
|
{
|
|
ECFieldElement rawXCoord = base.RawXCoord;
|
|
ECFieldElement rawXCoord2 = b.RawXCoord;
|
|
ECFieldElement rawYCoord2 = b.RawYCoord;
|
|
ECFieldElement eCFieldElement = rawXCoord2.Subtract(rawXCoord);
|
|
ECFieldElement eCFieldElement2 = rawYCoord2.Subtract(rawYCoord);
|
|
if (eCFieldElement.IsZero)
|
|
{
|
|
if (eCFieldElement2.IsZero)
|
|
{
|
|
return ThreeTimes();
|
|
}
|
|
return this;
|
|
}
|
|
ECFieldElement eCFieldElement3 = eCFieldElement.Square();
|
|
ECFieldElement b2 = eCFieldElement2.Square();
|
|
ECFieldElement eCFieldElement4 = eCFieldElement3.Multiply(Two(rawXCoord).Add(rawXCoord2)).Subtract(b2);
|
|
if (eCFieldElement4.IsZero)
|
|
{
|
|
return Curve.Infinity;
|
|
}
|
|
ECFieldElement eCFieldElement5 = eCFieldElement4.Multiply(eCFieldElement);
|
|
ECFieldElement b3 = eCFieldElement5.Invert();
|
|
ECFieldElement eCFieldElement6 = eCFieldElement4.Multiply(b3).Multiply(eCFieldElement2);
|
|
ECFieldElement eCFieldElement7 = Two(rawYCoord).Multiply(eCFieldElement3).Multiply(eCFieldElement).Multiply(b3)
|
|
.Subtract(eCFieldElement6);
|
|
ECFieldElement eCFieldElement8 = eCFieldElement7.Subtract(eCFieldElement6).Multiply(eCFieldElement6.Add(eCFieldElement7)).Add(rawXCoord2);
|
|
ECFieldElement y = rawXCoord.Subtract(eCFieldElement8).Multiply(eCFieldElement7).Subtract(rawYCoord);
|
|
return new FpPoint(Curve, eCFieldElement8, y, base.IsCompressed);
|
|
}
|
|
case 4:
|
|
return TwiceJacobianModified(calculateW: false).Add(b);
|
|
default:
|
|
return Twice().Add(b);
|
|
}
|
|
}
|
|
|
|
public override ECPoint ThreeTimes()
|
|
{
|
|
if (base.IsInfinity)
|
|
{
|
|
return this;
|
|
}
|
|
ECFieldElement rawYCoord = base.RawYCoord;
|
|
if (rawYCoord.IsZero)
|
|
{
|
|
return this;
|
|
}
|
|
ECCurve curve = Curve;
|
|
switch (curve.CoordinateSystem)
|
|
{
|
|
case 0:
|
|
{
|
|
ECFieldElement rawXCoord = base.RawXCoord;
|
|
ECFieldElement eCFieldElement = Two(rawYCoord);
|
|
ECFieldElement eCFieldElement2 = eCFieldElement.Square();
|
|
ECFieldElement eCFieldElement3 = Three(rawXCoord.Square()).Add(Curve.A);
|
|
ECFieldElement b = eCFieldElement3.Square();
|
|
ECFieldElement eCFieldElement4 = Three(rawXCoord).Multiply(eCFieldElement2).Subtract(b);
|
|
if (eCFieldElement4.IsZero)
|
|
{
|
|
return Curve.Infinity;
|
|
}
|
|
ECFieldElement eCFieldElement5 = eCFieldElement4.Multiply(eCFieldElement);
|
|
ECFieldElement b2 = eCFieldElement5.Invert();
|
|
ECFieldElement eCFieldElement6 = eCFieldElement4.Multiply(b2).Multiply(eCFieldElement3);
|
|
ECFieldElement eCFieldElement7 = eCFieldElement2.Square().Multiply(b2).Subtract(eCFieldElement6);
|
|
ECFieldElement eCFieldElement8 = eCFieldElement7.Subtract(eCFieldElement6).Multiply(eCFieldElement6.Add(eCFieldElement7)).Add(rawXCoord);
|
|
ECFieldElement y = rawXCoord.Subtract(eCFieldElement8).Multiply(eCFieldElement7).Subtract(rawYCoord);
|
|
return new FpPoint(Curve, eCFieldElement8, y, base.IsCompressed);
|
|
}
|
|
case 4:
|
|
return TwiceJacobianModified(calculateW: false).Add(this);
|
|
default:
|
|
return Twice().Add(this);
|
|
}
|
|
}
|
|
|
|
public override ECPoint TimesPow2(int e)
|
|
{
|
|
if (e < 0)
|
|
{
|
|
throw new ArgumentException("cannot be negative", "e");
|
|
}
|
|
if (e == 0 || base.IsInfinity)
|
|
{
|
|
return this;
|
|
}
|
|
if (e == 1)
|
|
{
|
|
return Twice();
|
|
}
|
|
ECCurve curve = Curve;
|
|
ECFieldElement eCFieldElement = base.RawYCoord;
|
|
if (eCFieldElement.IsZero)
|
|
{
|
|
return curve.Infinity;
|
|
}
|
|
int coordinateSystem = curve.CoordinateSystem;
|
|
ECFieldElement eCFieldElement2 = curve.A;
|
|
ECFieldElement eCFieldElement3 = base.RawXCoord;
|
|
ECFieldElement eCFieldElement4 = ((base.RawZCoords.Length < 1) ? curve.FromBigInteger(BigInteger.One) : base.RawZCoords[0]);
|
|
if (!eCFieldElement4.IsOne)
|
|
{
|
|
switch (coordinateSystem)
|
|
{
|
|
case 1:
|
|
{
|
|
ECFieldElement eCFieldElement5 = eCFieldElement4.Square();
|
|
eCFieldElement3 = eCFieldElement3.Multiply(eCFieldElement4);
|
|
eCFieldElement = eCFieldElement.Multiply(eCFieldElement5);
|
|
eCFieldElement2 = CalculateJacobianModifiedW(eCFieldElement4, eCFieldElement5);
|
|
break;
|
|
}
|
|
case 2:
|
|
eCFieldElement2 = CalculateJacobianModifiedW(eCFieldElement4, null);
|
|
break;
|
|
case 4:
|
|
eCFieldElement2 = GetJacobianModifiedW();
|
|
break;
|
|
}
|
|
}
|
|
for (int i = 0; i < e; i++)
|
|
{
|
|
if (eCFieldElement.IsZero)
|
|
{
|
|
return curve.Infinity;
|
|
}
|
|
ECFieldElement x = eCFieldElement3.Square();
|
|
ECFieldElement eCFieldElement6 = Three(x);
|
|
ECFieldElement eCFieldElement7 = Two(eCFieldElement);
|
|
ECFieldElement eCFieldElement8 = eCFieldElement7.Multiply(eCFieldElement);
|
|
ECFieldElement eCFieldElement9 = Two(eCFieldElement3.Multiply(eCFieldElement8));
|
|
ECFieldElement x2 = eCFieldElement8.Square();
|
|
ECFieldElement eCFieldElement10 = Two(x2);
|
|
if (!eCFieldElement2.IsZero)
|
|
{
|
|
eCFieldElement6 = eCFieldElement6.Add(eCFieldElement2);
|
|
eCFieldElement2 = Two(eCFieldElement10.Multiply(eCFieldElement2));
|
|
}
|
|
eCFieldElement3 = eCFieldElement6.Square().Subtract(Two(eCFieldElement9));
|
|
eCFieldElement = eCFieldElement6.Multiply(eCFieldElement9.Subtract(eCFieldElement3)).Subtract(eCFieldElement10);
|
|
eCFieldElement4 = (eCFieldElement4.IsOne ? eCFieldElement7 : eCFieldElement7.Multiply(eCFieldElement4));
|
|
}
|
|
switch (coordinateSystem)
|
|
{
|
|
case 0:
|
|
{
|
|
ECFieldElement eCFieldElement11 = eCFieldElement4.Invert();
|
|
ECFieldElement eCFieldElement12 = eCFieldElement11.Square();
|
|
ECFieldElement b = eCFieldElement12.Multiply(eCFieldElement11);
|
|
return new FpPoint(curve, eCFieldElement3.Multiply(eCFieldElement12), eCFieldElement.Multiply(b), base.IsCompressed);
|
|
}
|
|
case 1:
|
|
eCFieldElement3 = eCFieldElement3.Multiply(eCFieldElement4);
|
|
eCFieldElement4 = eCFieldElement4.Multiply(eCFieldElement4.Square());
|
|
return new FpPoint(curve, eCFieldElement3, eCFieldElement, new ECFieldElement[1] { eCFieldElement4 }, base.IsCompressed);
|
|
case 2:
|
|
return new FpPoint(curve, eCFieldElement3, eCFieldElement, new ECFieldElement[1] { eCFieldElement4 }, base.IsCompressed);
|
|
case 4:
|
|
return new FpPoint(curve, eCFieldElement3, eCFieldElement, new ECFieldElement[2] { eCFieldElement4, eCFieldElement2 }, base.IsCompressed);
|
|
default:
|
|
throw new InvalidOperationException("unsupported coordinate system");
|
|
}
|
|
}
|
|
|
|
protected virtual ECFieldElement Two(ECFieldElement x)
|
|
{
|
|
return x.Add(x);
|
|
}
|
|
|
|
protected virtual ECFieldElement Three(ECFieldElement x)
|
|
{
|
|
return Two(x).Add(x);
|
|
}
|
|
|
|
protected virtual ECFieldElement Four(ECFieldElement x)
|
|
{
|
|
return Two(Two(x));
|
|
}
|
|
|
|
protected virtual ECFieldElement Eight(ECFieldElement x)
|
|
{
|
|
return Four(Two(x));
|
|
}
|
|
|
|
protected virtual ECFieldElement DoubleProductFromSquares(ECFieldElement a, ECFieldElement b, ECFieldElement aSquared, ECFieldElement bSquared)
|
|
{
|
|
return a.Add(b).Square().Subtract(aSquared)
|
|
.Subtract(bSquared);
|
|
}
|
|
|
|
public override ECPoint Negate()
|
|
{
|
|
if (base.IsInfinity)
|
|
{
|
|
return this;
|
|
}
|
|
ECCurve curve = Curve;
|
|
if (curve.CoordinateSystem != 0)
|
|
{
|
|
return new FpPoint(curve, base.RawXCoord, base.RawYCoord.Negate(), base.RawZCoords, base.IsCompressed);
|
|
}
|
|
return new FpPoint(curve, base.RawXCoord, base.RawYCoord.Negate(), base.IsCompressed);
|
|
}
|
|
|
|
protected virtual ECFieldElement CalculateJacobianModifiedW(ECFieldElement Z, ECFieldElement ZSquared)
|
|
{
|
|
ECFieldElement a = Curve.A;
|
|
if (a.IsZero || Z.IsOne)
|
|
{
|
|
return a;
|
|
}
|
|
if (ZSquared == null)
|
|
{
|
|
ZSquared = Z.Square();
|
|
}
|
|
ECFieldElement eCFieldElement = ZSquared.Square();
|
|
ECFieldElement eCFieldElement2 = a.Negate();
|
|
if (eCFieldElement2.BitLength < a.BitLength)
|
|
{
|
|
return eCFieldElement.Multiply(eCFieldElement2).Negate();
|
|
}
|
|
return eCFieldElement.Multiply(a);
|
|
}
|
|
|
|
protected virtual ECFieldElement GetJacobianModifiedW()
|
|
{
|
|
ECFieldElement[] rawZCoords = base.RawZCoords;
|
|
ECFieldElement eCFieldElement = rawZCoords[1];
|
|
if (eCFieldElement == null)
|
|
{
|
|
eCFieldElement = (rawZCoords[1] = CalculateJacobianModifiedW(rawZCoords[0], null));
|
|
}
|
|
return eCFieldElement;
|
|
}
|
|
|
|
protected virtual FpPoint TwiceJacobianModified(bool calculateW)
|
|
{
|
|
ECFieldElement rawXCoord = base.RawXCoord;
|
|
ECFieldElement rawYCoord = base.RawYCoord;
|
|
ECFieldElement eCFieldElement = base.RawZCoords[0];
|
|
ECFieldElement jacobianModifiedW = GetJacobianModifiedW();
|
|
ECFieldElement x = rawXCoord.Square();
|
|
ECFieldElement eCFieldElement2 = Three(x).Add(jacobianModifiedW);
|
|
ECFieldElement eCFieldElement3 = Two(rawYCoord);
|
|
ECFieldElement eCFieldElement4 = eCFieldElement3.Multiply(rawYCoord);
|
|
ECFieldElement eCFieldElement5 = Two(rawXCoord.Multiply(eCFieldElement4));
|
|
ECFieldElement eCFieldElement6 = eCFieldElement2.Square().Subtract(Two(eCFieldElement5));
|
|
ECFieldElement x2 = eCFieldElement4.Square();
|
|
ECFieldElement eCFieldElement7 = Two(x2);
|
|
ECFieldElement y = eCFieldElement2.Multiply(eCFieldElement5.Subtract(eCFieldElement6)).Subtract(eCFieldElement7);
|
|
ECFieldElement eCFieldElement8 = (calculateW ? Two(eCFieldElement7.Multiply(jacobianModifiedW)) : null);
|
|
ECFieldElement eCFieldElement9 = (eCFieldElement.IsOne ? eCFieldElement3 : eCFieldElement3.Multiply(eCFieldElement));
|
|
return new FpPoint(Curve, eCFieldElement6, y, new ECFieldElement[2] { eCFieldElement9, eCFieldElement8 }, base.IsCompressed);
|
|
}
|
|
}
|