Загрузка данных


Файл:EllipLong.c
//циклическая группа (скалярное произведение удвоение-сложение Num*(xP,yP))
#include <stdio.h>
#include <math.h>
#include "larif16-2.c"
#include <string.h>
#include <stdlib.h>
#include <time.h>

//параметры области определения

//================================================================================
	//модуль
char	ps[] = "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"; 
	//параметры эллиптической фукции
int	a = 0;
int	b = 7;
	//базовая точка
char	xGs[] = "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798";
char	yGs[] = "483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8";
	//порядок подгруппы
char	ns[] = "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141";
	//кофактор
int h=1;
//====================================================================================
/*
char	ps[] = "61"; 
	//параметры эллиптической фукции
int	a = 2;
int	b = 3;
//базовая точка	

char	xGs[] = "3";
//char	xGs[] = "79be667ef9dcbbac55a06295ce870b00029bfcdb2dce28d959f2815b16f81798";
char	yGs[] = "6";
	//порядок подгруппы
char	ns[] = "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141";
	//кофактор
int h=1;
*/
LDig P, xG, yG, n;

//инициализация параметров эллиптической кривой
void InitPar(){
	InitLong(&P);
	InitLong(&n);
	InitLong(&xG);
	InitLong(&yG);
	Read16Long(&P,ps);
	Read16Long(&n,ns);
	Read16Long(&xG,xGs);
	Read16Long(&yG,yGs);
	
	return;
}

//длинный остаток от деления (mod), результат в Ost
void OstLong(LDig *A, LDig *Ost){
	LDig Res;
	InitLong(&Res);
	LongDivLong(A, &P, &Res, Ost);
	//если остаток - отрицательный
	if ((Ost->sign<0)&&!IsNulLong(Ost)){
		SumLongA(Ost, &P);
	}

	return;
}

void OstLongMod(LDig *A, LDig *Ost, LDig *mod){
	LDig Res;
	InitLong(&Res);
	LongDivLong(A, mod, &Res, Ost);
	//если остаток - отрицательный
	if ((Ost->sign<0)&&!IsNulLong(Ost)){
		SumLongA(Ost, mod);
	}

	return;
}

//длинный остаток от деления (mod), результат в A
void OstLongA(LDig *A){
	LDig Ost;
	InitLong(&Ost);
	OstLong(A, &Ost);
	*A=Ost;
	return;
}

void OstLongAMod(LDig *A, LDig *mod){
	LDig Ost;
	InitLong(&Ost);
	OstLongMod(A, &Ost, mod);
	*A=Ost;
	return;
}

//расширенный алгоритм Евклида для длинных чисел без s, не используется
void  LongEnhEvklid(LDig *A, LDig *B, LDig *t, LDig *nod){
	LDig *r1, *r2, *t1, *t2, *r, *q, *tt,  *C;
	int i=0;
	char s1[256];
	r1=malloc(sizeof(LDig));
	r2=malloc(sizeof(LDig));
	t1=malloc(sizeof(LDig));
	t2=malloc(sizeof(LDig));	
	r=malloc(sizeof(LDig));
	q=malloc(sizeof(LDig));
	tt=malloc(sizeof(LDig));
	C=malloc(sizeof(LDig));
	InitLong(r1); 	InitLong(r2);
	InitLong(t1); 	InitLong(t2);	
	InitLong(q); 	InitLong(r);
	InitLong(tt);
	InitLong(C); 	
//ShowLongS(A);

	//начальные присвоения
	*r1=*A;	*r2=*B;
	t1->lm[0]=0;	t2->lm[0]=1;
	Dig16Str(i, s1);
//	printf("s1=%s\n",s1);
//	WriteInFile(r2,s1);
	while(!IsNulLong(r2)){
		i++;
		InitLong(q); 	InitLong(r);
		if (i==0x7f){
//		WriteInFile(r2,"r2");	
//		WriteInFile(r1,"r1");
		}
		LongDivLong(r1,r2,q,r);
		*r1=*r2;	*r2=*r;
		InitLong(C); 
		InitLong(tt);		
		MulTwoLong(q, t2, C);
		SubLong(t1,C,tt);
		*t1=*t2;	*t2=*tt;

	Dig16Str(i, s1);
//	printf("s1=%s\n",s1);
//	WriteInFile(r2,s1);
	}
//	printf("i=%d\n",i);
	*nod=*r1;
	*t=*t1;
	free(r1);	free(r2);	
	free(t1);	free(t2);	
	free(r);		free(q);	
	free(tt);	free(C);

	return;
}

	//Мультипликативная инверсия A*T=1 ищем T
void invA(LDig *A, LDig *T){
	LDig t, nod,	Ed;
	InitLong(&t);
	InitLong(&nod);
	InitLong(&Ed);
	Ed.lm[0]=1;
//	ShowLongS(A);	
	LongEnhEvklid(&P, A, &t, &nod);
	if(!Eq(&nod, &Ed)) printf("err\n");
//	ShowLongS(&nod);
	*T=t;

	return;
}

	//Мультипликативная инверсия по модулю A*T=1 mod n ищем T
void invAMod(LDig *A, LDig *T, LDig *n){
	LDig t, nod,	Ed;
	InitLong(&t);
	InitLong(&nod);
	InitLong(&Ed);
	Ed.lm[0]=1;
//	ShowLongS(A);	
	LongEnhEvklid(n, A, &t, &nod);
	if(!Eq(&nod, &Ed)) printf("err\n");
//	ShowLongS(&nod);
	*T=t;

	return;
}

//сложение двух точек P+Q=R, результат в R
void AddPoint(LDig *xP, LDig *yP, LDig *xQ, LDig *yQ, LDig *xR, LDig *yR){
	LDig *m, *s1, *s2, *C1, *C2, *C3;
	m=malloc(sizeof(LDig));
	s1=malloc(sizeof(LDig));
	s2=malloc(sizeof(LDig));		
	C1=malloc(sizeof(LDig));
	C2=malloc(sizeof(LDig));
	C3=malloc(sizeof(LDig));		

	InitLong(m);
	InitLong(s1);
	InitLong(s2);	
	InitLong(C1);	
	InitLong(C2);		
	InitLong(C3);		
	
	SubLong(xP, xQ, C1);	//C1=xP-xQ
	OstLongA(C1);
//	ShowLongS(C1);
	SubLong(yP, yQ, C2);	//C2=yP-yQ
	OstLongA(C2);
	
	//Проверка на особую точку
	//Если P=0, то P+Q=Q
	if(IsNulLong(xP)&&IsNulLong(yP)){
		*xR=*xQ;
		*yR=*yQ;
		return;
	}
	//Если Q=0, то P+Q=P
	if(IsNulLong(xQ)&&IsNulLong(yQ)){
		*xR=*xP;
		*yR=*yP;
		return;
	}
	//Если P=-Q (xP=xQ и yP=-yQ) то R-особая точка
	if(IsNulLong(C1)){
		if (!IsNulLong(C2)){
			SumLong(yP,yQ,C3);
			OstLongA(C3);
			if(IsNulLong(C3)){
				InitLong(xR);
				InitLong(yR);
//				InitLong(C3);
				return;
			}
		}
	}
	
	if (IsNulLong(C1)&&IsNulLong(C2)){
		InitLong(C1);
		InitLong(C2);
		//s1=xP*xP*3+a (mod p)
		MulTwoLong(xP, xP, C1);	//C1=xP*xP
		OstLongA(C1);
		MulA(C1, 3);		//C1=C1*3
		DigToArray(a,C2);
		SumLongA(C1,C2);	//C1+a
		OstLong(C1, s1);	//s1=C1%p
		InitLong(C1);
		InitLong(C2);
		//s2=(2*yP)^-1
		Mul(yP, 2, C1);	//C1=yP*2
		OstLong(C1,C2);
		if(IsNulLong(C2)) printf("null\n");
		invA(C2, s2);		//s2=C1^-1
		OstLongA(s2);
	}
	else{
		//s1=yP-yQ
		OstLong(C2, s1);		//s1=C2%p
		//s2=xP-xQ
		OstLong(C1,C3);
		if(IsNulLong(C3)) printf("null\n");
//		if ((i==0)&&(j==13))	WriteInFile(C3, "C3");
		
		invA(C3, s2);					//s2=C1^-1
		OstLongA(s2);
	}
	InitLong(C1);						//C1=0
	InitLong(C2);						//C2=0

	//xR=m*m-(xP+xQ)
	MulTwoLong(s1, s2, m);		//m=s1*s2
	OstLongA(m);			//m=C1%p
	MulTwoLong(m, m, C1);	//C1=m*m
	OstLongA(C1);
	SumLong(xP, xQ, C2);			//C2=xP+xQ
	OstLongA(C2);
	SubLong(C1, C2, xR);		//xR=C1-C2
	OstLongA(xR);			//xR=C3%p
	InitLong(C1);						//C1=0
	InitLong(C2);						//C2=0
	
	//yR=yP+m(xR-xP)
	SubLong(xR, xP, C1);			//C1=xR-xP
	OstLongA(C1);

	MulTwoLong(C1, m, C2);	//C2=C1*m	
	OstLongA(C2);
	SumLong(yP, C2, yR);		//C3=yP+C2
	OstLongA(yR);

	//меняем знак yR=-yR
	yR->sign=-yR->sign;			//C1=-C1
	OstLongA(yR);			//yR=C1%p
//			ShowLongS(yR);
	free(m); free(s1);	free(s2); free(C1);	free(C2); free(C3);

	return;
}

//сложение двух точек P+Q, результат в P
void AddPointP(LDig *xP, LDig *yP, LDig *xQ, LDig *yQ){
	LDig *xR, *yR;
	xR=malloc(sizeof(LDig));
	yR=malloc(sizeof(LDig));		
		
	InitLong(xR);		
	InitLong(yR);		
	
	AddPoint(xP, yP, xQ, yQ, xR, yR);
	*xP=*xR;
	*yP=*yR;
	free(xR); free(yR);
	return;
}

//скалярное произведение (алгоритм удвоения-сложения)
void ScalMulPoint(LDig *K, LDig *xP, LDig *yP, LDig *xR, LDig *yR){
	int i,j,m;
	LDig Sx, Sy, xP1, yP1;
	InitLong(&Sx);
	InitLong(&Sy);
	xP1=*xP;
	yP1=*yP;
//	printf("len=%d\n",K->len);
	for (i=0;i<K->len;i++){	//цикл по байтам
		m=K->lm[i];
//		printf("m=%x i=%d\n", m,i);
		for (j=0;j<mm;j++){	//цикл по разрядам внутри байта
			if ((i==0)&&(j==0)){
				if((m%2)==1) 	{Sx=*xP;	Sy=*yP;}	//AddPointP(&Sx, &Sy,  xP, yP); 	
			}
			else{			
				AddPointP(&xP1, &yP1, &xP1, &yP1);	//удвоение
				if((m%2)==1) 	AddPointP(&Sx, &Sy,  &xP1, &yP1); 	//сложение
				if ((j==13)&&(i==0)) ShowLongS(&Sy);
//				printf("		%d\n",j);
			}
			m=m/2;
		}
	}
	*xR=Sx;
	*yR=Sy;
	
	return;
}

//случайное длинное от 1 до n-1
void LongRand(LDig *M){
	int i, len;
	len=n.len;
	srand(time(NULL));
	do{
		for (i=0; i<len;i++){
			M->lm[i]=(unsigned char)rand();
//			printf("%x",M->lm[i]);
		}
		M->len=len;
//		printf("%d \n",len);
	}while (More_Eq(M, &n));
	return ;
}