www.pudn.com > calc.rar > elliptic.c


/* elliptic.c */ 
 
#include  
#include  
#include "integer.h" 
#include "fun.h" 
#include "primepow.h" 
 
extern unsigned int ECMAX; 
/*extern unsigned long PRIMEPOWERS[];*/ 
 
void ADD_ELLIPTIC_Q(MPR *X1, MPR *Y1, MPR *X2, MPR *Y2, MPR **Xptr, MPR **Yptr, MPR *A, MPR *B) 
/* (*Xptr, *Yptr) is the sum of the two points (X1,Y1) and (X2,Y2) on the  
 * rational elliptic curve y^2=x^3+A*X+B, where 4*A^3+27*b^2 != 0. 
 */ 
{ 
	MPR *L, *Tmp1, *Tmp2, *Tmp3, *Tmp4, *Tmp5, *Tmp6, *Tmp7; 
 
	Tmp1 = BUILDMPR(); 
	Tmp1->N = CHANGE(4); 
	Tmp1->D = ONEI(); 
	Tmp2 = BUILDMPR(); 
	Tmp2->N = CHANGE(27); 
	Tmp2->D = ONEI(); 
	Tmp3 = POWERR(A, 3); 
	Tmp4 = POWERR(B, 2); 
	Tmp5 = MULTR(Tmp1, Tmp3); 
	Tmp6 = MULTR(Tmp2, Tmp4); 
	Tmp7 = ADDR(Tmp5, Tmp6); 
	if (EQZEROR(Tmp7)) 
	{ 
		fprintf(stderr, "discriminant is zero"); 
		exit (1); 
	} 
	FREEMPR(Tmp1); 
	FREEMPR(Tmp2); 
	FREEMPR(Tmp3); 
	FREEMPR(Tmp4); 
	FREEMPR(Tmp5); 
	FREEMPR(Tmp6); 
	FREEMPR(Tmp7); 
 
	Tmp1 = SUBR(X1, X2); 
	Tmp2 = ADDR(Y1, Y2); 
	if (EQZEROR(Tmp1) * EQZEROR(Tmp2)) 
	{ 
		fprintf(stderr, "sum is the identity\n"); 
		exit (1); 
		 
	} 
	FREEMPR(Tmp2); 
	if (!EQZEROR(Tmp1)) 
	{ 
		Tmp2 = SUBR(Y1, Y2); 
		L = RATIOR(Tmp2, Tmp1); 
		FREEMPR(Tmp2); 
	} 
	else 
	{ 
		Tmp2 = MULTR(X1, X1);	 
		Tmp3 = BUILDMPR(); 
		Tmp3->N = CHANGE(3); 
		Tmp3->D = ONEI(); 
		Tmp4 = MULTR(Tmp3, Tmp2); 
		Tmp5 = ADDR(Tmp4, A); 
		Tmp6 = ADDR(Y1, Y1);	 
		L = RATIOR(Tmp5, Tmp6); 
		FREEMPR(Tmp2); 
		FREEMPR(Tmp3); 
		FREEMPR(Tmp4); 
		FREEMPR(Tmp5); 
		FREEMPR(Tmp6); 
	} 
	FREEMPR(Tmp1); 
	Tmp1 = ADDR(X1, X2); 
	Tmp2 = MINUSR(Tmp1); 
	Tmp3 = MULTR(L, L); 
	*Xptr = ADDR(Tmp3, Tmp2); 
	FREEMPR(Tmp1); 
	FREEMPR(Tmp2); 
	FREEMPR(Tmp3); 
	Tmp1 = SUBR(*Xptr, X1); 
	Tmp2 = MULTR(L, Tmp1); 
	Tmp3 = ADDR(Tmp2, Y1); 
	*Yptr = MINUSR(Tmp3); 
	FREEMPR(L); 
	FREEMPR(Tmp1); 
	FREEMPR(Tmp2); 
	FREEMPR(Tmp3); 
	return; 
} 
 
/*MPI *XSUB2I(); 
MPI *ZSUB2I(); 
MPI *XSUB2IPLUS1(); 
MPI *ZSUB2IPLUS1(); */ 
 
void EXZPOWER(MPI *X, MPI *Z, USI k, MPI *P, MPI *Q, MPI **Aptr, MPI **Cptr, MPI *N) 
{ 
	unsigned int i = 0, w, C[50], l; 
	MPI *B, *D, *U, *V, *T, *Tmp; 
 
	U = V = NULL; 
	w = k; 
	while (w) 
	{ 
		i++; 
		C[i] = w % 2; 
		w = w / 2; 
	} 
	l = i; 
	*Aptr = COPYI(X); 
	*Cptr = COPYI(Z); 
	B = XSUB2I(X, Z, P, Q, N); 
	D = ZSUB2I(X, Z, P, Q, N); 
	for (i = l - 1; i >= 1; i--) 
	{ 
		U = XSUB2IPLUS1(X, Z, *Aptr, *Cptr, B, D, P, Q, N); 
		V = ZSUB2IPLUS1(X, *Aptr, *Cptr, B, D, N); 
		if (C[i] == 0) 
		{ 
			T = XSUB2I(*Aptr, *Cptr, P, Q, N); 
			Tmp = *Cptr; 
			*Cptr = ZSUB2I(*Aptr, *Cptr, P, Q, N); 
			FREEMPI(Tmp); 
			Tmp = *Aptr; 
			*Aptr = T; 
			FREEMPI(Tmp); 
			Tmp = B; 
			B = U; 
			FREEMPI(Tmp); 
			Tmp = D; 
			D = V; 
			FREEMPI(Tmp); 
		} 
		else 
		{ 
			T = XSUB2I(B, D, P, Q, N); 
			Tmp = D; 
			D = ZSUB2I(B, D, P, Q, N); 
			FREEMPI(Tmp); 
			Tmp = B; 
			B = T; 
			FREEMPI(Tmp); 
			Tmp = *Aptr; 
			*Aptr = U; 
			FREEMPI(Tmp); 
			Tmp = *Cptr; 
			*Cptr = V; 
			FREEMPI(Tmp); 
		} 
	}	 
	if (C[1] == 0) 
	{ 
		FREEMPI(U); 
		FREEMPI(V); 
	} 
	else 
	{ 
		FREEMPI(B); 
		FREEMPI(D); 
	} 
	return; 
} 
 
MPI *XSUB2I(MPI *R, MPI *S, MPI *P, MPI *Q, MPI *N) 
{ 
	MPI *T, *G, *H, *I, *Tmp0, *Tmp, *Tmp1, *Tmp2, *Tmp3, *Tmp4, *EIGHT; 
 
	G = MULTI(R, R); 
	H = MULTI(S, S); 
	I = MULTI(Q, S); 
	Tmp = I; 
	I = MULTI(I, H);/* I = Q * S * S * S  */ 
	FREEMPI(Tmp); 
	Tmp = H; 
	H = MULTI(H, P); /* H = P * S * S  */ 
	FREEMPI(Tmp); 
	Tmp1 = ADDI(G, H); /* Tmp1 = R * R + P * S * S */ 
	Tmp2 = MULTI(R, Tmp1); 
	FREEMPI(Tmp1); 
	Tmp = ADDI(Tmp2, I); 
	Tmp0 = Tmp; 
	Tmp = MOD(Tmp, N); 
	FREEMPI(Tmp0); 
	FREEMPI(Tmp2); 
	if (Tmp->S == 0) 
	{ 
		FREEMPI(I); 
		FREEMPI(G); 
		FREEMPI(H); 
		return (Tmp); 
	} 
	FREEMPI(Tmp); 
	Tmp = SUBI(G, H); 
	T = MOD(Tmp, N); 
	FREEMPI(Tmp); 
	Tmp1 = MULTI(T, T); 
	EIGHT = CHANGE(8); 
	Tmp2 = MULTI(R, I); 
	FREEMPI(I); 
	Tmp3 = MULTI(EIGHT, Tmp2); 
	Tmp =  SUBI(Tmp1, Tmp3); 
	Tmp4 = MOD(Tmp, N); 
	FREEMPI(T); 
	FREEMPI(Tmp); 
	FREEMPI(Tmp1); 
	FREEMPI(Tmp2); 
	FREEMPI(Tmp3); 
	FREEMPI(EIGHT); 
	FREEMPI(G); 
	FREEMPI(H); 
	return(Tmp4); 
} 
 
MPI *ZSUB2I(MPI *R, MPI *S, MPI *P, MPI *Q, MPI *N) 
{ 
	MPI *Tmp, *Tmp1, *Tmp2, *Tmp3, *Tmp4, *Tmp5, *Tmp6, *Tmp7, *Tmp8, *FOUR; 
 
	Tmp1 = POWERI(R, 3); 
	Tmp2 = MULTI(S, S); 
	Tmp3 = POWERI(S, 3); 
	Tmp4 = MULTI(P, R); 
	Tmp5 = MULTI(Tmp2, Tmp4); 
	Tmp6 = ADDI(Tmp1, Tmp5); 
	Tmp7 = MULTI(Q, Tmp3); 
	Tmp = ADDI(Tmp6, Tmp7); 
	Tmp8 = MOD(Tmp, N); 
	FREEMPI(Tmp); 
	FREEMPI(Tmp1); 
	FREEMPI(Tmp2); 
	FREEMPI(Tmp3); 
	FREEMPI(Tmp4); 
	FREEMPI(Tmp5); 
	FREEMPI(Tmp6); 
	FREEMPI(Tmp7); 
	if (Tmp8->S == 0) 
		return (Tmp8); 
	else 
	{ 
		FOUR = CHANGE(4); 
		Tmp1 = MULTI(S, Tmp8); 
		FREEMPI(Tmp8); 
		Tmp = MULTI(FOUR, Tmp1); 
		Tmp2 = MOD(Tmp, N); 
		FREEMPI(Tmp); 
		FREEMPI(Tmp1); 
		FREEMPI(FOUR); 
		return (Tmp2); 
		 
	} 
} 
 
MPI *XSUB2IPLUS1(MPI *X, MPI *Z, MPI *R, MPI *S, MPI *U, MPI *V, MPI *P, MPI *Q, MPI *N) 
{ 
	MPI *F, *G, *Tmp1, *Tmp2, *Tmp3, *Tmp4, *Tmp5, *Tmp6, *Tmp7, *Tmp8; 
	MPI *FOUR, *Tmp, *Tmp0; 
	 
	Tmp1 = MULTI(R, U); /* Tmp1 = R * U */ 
	Tmp3 = MULTI(V, S); /* Tmp3 = S * V */ 
	Tmp4 = MULTI(R, V); 
	Tmp5 = MULTI(P, Tmp3); /* Tmp5 = P * S * V */ 
	Tmp = SUBI(Tmp1, Tmp5);  
	F = MOD(Tmp, N);/* F = MOD(R * U - P * S * V, N) */ 
	FREEMPI(Tmp); 
	Tmp6 = MULTI(U, S); 
	Tmp7 = ADDI(Tmp4, Tmp6); /* Tmp7 = R * V + S * U */ 
	FREEMPI(Tmp4); 
	FREEMPI(Tmp6); 
	Tmp8 = MULTI(Q, Tmp3); /* Tmp8 = Q * S * V */ 
	Tmp = MULTI(Tmp8, Tmp7); 
	G = MOD(Tmp, N); 
	FREEMPI(Tmp); 
	if (X->S != 0) 
	{ 
		FREEMPI(Tmp1); 
		FREEMPI(Tmp3); 
		FREEMPI(Tmp5); 
		FREEMPI(Tmp7); 
		FREEMPI(Tmp8); 
		Tmp1 = MULTI(F, F); 
		FOUR = CHANGE(4); 
		Tmp2 = MULTI(FOUR, G); 
		Tmp3 = SUBI(Tmp1, Tmp2); 
		Tmp = MULTI(Z, Tmp3);	 
		Tmp4 = MOD(Tmp, N); 
		FREEMPI(Tmp); 
		FREEMPI(Tmp1); 
		FREEMPI(Tmp2); 
		FREEMPI(Tmp3); 
		FREEMPI(F); 
		FREEMPI(G); 
		FREEMPI(FOUR); 
		return (Tmp4); 
	} 
	Tmp = F; 
	FOUR = CHANGE(4); 
	Tmp2 = MULTI(Tmp8, Tmp3); 
	F = MULTI(FOUR, Tmp2); 
	FREEMPI(Tmp); 
	FREEMPI(FOUR); 
	Tmp4 = ADDI(Tmp5, Tmp1); 
	Tmp6 = ADDI(Tmp4, Tmp4); 
	Tmp = G; 
	G = MULTI(Tmp6, Tmp7); 
	FREEMPI(Tmp); 
	Tmp = ADDI(F, G); 
	Tmp0 = MOD(Tmp, N); 
	FREEMPI(Tmp); 
	FREEMPI(F); 
	FREEMPI(G); 
	FREEMPI(Tmp1); 
	FREEMPI(Tmp2); 
	FREEMPI(Tmp3); 
	FREEMPI(Tmp4); 
	FREEMPI(Tmp5); 
	FREEMPI(Tmp6); 
	FREEMPI(Tmp7); 
	FREEMPI(Tmp8); 
	return (Tmp0); 
} 
 
MPI *ZSUB2IPLUS1(MPI *X, MPI *R, MPI *S, MPI *U, MPI *V, MPI *N) 
{ 
	MPI *Tmp, *T, *Tmp1, *Tmp2, *Tmp3, *Tmp4; 
 
	Tmp1 = MULTI(U, S);		 
	Tmp2 = MULTI(R, V);		 
	T = SUBI(Tmp1, Tmp2);		 
	Tmp3 = MULTI(T, T); 
	FREEMPI(T); 
	FREEMPI(Tmp1); 
	FREEMPI(Tmp2); 
	if (X->S != 0) 
	{ 
		Tmp = MULTI(X, Tmp3); 
		Tmp4 = MOD(Tmp, N); 
		FREEMPI(Tmp); 
		FREEMPI(Tmp3); 
		return (Tmp4); 
	} 
	else 
	{ 
		Tmp4 = MOD(Tmp3, N); 
		FREEMPI(Tmp3); 
		return (Tmp4); 
	} 
} 
 
MPI *EFACTOR(MPI *N, USI m, USI p) 
/* 
 * This is a modification of algorithm 14.5, page 216, Bressoud. 
 * This program uses the elliptic curve y^2=x^3-Ax+A, as in Niven, 
 * Zuckerman, Montgomery, page 285. 
 * It is assumed that m <= 2328 here. 
 * n is the composite number, m is the number of prime powers used in 
 * exponentiation on the elliptic curve, p is the starting seed for the 
 * random curve y^2=x^3-A*x+A mod n. 
 * J is the number of curves used. 
 */ 
{ 
	/* NOTE: m must be > 10, p > 0. */ 
	MPI *FOUR, *P, *G, *A, *C, *Tmp1, *Tmp2, *Tmp3; 
	MPI *ONE, *TWENTY_SEVEN, *Tmp, *AA, *CC; 
	unsigned int i, j, k, w, ecmax; 
	 
	w = m - 10; 
	P = Tmp = NULL; 
 
	ONE = ONEI(); 
	FOUR = CHANGE(4); 
	TWENTY_SEVEN = CHANGE(27); 
	if (ECMAX == 0) { 
	  printf("ECMAX = 0\n"); 
	  FREEMPI(ONE); 
	  FREEMPI(FOUR); 
	  FREEMPI(TWENTY_SEVEN); 
	  return NULL; 
	} 
	ecmax = ECMAX - 1; 
	j = 0; 
	while (p) 
	{ 
		if (j > ecmax) 
			break; 
		if (p % 1 == 0) 
		{ 
			fflush(stdout); 
			printf("elliptic curve number %u, A =  %u\n", j + 1, p); 
		} 
		P = CHANGE(p); 
		Tmp = MINUSI(P); 
		Tmp1 = POWERI(P, 3); 
		Tmp2 = MULTI(Tmp1, FOUR); 
		Tmp3 = SUBI(Tmp2, TWENTY_SEVEN); 
		G = GCD(Tmp3, N); 
		FREEMPI(Tmp1); 
		FREEMPI(Tmp2); 
		FREEMPI(Tmp3); 
		if (!EQUALI(G, ONE)) 
		{ 
			printf("discriminant not relatively prime to "); 
			PRINTI(N); 
			if (!EQUALI(G, N)) 
			{ 
				printf("\n found a factor "); 
				PRINTI(G); 
				printf(" of "); 
				PRINTI(N); 
				printf("\n"); 
				FREEMPI(P); 
				FREEMPI(Tmp); 
				FREEMPI(FOUR); 
				FREEMPI(ONE); 
				FREEMPI(TWENTY_SEVEN); 
				return (G); 
			} 
			FREEMPI(G); 
		} 
		else 
		{ 
			FREEMPI(G); 
			A = ONEI(); 
			C = ONEI(); 
			k = 0; 
			while (k <= m) 
			{ 
				printf("k = %u\n", k); 
				if (k <= w) 
				{ 
					for (i = 1; i <= 10; i++) 
					{ 
					EXZPOWER(A, C, PRIMEPOWERS[k], Tmp, P, &AA, &CC, N); 
					FREEMPI(A); 
					FREEMPI(C); 
					A = AA; 
					C = CC; 
					k++; 
					} 
				} 
				else 
				{ 
					EXZPOWER(A, C, PRIMEPOWERS[k], Tmp, P, &AA, &CC, N); 
					FREEMPI(A); 
					FREEMPI(C); 
					A = AA; 
					C = CC; 
					k++; 
				} 
				G = GCD(C, N); 
				if (!EQUALI(G, ONE) && !EQUALI(G, N)) 
				{ 
					printf("Using elliptic curve number %u\n", j + 1); 
					printf(" has found a factor "); 
					PRINTI(G); 
					printf(" of "); 
					PRINTI(N); 
					printf("\n"); 
					FREEMPI(P); 
					FREEMPI(Tmp); 
					FREEMPI(FOUR); 
					FREEMPI(ONE); 
					FREEMPI(TWENTY_SEVEN); 
					FREEMPI(AA); 
					FREEMPI(CC); 
					return (G); 
				} 
				FREEMPI(G); 
			} 
			FREEMPI(A); 
			FREEMPI(C); 
		} 
		FREEMPI(P); 
		FREEMPI(Tmp); 
		p = RANDOMm(p); 
		j++; 
	} 
	FREEMPI(FOUR); 
	FREEMPI(ONE); 
	FREEMPI(TWENTY_SEVEN); 
	return(NULL); 
} 
 
unsigned int ORDERECP(MPI *X, MPI *Z, MPI *P, MPI *Q, MPI *N) 
/* 
 * Calculates the order of the point (X,Y,Z) on the elliptic curve 
 * Y^2*Z=X^3+P*X*Z^2+Q*Z^3 (mod N), N a prime. 
 */ 
{ 
	unsigned int k = 1; 
	MPI *A, *C; 
	 
	while (1) 
	{ 
		EXZPOWER(X, Z, k, P, Q, &A, &C, N); 
		FREEMPI(A); 
		if (EQZEROI(C)) 
			break; 
		if (k % 100 == 0) 
			printf("k = %u\n", k); 
		k++; 
		FREEMPI(C); 
	} 
	FREEMPI(C); 
	return (k--); 
}