160 lines
3.3 KiB
C#
160 lines
3.3 KiB
C#
using System;
|
|
using System.Text;
|
|
using System.Numerics;
|
|
|
|
namespace Crypto.EC
|
|
{
|
|
public class CurvePoint
|
|
{
|
|
public static readonly CurvePoint INFINITY = new CurvePoint();
|
|
|
|
public CurvePoint(EllipticCurve curve,BigInteger x,BigInteger y){
|
|
Curve = curve;
|
|
X = x;
|
|
Y = y;
|
|
}
|
|
|
|
private CurvePoint(){
|
|
this.Curve = null;
|
|
this.X = 0;
|
|
this.Y = 0;
|
|
}
|
|
|
|
public string toHexString()
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
sb.Append(X.ToString("X"));
|
|
sb.Append(".");
|
|
sb.Append(Y.ToString("X"));
|
|
return sb.ToString();
|
|
}
|
|
|
|
public string toHex()
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
sb.Append(X.ToString("X32"));
|
|
sb.Append(Y.ToString("X32"));
|
|
return sb.ToString();
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
if ((object)this == (object)INFINITY){
|
|
return String.Format("[CurvePoint INFINITY]");
|
|
}
|
|
return String.Format("[CurvePoint X={0} Y={1}]",X.ToString("X"),Y.ToString("X"));
|
|
}
|
|
|
|
public EllipticCurve Curve { get; private set; }
|
|
public BigInteger X { get; private set; }
|
|
public BigInteger Y { get; private set; }
|
|
|
|
public bool isOnCurve(){
|
|
return this.Curve.isOnCurve(this);
|
|
}
|
|
|
|
public bool isInfinity(){
|
|
return ((object)this == (object)INFINITY);
|
|
}
|
|
|
|
public CurvePoint Negated(){
|
|
return new CurvePoint(Curve, X, Curve.Fp.AdditiveInverse(Y));
|
|
}
|
|
|
|
public static CurvePoint operator +(CurvePoint p1, CurvePoint p2)
|
|
{
|
|
if ((object)p1 == (object)INFINITY){
|
|
return p2;
|
|
}
|
|
if ((object)p2 == (object)INFINITY){
|
|
return p1;
|
|
}
|
|
|
|
return p1.Curve.Add(p1, p2);
|
|
}
|
|
|
|
public static CurvePoint operator -(CurvePoint p1, CurvePoint p2)
|
|
{
|
|
if ((object)p1 == (object)INFINITY){
|
|
return p2;
|
|
}
|
|
if ((object)p2 == (object)INFINITY){
|
|
return p1;
|
|
}
|
|
return p1.Curve.Add(p1, p2.Negated());
|
|
}
|
|
|
|
public static CurvePoint operator *(CurvePoint p1, BigInteger n)
|
|
{
|
|
if ((object)p1 == (object)INFINITY){
|
|
return INFINITY;
|
|
}
|
|
|
|
if (p1.Y == BigInteger.Zero){
|
|
return INFINITY;
|
|
}
|
|
|
|
if (n.IsZero){
|
|
throw new NotImplementedException("CurvePoint * 0");
|
|
}
|
|
|
|
CurvePoint result = null;
|
|
CurvePoint p = p1;
|
|
|
|
int i;
|
|
byte[] nBytes = n.ToByteArray();
|
|
|
|
for (i = 0; i < nBytes.Length<<3; i++)
|
|
{
|
|
if ((nBytes[i >> 3] & (1 << (i & 0x07))) != 0)
|
|
break;
|
|
|
|
p += p;
|
|
}
|
|
|
|
result = p;
|
|
|
|
for (i++; i < nBytes.Length<<3; i++)
|
|
{
|
|
p += p;
|
|
if ((nBytes[i >> 3] & (1 << (i & 0x07))) != 0)
|
|
{
|
|
result = p + result;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public static bool operator ==(CurvePoint p1, CurvePoint p2)
|
|
{
|
|
if ((p1 is null)||(p2 is null)){
|
|
return false;
|
|
}
|
|
return (p1.X == p2.X) && (p1.Y == p2.Y);
|
|
}
|
|
public static bool operator !=(CurvePoint p1, CurvePoint p2)
|
|
{
|
|
if ((p1 is null)||(p2 is null)){
|
|
return false;
|
|
}
|
|
return (p1.X != p2.X) || (p1.Y != p2.Y);
|
|
}
|
|
|
|
public override bool Equals(object obj) => (obj is CurvePoint cp2) && X.Equals(cp2.X) && Y.Equals(cp2.Y);
|
|
public override int GetHashCode() => X.GetHashCode() ^ Y.GetHashCode();
|
|
|
|
public byte[] ToByteArray()
|
|
{
|
|
int bytesPerValue = Curve.Fp.FieldModulo.GetByteCount();
|
|
byte[] result = new byte[bytesPerValue*2];
|
|
X.TryWriteBytes(new Span<byte>(result, 0, bytesPerValue), out int bytesWritten);
|
|
Y.TryWriteBytes(new Span<byte>(result, bytesPerValue, bytesPerValue), out bytesWritten);
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
}
|
|
}
|