/******************************************************** * * * The purpose of this program is to search out possible * * eigen values to the frobenius equation when operating over a * * field extension. Taken from Menezes' "Elliptic Curve Public Key * * Cryptosystems" chapter 7, section 3. * * * * Author = Mike Rosing * * date = Aug. 12 1999 * * * ********************************************************/ #include #include #include "field2n.h" #include "eliptic.h" #include "multipoly.h" extern RAMDATA ram_block[]; #define PRIMEdepth 37 #define TESTN 10 INDEX PRIMES[32] = {3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97}; /* check to see if two FIELD2N values are equal. Returns 1 if they are, 0 if they aren't. */ INDEX isequal( FIELD2N *a, FIELD2N *b) { INDEX i; ELEMENT r; i = 0; r = 0; while ( ( !r) && ( ie[i] ^ b->e[i]; i++; } if (r) return (0); return(1); } void print_FIELD( text, value) char *text; FIELD2N *value; { INDEX i; printf("%s", text); SUMLOOP(i) printf ("%8x ",value->e[i]); printf("\n"); } /* Routine to multiply any MULTIPOLY by a power of x. This amounts to a shift in position by the power. Enter with z and n, returns with x^n * z. */ int multi_xmul( MULTIPOLY z, int n, MULTIPOLY *xnz) { FIELD2N *src, *dst; int i; xnz->degree = z.degree + n; if( !get_space( xnz)) return 0; src = Address( z); dst = AddressOf( xnz); for( i=0; idegree = dup.degree; fixit->memdex = dup.memdex; return 1; } /* core routine to square (a(x) + b(x) y). Used to determine sign of an eigenvalue. Enter with pointers to results a'(x), b'(x) and routine computes a'(x) = a^2 + b^2( x^3 + a6) b'(x) = x b^2 Done modulo the curve over y, modulo g1 over x */ int squarey( MULTIPOLY a, MULTIPOLY b, MULTIPOLY *newa, MULTIPOLY *newb, CURVE crv, MULTIPOLY modulus, MULTIPOLY *x2j_mod_g) { MULTIPOLY a2, b2, curve, temp; FIELD2N *xb, *bptr; /* a^2 and b^2 first */ if( !square_modf( a, modulus, x2j_mod_g, &a2)) return 0; if( !square_modf( b, modulus, x2j_mod_g, &b2)) { free_space(&a2); return 0; } /* create curve polynomial */ curve.degree = 3; if( !get_space( &curve)) { free_space(&a2); free_space(&b2); return 0; } xb = Address( curve); copy( &crv.a6, xb); null( &xb[1]); null( &xb[2]); one( &xb[3]); if( !multi_mul( curve, b2, &temp)) { free_space( &a2); free_space( &b2); free_space( &curve); return 0; } if( !multi_add( a2, temp, &temp)) { free_space( &a2); free_space( &b2); free_space( &curve); free_space( &temp); return 0; } if( multi_div( temp, modulus, &temp, newa) <= 0) { free_space( &a2); free_space( &b2); free_space( &curve); free_space( &temp); return 0; } free_space( &temp); free_space( &curve); /* do y coefficient */ if( !multi_xmul( b2, 1, newb)) { free_space( &a2); free_space( &b2); return 0; } free_space( &a2); free_space( &b2); if( newb->degree >= modulus.degree) if( multi_div( *newb, modulus, &temp, newb) <= 0) return 0; return 1; } /* subroutine to compute y^2^NUMBITS. requires curve data, modulus, and pointer to modular squaring table as well as place to store results. since y^2 = (x^3 + a6) + xy, result is of the form a(x) + b(x) * y. Returns 1 on sucess, 0 on space failure. */ int yqmodg( MULTIPOLY modulus, MULTIPOLY *x2j_mod_g, CURVE crv, MULTIPOLY *yqx, MULTIPOLY *yqy) { MULTIPOLY xcoef, ycoef, newx, newy; FIELD2N *ptr; INDEX i; /* create initial value of y = 0 + 1 * y */ xcoef.degree = 0; if( !get_space( &xcoef) ) return 0; ptr = Address( xcoef); null( ptr); ycoef.degree = 0; if( !get_space( &ycoef)) { free_space( &xcoef); return 0; } ptr = Address( ycoef); one( ptr); // for( i=0; ie[NUMWORD] ^= 1L; /* combine all y terms separately from x terms for equation 7.5 in Menezes. yterms = xf[w]^3( y^q + y)_y + f[w-1]f[w]f[w+1] xterms = xf[w]^3*y^q_x + x^2 f[w-1]f[w]f[w+1] + f[w-2]f[w+1]^2 */ /* first y term = t2, xf3 = x*f[w]^3 */ if( !multi_mul( f[w], f[w], &xf3)) exit(-2); if( !multi_mul( f[w], xf3, &xf3)) exit(-2); if( !multi_mul( xone, xf3, &xf3)) exit(-2); if( multi_div( xf3, gcd_term, &t2, &t3) <= 0) exit(-2); free_space( &t2); if( !multi_mul( yqy, t3, &t2)) exit(-2); free_space(&t3); if( multi_div( t2, gcd_term, &t1, &t2) <= 0) exit(-2); free_space( &t1); /* second y term = t3, fff = f[w-1]f[w]f[w+1] */ if( !multi_mul( f[w], f[w-1], &fff)) exit(-3); if( !multi_mul( f[w+1], fff, &fff)) exit(-3); if( multi_div( fff, gcd_term, &t4, &t3) <= 0) exit(-3); free_space( &t4); if( !multi_add( t2, t3, &bbar)) exit(-3); /* compute middle term ff2 = f[w-2]f[w+1]^2 */ if( !multi_mul( f[w-2], f[w+1], &ff2)) exit(-4); if( !multi_mul( f[w+1], ff2, &ff2)) exit(-4); if( multi_div( ff2, gcd_term, &p2, &ff2) <= 0) exit(-4); free_space( &p2); /* compute a_bar in Menezes */ if( !multi_mul( xf3, yqx, &p2)) exit(-5); /* do x^2 * fff */ if( !multi_xmul( fff, 2, &p3)) exit(-5); if( !multi_add( p3, p2, &p2)) exit(-5); free_space( &p3); if( !multi_add( ff2, p2, &abar)) exit(-5); free_space( &p2); if( multi_div( abar, gcd_term, &p2, &abar) <= 0) exit(-5); free_space( &p2); free_space( &t1); free_space( &t2); free_space( &t3); free_space( &p1); free_space( &p2); x3a6.degree = 3; /* create x^3 + a6 */ if( !get_space( &x3a6)) exit(-6); xptr = Address( x3a6); copy( &crv.a6, xptr); null( &xptr[1]); null( &xptr[2]); one( &xptr[3]); /* compute y^q by brute force. Take modulo g1 after all terms found to see if modulo calculations done correctly. */ yqa[0].degree = 0; if( !get_space( &yqa[0])) exit(-10); xptr = Address( yqa[0]); null( xptr); yqb[0].degree = 0; if( !get_space( &yqb[0])) exit(-10); xptr = Address( yqb[0]); one( xptr); for( i=0; i 1) break; } /* end of w loop */ if( wdex ) { if (wdex == 2) printf("Eigenvalues are %d and %d at k = %d\n", wlist[0], wlist[1], k); else printf("Duplicate eigenvalue %d at k = %d\n", wlist[0], k); escape = 1; } prime_search++; if( !escape) printf("No eigenvalues for k = %d\n",k); free_space( &xqx); destroy_xmodf( f[k], x2j_modf_table); free_space( &fw_term); free_space( &gcd_term); }/* end of k loop */ exit(0); }/* end of program */