Showing posts with label addition. Show all posts
Showing posts with label addition. Show all posts

Sunday, July 04, 2010

This will work! P + Q Point addition in C#.NET code

Add appropriate controls and it will work to calculate P + Q, addition of two points on an elliptic curve over a finite field Fp.
And it all works with big Integers.
Be sure that you only use valid numbers (prime for Fp and points that acctually ARE on the curve)
Next version will contain valid curves generated from startpoint and startvalues , plus it will contain an implementation of the double and add algorithm.

Sorry for the horrible buggy primitive spaghetti code without validation and exception handling for now - but I just made it and it works! - tested against a huge amount of numeric examples calculated by hand + toy examples provided by Hoffman, Pipher and Silverman.

It will not handle input of point at infinity. But you already know that P + Ø = P so... here we go.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Numerics;

namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{

}

private void button2_Click(object sender, EventArgs e)
{
calcPoints();

}


private BigInteger calcLambda1(BigInteger y2, BigInteger y1, BigInteger x2, BigInteger x1, BigInteger modspace) {

BigInteger lam1 = (y2 - y1) * CalcInverse((x2 - x1), modspace);

return lam1;
}


private BigInteger calcLambda2(BigInteger x1, BigInteger y1, BigInteger A, BigInteger modspace)
{

BigInteger lam2= (3 * x1 * x1 + A)*CalcInverse((2 * y1), modspace);
return lam2;
}


private BigInteger calcXFinal(BigInteger Lambda, BigInteger x1, BigInteger x2, BigInteger modspace) {
BigInteger bigX= (Lambda*Lambda - x1 - x2)%modspace;
if (bigX < 0) { bigX = bigX + modspace; }
return bigX;

}
private BigInteger calcYFinal(BigInteger Lambda, BigInteger x1, BigInteger x3, BigInteger y1, BigInteger modspace)
{
BigInteger bigY= (Lambda*(x1-x3) - y1)%modspace;
if (bigY < 0) { bigY = bigY + modspace; }
return bigY;
}


private BigInteger CalcInverse(BigInteger n, BigInteger p)
{

BigInteger x = 1;
BigInteger y = 0;
BigInteger a = p;
BigInteger b = n;
BigInteger q, t;
BigInteger res;
while (b != 0)
{
t = b;
//q2 = Math.floor(a/t);
q = BigInteger.Divide(a, t);
b = a - q * t;
a = t;
t = x;
x = y - q * t;
y = t;
}
if (y < 0)
{
res = y + p;
}
else
{
res = y;
}
return res;

}

private void calcPoints() {

BigInteger inputA = BigInteger.Parse(paramA.Text);
BigInteger inputB = BigInteger.Parse(paramB.Text);

BigInteger inputx1 = BigInteger.Parse(paramx1.Text);
BigInteger inputy1 = BigInteger.Parse(paramy1.Text);

BigInteger inputx2 = BigInteger.Parse(paramx2.Text);
BigInteger inputy2 = BigInteger.Parse(paramy2.Text);

BigInteger modp = BigInteger.Parse(paramp.Text);


if ((inputx1 == inputx2) && (inputy1 != inputy2) )
{
resultx3.Text = "point at infinity";
resulty3.Text = "point at infinity";
}
else {


if ((inputx1 == inputx2) && (inputy1 == inputy2))
{

BigInteger l2 = (calcLambda2(inputx1,inputy1,inputA, modp))%modp;
dontpanic.Text = l2.ToString();

BigInteger resl2x3 = (calcXFinal(l2, inputx1, inputx2, modp))%modp;
BigInteger resl2y3 = (calcYFinal(l2, inputx1, resl2x3, inputy1, modp))%modp;


resultx3.Text = resl2x3.ToString();
resulty3.Text = resl2y3.ToString();


}
else {

BigInteger l1 = (calcLambda1(inputy2,inputy1, inputx2,inputx1, modp))%modp;

dontpanic.Text = l1.ToString();
BigInteger resl1x3 = (calcXFinal(l1, inputx1, inputx2, modp))%modp;
BigInteger resl1y3 = (calcYFinal(l1, inputx1, resl1x3, inputy1, modp))%modp;

resultx3.Text = resl1x3.ToString();
resulty3.Text = resl1y3.ToString();


}

}


}
}


The BigInteger is a part of the brand new package System.Numerics in .NET 4.0
more about that one here -->
http://msdn.microsoft.com/en-us/library/system.numerics.biginteger.aspx
For some reason the System.Numerics is not automatically added to projects - select menu project/Add Reference../ select tab: .NET and find System. Numerics.

Saturday, June 06, 2009

Double and Add algorithm

Very much like the fast powering algorithm - binary expansion can be used to calculate Q= nP fast.
ex n=947 = 2^9+2^8+2^7+2^5+2^4+2^1+2^0

which means that 947P = P+2P+16P+32P+128P+256P+512P. Thats 9 doublings and 6 additions, much better than 946 additions....
if we allow subtraction as well (ternary expansion) its even better.

want to calculate nP?

algorithm:
1. input point P from E(Fp) and n>=1
2. set Q=P and R=Ø (point at infinity)
3. loop while n>0{
if n = 1 (mod2) set R= R+Q
set Q=2Q and n=n/2 (floor)}
4.return R (which equals nP)


I've now posted working sourcecode available at http://christelbach.com
(source code contained in master thesis)

for instance this:
//double and add algorithm
private BigInteger[] calculatenP(BigInteger x, BigInteger y, BigInteger n, BigInteger A, BigInteger modp)
{
BigInteger[] Q = { x, y };
BigInteger[] R = { 0, 0 };
while (n > 0)
{
BigInteger t = BigInteger.ModPow(n, 1, 2);
if ((t) == 1)
{
R = addPoints(Q[0], Q[1], R[0], R[1], modp);
}
Q = doublePoints(Q[0], Q[1], A, modp);
n = n / 2;
}
BigInteger[] resPoint = { R[0], R[1] };
return resPoint;
}


Look in the pdf file for the methods addPoints() and doublePoints()

Sunday, May 24, 2009

Punktaddition

Simpelt demonstationseksempel på R, med værdier max 'integer' størrelse:
Der konstrueres passende felter i html dokument der matcher id'erne i denne kode.
Denne meget lille primitive løsning tester IKKE for om punkterne overhovedet ligger på kurven - det er på eget ansvar. Det er kun i tilfældet P1=p2 hvor y1 er forskellig fra nul at kurvens koeficienter direkte indgår i additionsberegningen - og derfor der fejlkilden skal findes.
fgl placeres i eksternt javascript

window.onload= initForm;
function initForm(){
document.getElementById("ok").onclick = calcPoint;
}
function calcPoint(){
var x1= parseInt(document.getElementById("xx1").value);
var y1= parseInt(document.getElementById("yy1").value);

var x2= parseInt(document.getElementById("xx2").value);
var y2= parseInt(document.getElementById("yy2").value);
if((x2-x1) != 0 ){
var m = (y2-y1)/(x2-x1);
var x3 = (m*m)-x1-x2;
var y3= m*(x1-x3)-y1;
document.getElementById("r1").innerHTML="P3, (x3,y3) er "+x3+","+y3;
}
else if (((x2-x1) == 0) && ((y2-y1) != 0)){
alert("det er farligt at dividere med nul, P1 + P2 giver punktet i uendelig");}
else if ((x2-x1)==0 && (y2-y1)==0){
if(y2 != 0){
var A= parseInt(document.getElementById("AA").value);
var m = ((3*x1*x1)+A)/(2*y1);
var x3 = (m*m)-2*x1;
var y3= m*(x1-x3)-y1;
document.getElementById("r1").innerHTML="P3, (x3,y3) er "+x3+","+y3;
}
else{
alert("P1 + P2 giver punktet i uendelig");
document.getElementById("r1").innerHTML="eternal sunshine in a spotless mind";
}
}
else{
alert("noget gik helt galt");
document.getElementById("r1").innerHTML="42";
}

return false;
}