FpPoint
using System;
namespace Renci.SshNet.Security.Org.BouncyCastle.Math.EC
{
internal class FpPoint : AbstractFpPoint
{
public FpPoint(ECCurve curve, ECFieldElement x, ECFieldElement y)
: this(curve, x, y, false)
{
}
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, 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) {
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 eCFieldElement28 = rawXCoord2.Subtract(rawXCoord);
ECFieldElement eCFieldElement29 = rawYCoord2.Subtract(rawYCoord);
if (eCFieldElement28.IsZero) {
if (eCFieldElement29.IsZero)
return Twice();
return Curve.Infinity;
}
ECFieldElement eCFieldElement30 = eCFieldElement29.Divide(eCFieldElement28);
ECFieldElement eCFieldElement31 = eCFieldElement30.Square().Subtract(rawXCoord).Subtract(rawXCoord2);
ECFieldElement y3 = eCFieldElement30.Multiply(rawXCoord.Subtract(eCFieldElement31)).Subtract(rawYCoord);
return new FpPoint(Curve, eCFieldElement31, y3, base.IsCompressed);
}
case 1: {
ECFieldElement eCFieldElement19 = base.RawZCoords[0];
ECFieldElement eCFieldElement20 = b.RawZCoords[0];
bool isOne3 = eCFieldElement19.IsOne;
bool isOne4 = eCFieldElement20.IsOne;
ECFieldElement obj = isOne3 ? rawYCoord2 : rawYCoord2.Multiply(eCFieldElement19);
ECFieldElement eCFieldElement21 = isOne4 ? rawYCoord : rawYCoord.Multiply(eCFieldElement20);
ECFieldElement eCFieldElement22 = obj.Subtract(eCFieldElement21);
ECFieldElement obj2 = isOne3 ? rawXCoord2 : rawXCoord2.Multiply(eCFieldElement19);
ECFieldElement b6 = isOne4 ? rawXCoord : rawXCoord.Multiply(eCFieldElement20);
ECFieldElement eCFieldElement23 = obj2.Subtract(b6);
if (eCFieldElement23.IsZero) {
if (eCFieldElement22.IsZero)
return Twice();
return curve.Infinity;
}
ECFieldElement b7 = isOne3 ? eCFieldElement20 : (isOne4 ? eCFieldElement19 : eCFieldElement19.Multiply(eCFieldElement20));
ECFieldElement eCFieldElement24 = eCFieldElement23.Square();
ECFieldElement eCFieldElement25 = eCFieldElement24.Multiply(eCFieldElement23);
ECFieldElement eCFieldElement26 = eCFieldElement24.Multiply(b6);
ECFieldElement b8 = eCFieldElement22.Square().Multiply(b7).Subtract(eCFieldElement25)
.Subtract(Two(eCFieldElement26));
ECFieldElement x = eCFieldElement23.Multiply(b8);
ECFieldElement y2 = eCFieldElement26.Subtract(b8).MultiplyMinusProduct(eCFieldElement22, eCFieldElement21, eCFieldElement25);
ECFieldElement eCFieldElement27 = eCFieldElement25.Multiply(b7);
return new FpPoint(curve, x, y2, new ECFieldElement[1] {
eCFieldElement27
}, 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) {
b4 = rawXCoord2;
b5 = rawYCoord2;
} else {
ECFieldElement eCFieldElement9 = eCFieldElement.Square();
b4 = eCFieldElement9.Multiply(rawXCoord2);
b5 = eCFieldElement9.Multiply(eCFieldElement).Multiply(rawYCoord2);
}
bool isOne2 = eCFieldElement2.IsOne;
ECFieldElement eCFieldElement10;
ECFieldElement eCFieldElement11;
if (isOne2) {
eCFieldElement10 = rawXCoord;
eCFieldElement11 = rawYCoord;
} else {
ECFieldElement eCFieldElement12 = eCFieldElement2.Square();
eCFieldElement10 = eCFieldElement12.Multiply(rawXCoord);
eCFieldElement11 = eCFieldElement12.Multiply(eCFieldElement2).Multiply(rawYCoord);
}
ECFieldElement eCFieldElement13 = eCFieldElement10.Subtract(b4);
ECFieldElement eCFieldElement14 = eCFieldElement11.Subtract(b5);
if (eCFieldElement13.IsZero) {
if (eCFieldElement14.IsZero)
return Twice();
return curve.Infinity;
}
ECFieldElement eCFieldElement15 = eCFieldElement13.Square();
ECFieldElement eCFieldElement16 = eCFieldElement15.Multiply(eCFieldElement13);
ECFieldElement eCFieldElement17 = eCFieldElement15.Multiply(eCFieldElement10);
eCFieldElement7 = eCFieldElement14.Square().Add(eCFieldElement16).Subtract(Two(eCFieldElement17));
y = eCFieldElement17.Subtract(eCFieldElement7).MultiplyMinusProduct(eCFieldElement14, eCFieldElement16, eCFieldElement11);
eCFieldElement8 = eCFieldElement13;
if (!isOne)
eCFieldElement8 = eCFieldElement8.Multiply(eCFieldElement);
if (!isOne2)
eCFieldElement8 = eCFieldElement8.Multiply(eCFieldElement2);
if (eCFieldElement8 == eCFieldElement13)
zSquared = eCFieldElement15;
}
ECFieldElement[] zs;
if (coordinateSystem == 4) {
ECFieldElement eCFieldElement18 = CalculateJacobianModifiedW(eCFieldElement8, zSquared);
zs = new ECFieldElement[2] {
eCFieldElement8,
eCFieldElement18
};
} else
zs = new ECFieldElement[1] {
eCFieldElement8
};
return new FpPoint(curve, eCFieldElement7, y, zs, base.IsCompressed);
}
default:
throw new InvalidOperationException("unsupported coordinate system");
}
}
return Twice();
}
public override ECPoint Twice()
{
if (base.IsInfinity)
return this;
ECCurve curve = Curve;
ECFieldElement rawYCoord = base.RawYCoord;
if (!rawYCoord.IsZero) {
int coordinateSystem = curve.CoordinateSystem;
ECFieldElement rawXCoord = base.RawXCoord;
switch (coordinateSystem) {
case 0: {
ECFieldElement x3 = rawXCoord.Square();
ECFieldElement eCFieldElement9 = Three(x3).Add(Curve.A).Divide(Two(rawYCoord));
ECFieldElement eCFieldElement10 = eCFieldElement9.Square().Subtract(Two(rawXCoord));
ECFieldElement y2 = eCFieldElement9.Multiply(rawXCoord.Subtract(eCFieldElement10)).Subtract(rawYCoord);
return new FpPoint(Curve, eCFieldElement10, y2, base.IsCompressed);
}
case 1: {
ECFieldElement eCFieldElement11 = base.RawZCoords[0];
bool isOne2 = eCFieldElement11.IsOne;
ECFieldElement eCFieldElement12 = curve.A;
if (!eCFieldElement12.IsZero && !isOne2)
eCFieldElement12 = eCFieldElement12.Multiply(eCFieldElement11.Square());
eCFieldElement12 = eCFieldElement12.Add(Three(rawXCoord.Square()));
ECFieldElement eCFieldElement13 = isOne2 ? rawYCoord : rawYCoord.Multiply(eCFieldElement11);
ECFieldElement eCFieldElement14 = isOne2 ? rawYCoord.Square() : eCFieldElement13.Multiply(rawYCoord);
ECFieldElement x4 = rawXCoord.Multiply(eCFieldElement14);
ECFieldElement eCFieldElement15 = Four(x4);
ECFieldElement eCFieldElement16 = eCFieldElement12.Square().Subtract(Two(eCFieldElement15));
ECFieldElement eCFieldElement17 = Two(eCFieldElement13);
ECFieldElement x5 = eCFieldElement16.Multiply(eCFieldElement17);
ECFieldElement eCFieldElement18 = Two(eCFieldElement14);
ECFieldElement y3 = eCFieldElement15.Subtract(eCFieldElement16).Multiply(eCFieldElement12).Subtract(Two(eCFieldElement18.Square()));
ECFieldElement x6 = isOne2 ? Two(eCFieldElement18) : eCFieldElement17.Square();
ECFieldElement eCFieldElement19 = Two(x6).Multiply(eCFieldElement13);
return new FpPoint(curve, x5, y3, new ECFieldElement[1] {
eCFieldElement19
}, 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(3))) {
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()).Square();
eCFieldElement4 = ((eCFieldElement3.BitLength >= a.BitLength) ? eCFieldElement4.Add(eCFieldElement6.Multiply(a)) : eCFieldElement4.Subtract(eCFieldElement6.Multiply(eCFieldElement3)));
}
eCFieldElement5 = Four(rawXCoord.Multiply(eCFieldElement2));
}
ECFieldElement eCFieldElement7 = eCFieldElement4.Square().Subtract(Two(eCFieldElement5));
ECFieldElement y = eCFieldElement5.Subtract(eCFieldElement7).Multiply(eCFieldElement4).Subtract(Eight(x));
ECFieldElement eCFieldElement8 = Two(rawYCoord);
if (!isOne)
eCFieldElement8 = eCFieldElement8.Multiply(eCFieldElement);
return new FpPoint(curve, eCFieldElement7, y, new ECFieldElement[1] {
eCFieldElement8
}, base.IsCompressed);
}
case 4:
return TwiceJacobianModified(true);
default:
throw new InvalidOperationException("unsupported coordinate system");
}
}
return curve.Infinity;
}
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) {
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 b3 = eCFieldElement4.Multiply(eCFieldElement).Invert();
ECFieldElement eCFieldElement5 = eCFieldElement4.Multiply(b3).Multiply(eCFieldElement2);
ECFieldElement eCFieldElement6 = Two(rawYCoord).Multiply(eCFieldElement3).Multiply(eCFieldElement).Multiply(b3)
.Subtract(eCFieldElement5);
ECFieldElement eCFieldElement7 = eCFieldElement6.Subtract(eCFieldElement5).Multiply(eCFieldElement5.Add(eCFieldElement6)).Add(rawXCoord2);
ECFieldElement y = rawXCoord.Subtract(eCFieldElement7).Multiply(eCFieldElement6).Subtract(rawYCoord);
return new FpPoint(Curve, eCFieldElement7, y, base.IsCompressed);
}
case 4:
return TwiceJacobianModified(false).Add(b);
default:
return Twice().Add(b);
}
}
return b;
}
public override ECPoint ThreeTimes()
{
if (base.IsInfinity)
return this;
ECFieldElement rawYCoord = base.RawYCoord;
if (!rawYCoord.IsZero) {
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 b2 = eCFieldElement4.Multiply(eCFieldElement).Invert();
ECFieldElement eCFieldElement5 = eCFieldElement4.Multiply(b2).Multiply(eCFieldElement3);
ECFieldElement eCFieldElement6 = eCFieldElement2.Square().Multiply(b2).Subtract(eCFieldElement5);
ECFieldElement eCFieldElement7 = eCFieldElement6.Subtract(eCFieldElement5).Multiply(eCFieldElement5.Add(eCFieldElement6)).Add(rawXCoord);
ECFieldElement y = rawXCoord.Subtract(eCFieldElement7).Multiply(eCFieldElement6).Subtract(rawYCoord);
return new FpPoint(Curve, eCFieldElement7, y, base.IsCompressed);
}
case 4:
return TwiceJacobianModified(false).Add(this);
default:
return Twice().Add(this);
}
}
return 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) {
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");
}
}
return curve.Infinity;
}
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(a);
return eCFieldElement.Multiply(eCFieldElement2).Negate();
}
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);
}
}
}