Current section
Files
Jump to
Current section
Files
priv/dstu/src/math/ec/ECPoint.cs
using System;
namespace UA.Cryptography.EC
{
public abstract class ECPoint
{
internal readonly ECCurve curve;
internal readonly ECFieldElement x, y;
internal readonly bool withCompression;
protected internal ECPoint(
ECCurve curve,
ECFieldElement x,
ECFieldElement y,
bool withCompression)
{
if (curve == null)
throw new ArgumentNullException("curve");
this.curve = curve;
this.x = x;
this.y = y;
this.withCompression = withCompression;
}
public ECCurve Curve
{
get { return curve; }
}
public ECFieldElement X
{
get { return x; }
}
public ECFieldElement Y
{
get { return y; }
}
public bool IsInfinity
{
get { return x == null && y == null; }
}
public bool IsCompressed
{
get { return withCompression; }
}
public override bool Equals(
object obj)
{
if (obj == this)
return true;
ECPoint o = obj as ECPoint;
if (o == null)
return false;
if (this.IsInfinity)
return o.IsInfinity;
return x.Equals(o.x) && y.Equals(o.y);
}
public override int GetHashCode()
{
if (this.IsInfinity)
return 0;
return x.GetHashCode() ^ y.GetHashCode();
}
public abstract ECPoint Add(ECPoint b);
public abstract ECPoint Subtract(ECPoint b);
public abstract ECPoint Negate();
public abstract ECPoint Twice();
public abstract ECPoint Multiply(BigInteger b);
}
public class F2mPoint
: ECPoint
{
public F2mPoint(
ECCurve curve,
ECFieldElement x,
ECFieldElement y)
: this(curve, x, y, false)
{
}
public F2mPoint(
ECCurve curve,
ECFieldElement x,
ECFieldElement y,
bool withCompression)
: base(curve, x, y, withCompression)
{
if ((x != null && y == null) || (x == null && y != null))
{
throw new ArgumentException("Exactly one of the field elements is null");
}
if (x != null)
{
F2mFieldElement.CheckFieldElements(this.x, this.y);
F2mFieldElement.CheckFieldElements(this.x, this.curve.A);
}
}
[Obsolete("Use ECCurve.Infinity property")]
public F2mPoint(
ECCurve curve)
: this(curve, null, null)
{
}
public override ECPoint Multiply(
BigInteger k)
{
if (this.IsInfinity)
return this;
if (k.SignValue == 0)
return this.curve.Infinity;
return Multiply(this, k);
}
public ECPoint Multiply(ECPoint p, BigInteger k)
{
// TODO Probably should try to add this
//BigInteger e = k.Mod(new BigInteger("173", 10)); // n == order of p
ECPoint r = Curve.Infinity;
for (int t = k.BitLength - 1; t >= 0; --t)
{
r = r.Twice();
if (k.TestBit(t))
r = r.Add(p);
}
return r;
//BigInteger e = k;
//BigInteger h = e.Multiply(BigInteger.Three);
//ECPoint neg = p.Negate();
//ECPoint R = p;
//for (int i = h.BitLength - 2; i > 0; --i)
//{
// R = R.Twice();
// bool hBit = h.TestBit(i);
// bool eBit = e.TestBit(i);
// if (hBit != eBit)
// {
// R = R.Add(hBit ? p : neg);
// }
//}
//return R;
}
protected internal bool YTilde
{
get
{
return this.X.ToBigInteger().SignValue != 0
&& this.Y.Multiply(this.X.Invert()).ToBigInteger().TestBit(0);
}
}
private static void CheckPoints(
ECPoint a,
ECPoint b)
{
if (!a.curve.Equals(b.curve))
throw new ArgumentException("Only points on the same curve can be added or subtracted");
}
public override ECPoint Add(ECPoint b)
{
CheckPoints(this, b);
return AddSimple((F2mPoint) b);
}
internal F2mPoint AddSimple(F2mPoint b)
{
if (this.IsInfinity)
return b;
if (b.IsInfinity)
return this;
F2mFieldElement x2 = (F2mFieldElement) b.X;
F2mFieldElement y2 = (F2mFieldElement) b.Y;
if (this.x.Equals(x2))
{
if (this.y.Equals(y2))
return (F2mPoint) this.Twice();
return (F2mPoint) this.curve.Infinity;
}
ECFieldElement xSum = this.x.Add(x2);
F2mFieldElement lambda
= (F2mFieldElement)(this.y.Add(y2)).Divide(xSum);
F2mFieldElement x3
= (F2mFieldElement)lambda.Square().Add(lambda).Add(xSum).Add(this.curve.A);
F2mFieldElement y3
= (F2mFieldElement)lambda.Multiply(this.x.Add(x3)).Add(x3).Add(this.y);
return new F2mPoint(curve, x3, y3, withCompression);
}
public override ECPoint Subtract(
ECPoint b)
{
CheckPoints(this, b);
return SubtractSimple((F2mPoint) b);
}
internal F2mPoint SubtractSimple(
F2mPoint b)
{
if (b.IsInfinity)
return this;
return AddSimple((F2mPoint) b.Negate());
}
public override ECPoint Twice()
{
if (this.IsInfinity)
return this;
if (this.x.ToBigInteger().SignValue == 0)
return this.curve.Infinity;
F2mFieldElement lambda = (F2mFieldElement) this.x.Add(this.y.Divide(this.x));
F2mFieldElement x2 = (F2mFieldElement)lambda.Square().Add(lambda).Add(this.curve.A);
ECFieldElement ONE = this.curve.FromBigInteger(BigInteger.One);
F2mFieldElement y2 = (F2mFieldElement)this.x.Square().Add(
x2.Multiply(lambda.Add(ONE)));
return new F2mPoint(this.curve, x2, y2, withCompression);
}
public override ECPoint Negate()
{
return new F2mPoint(curve, this.x, this.x.Add(this.y), withCompression);
}
}
}