diff --git a/Crypto.csproj b/Crypto.csproj
index 08be3e4..946c98f 100644
--- a/Crypto.csproj
+++ b/Crypto.csproj
@@ -32,8 +32,9 @@
-
+
+
@@ -47,6 +48,10 @@
{97CA3CA9-98B3-4492-B072-D7A5995B68E9}
sharp.extensions
+
+ {56733EC1-7D97-48D0-AA4C-98EA624A5A21}
+ sharp.contracts
+
\ No newline at end of file
diff --git a/EC/CurvePoint.cs b/EC/CurvePoint.cs
index 62b8974..d32c28f 100644
--- a/EC/CurvePoint.cs
+++ b/EC/CurvePoint.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using BigInt;
using System.Text;
using System.Runtime.CompilerServices;
@@ -7,56 +7,115 @@ namespace Crypto.EC
{
public class CurvePoint
{
- public CurvePoint(EllipticCurve curve,UInteger x,UInteger y){
+ public static readonly CurvePoint INFINITY = new CurvePoint();
+
+ public CurvePoint(EllipticCurve curve,Integer x,Integer y){
Curve = curve;
X = x;
Y = y;
}
- public string toHexString(){
+ private CurvePoint(){
+ this.Curve = null;
+ this.X = 0;
+ this.Y = 0;
+ }
+
+ public string toHexString()
+ {
StringBuilder sb = new StringBuilder();
- sb.Append(X.toHexString());
+ sb.Append(((UInteger)X).toHexString());
sb.Append(".");
- sb.Append(Y.toHexString());
+ sb.Append(((UInteger)Y).toHexString());
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(),Y.ToString());
+ }
+
public EllipticCurve Curve { get; private set; }
- public UInteger X { get; private set; }
- public UInteger Y { get; private set; }
+ public Integer X { get; private set; }
+ public Integer 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)
{
- return p1.Curve.Add(p1,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, UInteger n)
+
+ public static CurvePoint operator -(CurvePoint p1, CurvePoint p2)
{
- if (p1.Y == UInteger.ZERO){
- throw new NotImplementedException("Eternity point not implemented");
+ 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, Integer n)
+ {
+ if ((object)p1 == (object)INFINITY){
+ return INFINITY;
+ }
+
+ if (p1.Y == Integer.ZERO){
+ return INFINITY;
+ }
+
+ if (n.isZero()){
+ throw new NotImplementedException("CurevPoint * 0");
}
CurvePoint result = null;
CurvePoint p = p1;
int i;
+ int bitwidth = n.Log2();
- for (i = 0; i < 256; i++)
+ if (bitwidth < 0){
+ bitwidth = -bitwidth;
+ }
+
+ for (i = 0; i < bitwidth; i++)
{
- if (n[i]){
- result = p;
+ if (n[i])
break;
- }
+
p += p;
}
- for (; i < 256; i++)
+
+ result = p;
+
+ for (i++; i <= bitwidth; i++)
{
p += p;
if (n[i]){
- result += p;
+ result = p + result;
}
}
diff --git a/EC/EllipticCurve.cs b/EC/EllipticCurve.cs
index 55c5636..8336e14 100644
--- a/EC/EllipticCurve.cs
+++ b/EC/EllipticCurve.cs
@@ -7,15 +7,15 @@ namespace Crypto.EC
{
public class EllipticCurve
{
- public UInteger a { get; private set; }
- public UInteger b { get; private set; }
- public UInteger n { get; private set; }
+ public Integer a { get; private set; }
+ public Integer b { get; private set; }
+ public Integer n { get; private set; }
public int h { get; private set; }
public CurvePoint G { get; private set; }
public IntField Fp { get; private set; }
- public EllipticCurve(UInteger p,UInteger a,UInteger b,UInteger xG,UInteger yG,UInteger n,int h)
+ public EllipticCurve(Integer p,Integer a,Integer b,Integer xG,Integer yG,Integer n,int h)
{
this.Fp = new IntField(p);
this.a = a;
@@ -29,38 +29,38 @@ namespace Crypto.EC
}
}
- public UInteger Y2(UInteger x){
+ public Integer Y2(Integer x){
- UInteger yy = x;
+ Integer yy = x;
- Console.WriteLine("Y(x): X = {0}",x.toHexString());
- Console.WriteLine("Y(x): x^2 = {0}",yy.Pow(2).toHexString());
+ //Console.WriteLine("Y(x): X = {0}",x.toHexString());
+ //Console.WriteLine("Y(x): x^2 = {0}",yy.Pow(2).toHexString());
yy = yy.Pow(3);
- Console.WriteLine("Y(x): x^3 = {0}",yy.toHexString());
+ //Console.WriteLine("Y(x): x^3 = {0}",yy.toHexString());
yy += (a * x);
- Console.WriteLine("Y(x): x^3 + ax = {0}",yy.toHexString());
+ //Console.WriteLine("Y(x): x^3 + ax = {0}",yy.toHexString());
yy += b;
- Console.WriteLine("Y(x) x^3 + ax + b = {0}",yy.toHexString());
+ //Console.WriteLine("Y(x) x^3 + ax + b = {0}",yy.toHexString());
- yy %= this.Fp.FieldModulo;
+ yy %= (Integer)this.Fp.FieldModulo;
- Console.WriteLine("Y(x) mod p = {0}",yy.toHexString());
+ //Console.WriteLine("Y(x) mod p = {0}",yy.toHexString());
return yy;
}
public bool isOnCurve(CurvePoint p){
- UInteger py2 = this.Fp.Fit(p.Y.Pow(2));
- UInteger pcy2 = Y2(p.X);
+ Integer py2 = this.Fp.Fit(p.Y.Pow(2));
+ Integer pcy2 = Y2(p.X);
- Console.WriteLine("CHECK A: {0}",py2.toHexString());
- Console.WriteLine("CHECK B: {0}",pcy2.toHexString());
+ //Console.WriteLine("CHECK A: {0}",py2.toHexString());
+ //Console.WriteLine("CHECK B: {0}",pcy2.toHexString());
return (py2 == pcy2);
}
@@ -69,57 +69,39 @@ namespace Crypto.EC
{
if (((object)p1 == null) || ((object)p2 == null))
{
- throw new ArgumentException("CurvePoints to be added must not be null");
+ throw new ArgumentException("SignedCurvePoints to be added must not be null");
}
if (p1.Curve != p2.Curve)
{
- throw new ArgumentException("Curvepoints to be added must belong to the same curve!");
+ throw new ArgumentException("SignedCurvePoints to be added must belong to the same curve!");
}
- if (p1 == p2)
- {
-// UInteger inv2y = Euclid.inverse(this.Fp.Fit(p1.Y << 1),this.Fp.FieldModulo);
- UInteger inv2y = Euclid.inverse((p1.Y * 2),this.Fp.FieldModulo);
- UInteger s = Fp.Fit(p1.X.Pow(3)) * 3;
- s += p1.Curve.a;
- s *= inv2y;
-
- //(((p1.X.Pow(2) * 3) + p1.Curve.a) / (p1.Y << 1));
-
- UInteger xR = (s.Pow(2) - (p1.X * 2));
- UInteger yR = ((s * (p1.X - xR)) - p1.Y);
-
- xR = this.Fp.Fit(xR);
- yR = this.Fp.Fit(yR);
-
- return new CurvePoint(p1.Curve, xR, yR);
+ if ((p1 != p2) && (p1.X == p2.X)){
+ return CurvePoint.INFINITY;
}
- if (p1.X == p2.X)
- {
- throw new NotImplementedException("Eternity point not implemented");
- }
- else
- {
- UInteger s = (((p1.Y - p2.Y) / (p1.X - p2.X)));
- UInteger xR = (s.Pow(2) - p1.X - p2.X);
- UInteger yR = ((s * (p1.X - xR)) - p1.Y);
+ Integer lambda,divlambda;
- xR = this.Fp.Fit(xR);
- yR = this.Fp.Fit(yR);
-
- return new CurvePoint(p1.Curve, xR, yR);
+ if (p1 == p2){
+ lambda = Fp.Fit(3 * p1.X.Pow(2) + a);
+ divlambda = Fp.Fit(2 * p1.Y);
+ } else {
+ lambda = Fp.Fit(p2.Y - p1.Y);
+ divlambda = Fp.Fit(p2.X - p1.X);
}
- throw new NotImplementedException("Point addition not yet implemented");
+ lambda = lambda * Euclid.inverse(divlambda, Fp.FieldModulo);
+
+ Integer xR = (lambda.Pow(2) - p1.X - p2.X);
+ Integer yR = (lambda * (p1.X - xR)) - p1.Y;
+
+ xR = Fp.Fit(xR);
+ yR = Fp.Fit(yR);
+
+ return new CurvePoint(this, xR, yR);
}
-/* public CurvePoint getPoint(T x){
- x = new T(x, this.Fp);
- return new CurvePoint(this,x,Y(x));
- }
-*/
public override string ToString()
{
StringBuilder sb = new StringBuilder();
@@ -134,20 +116,20 @@ namespace Crypto.EC
}
public static EllipticCurve createSecp256k1(){
- UInteger p = (UInteger.ONE << 256);
- p -= UInteger.ONE;
- p -= (UInteger.ONE << 32);
- p -= (UInteger.ONE << 9);
- p -= (UInteger.ONE << 8);
- p -= (UInteger.ONE << 7);
- p -= (UInteger.ONE << 6);
- p -= (UInteger.ONE << 4);
+ Integer p = (Integer.ONE << 256);
+ p -= Integer.ONE;
+ p -= (Integer.ONE << 32);
+ p -= (Integer.ONE << 9);
+ p -= (Integer.ONE << 8);
+ p -= (Integer.ONE << 7);
+ p -= (Integer.ONE << 6);
+ p -= (Integer.ONE << 4);
- UInteger xG = UInteger.fromHexString("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798");
- UInteger yG = UInteger.fromHexString("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8");
+ Integer xG = Integer.fromHexString("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798");
+ Integer yG = Integer.fromHexString("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8");
- UInteger n = UInteger.fromHexString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141");
- return new EllipticCurve(p, new UInteger(0), new UInteger(7), xG, yG, n, 1);
+ Integer n = Integer.fromHexString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141");
+ return new EllipticCurve(p, new Integer(0), new Integer(7), xG, yG, n, 1);
}
}
}
diff --git a/EC/ProjectiveCurvePoint.cs b/EC/ProjectiveCurvePoint.cs
new file mode 100644
index 0000000..160ffac
--- /dev/null
+++ b/EC/ProjectiveCurvePoint.cs
@@ -0,0 +1,198 @@
+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;
+ }
+
+ }
+}