📄 elliptic.c
字号:
/* elliptic.c */
#include <stdio.h>
#include <stdlib.h>
#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--);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -