sharp-crypto/EC/ProjectiveCurvePoint.cs

199 lines
4.0 KiB
C#

using System;
using BigInt;
using System.CodeDom;
using sharp.contracts;
namespace Crypto.EC
{
public class ProjectiveCurvePoint
{
public static readonly ProjectiveCurvePoint INFINITY = new ProjectiveCurvePoint(null,1,0,0);
public Integer X { get; set; }
public Integer Y { get; set; }
public Integer Z { get; set; }
public EllipticCurve Curve { get; private set; }
public ProjectiveCurvePoint(CurvePoint p)
{
this.Curve = p.Curve;
this.X = p.X;
this.Y = p.Y;
this.Z = 1;
}
public ProjectiveCurvePoint(EllipticCurve curve,Integer x,Integer y,Integer z)
{
this.Curve = curve;
this.X = x;
this.Y = y;
this.Z = z;
}
public CurvePoint toCurvePoint(){
if (Z.isZero()){
return CurvePoint.INFINITY;
}
Integer iz = Euclid.inverse(Z, Curve.Fp.FieldModulo);
Integer nx = Curve.Fp.Fit(X * iz);
Integer ny = Curve.Fp.Fit(Y * iz);
return new CurvePoint(Curve, nx, ny);
}
public override bool Equals(object obj)
{
ProjectiveCurvePoint p = INFINITY;
return new BooleanConditional()
.requires(obj != null)
.requires(GetType().IsInstanceOfType(obj))
.does( () => { p = (ProjectiveCurvePoint)obj; } )
.requires(this.Curve == p.Curve)
.requires(this.X == p.X)
.requires(this.Y == p.Y)
.requires(this.Z == p.Z)
.isSuccess();
}
public ProjectiveCurvePoint doubled()
{
Integer s = Curve.Fp.Fit(Y * Z);
Integer B = Curve.Fp.Fit(X * Y * s);
Integer w = Curve.Fp.Fit(
(Curve.a * Z.Pow(2)) +
(X.Pow(2) * 3)
);
Integer h = Curve.Fp.Fit(w.Pow(2) - (B * 8));
Integer xd = h * s * 2;
Integer yd = (
(w * ((B * 4) - h)) -
(Y.Pow(2) * s.Pow(2) * 8)
);
Integer zd = s.Pow(3) * 8;
xd = Curve.Fp.Fit(xd);
yd = Curve.Fp.Fit(yd);
zd = Curve.Fp.Fit(zd);
return new ProjectiveCurvePoint(Curve,xd,yd,zd);
}
public ProjectiveCurvePoint add(ProjectiveCurvePoint p){
Integer u = Curve.Fp.Fit( (p.Y * Z) - (Y * p.Z) );
Integer v = Curve.Fp.Fit( (p.X * Z) - (X * p.Z) );
Integer A = Curve.Fp.Fit(
(Z * p.Z * u.Pow(2)) - v.Pow(3) - (v.Pow(2) * X * p.Z * 2)
);
Integer xd = v * A;
Integer yd = (
(u * ((X * p.Z * v.Pow(2)) - A)) -
(v.Pow(3) * Y * p.Z)
);
Integer zd = Z * p.Z * v.Pow(3);
xd = Curve.Fp.Fit(xd);
yd = Curve.Fp.Fit(yd);
zd = Curve.Fp.Fit(zd);
if (zd == 0){
return INFINITY;
}
return new ProjectiveCurvePoint(Curve, xd, yd, zd);
}
public ProjectiveCurvePoint Negated(){
return new ProjectiveCurvePoint(Curve, X, Curve.Fp.AdditiveInverse(Y), Z);
}
public override string ToString()
{
return string.Format("[ProjectiveCurvePoint: Curve=... X={1} Y={2} Z={3}]", Curve,X,Y,Z);
}
public static implicit operator ProjectiveCurvePoint(CurvePoint p){
return new ProjectiveCurvePoint(p);
}
public static ProjectiveCurvePoint operator +(ProjectiveCurvePoint p1, ProjectiveCurvePoint p2)
{
if ((object)p1 == INFINITY){
return p2;
} else if ((object)p2 == INFINITY){
return p1;
} else if (p1.Equals(p2)){
return p1.doubled();
} else {
return p1.add(p2);
}
}
public static ProjectiveCurvePoint operator -(ProjectiveCurvePoint p1, ProjectiveCurvePoint p2)
{
if ((object)p1 == INFINITY)
{
return p2;
}
else if ((object)p2 == INFINITY)
{
return p1;
}
return p1 + p2.Negated();
}
public static ProjectiveCurvePoint operator *(ProjectiveCurvePoint p1, Integer n)
{
if ((object)p1 == (object)INFINITY)
{
return INFINITY;
}
if (p1.Y == Integer.ZERO)
{
return INFINITY;
}
if (n.isZero())
{
throw new NotImplementedException("CurevPoint * 0");
}
ProjectiveCurvePoint result = null;
ProjectiveCurvePoint p = p1;
int i;
int bitwidth = n.Log2();
if (bitwidth < 0)
{
bitwidth = -bitwidth;
}
for (i = 0; i < bitwidth; i++)
{
if (n[i])
break;
p += p;
}
result = p;
for (i++; i <= bitwidth; i++)
{
p += p;
if (n[i])
{
result = p + result;
}
}
return result;
}
}
}