ln.crypto.ec/ln.crypto.ec/CurvePoint.cs

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;
}
}
}