⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ring.c

📁 多项式的计算
💻 C
字号:
/*************************************************************************************																					**    The following routines implement GF(2^n) math via the Ring R_p using J. Siverman's descriptions		**  in the paper "Fast Multiplication in Finite Fields GF(2^n).  The idea here is that the ring taken modulo	**  X^p-1 where p is a prime such that p-1 gives a Type I ONB allows us to compute much faster than in		**  the field GF(2^n) (n = p-1) directly.  This magic happens because X^p-1 factors into (X-1)*phi(X) and		**  phi(X) is the irreducible prime governing the ONB field.										**																					**									Author = mike rosing							**									 date  = July 7, 1999							*************************************************************************************/#include "stdio.h"#include "field2n.h"#define  GHOST_BIT		(1L << UPRSHIFT)#define  GHOST_SHIFT	(field_prime % WORDSIZE)#define  GHOST_MASK	~(~0 << GHOST_SHIFT)#define  field_prime   192/*  globals initialized once and used for multiply and	inversion routines as well as quadratic solver.*/static	INDEX	two_inx[field_prime];static	ELEMENT	two_bit[field_prime];static	INDEX	sqr_inx[field_prime];static	ELEMENT	sqr_bit[field_prime];static unsigned char shift_by[256];void print_field( string, field)char *string;FIELD2N *field;{	INDEX i;		printf("%s : ", string);	SUMLOOP(i) printf("%8x ", field->e[i]);	printf("\n");}void ring_right(FIELD2N *a){        INDEX i;        ELEMENT bit,temp;        bit = (a->e[NUMWORD] & 1) ? GHOST_BIT : 0L;        SUMLOOP(i) {           temp = ( a->e[i] >> 1)  | bit;           bit = (a->e[i] & 1) ? MSB : 0L;           a->e[i] = temp;        }        a->e[0] &= GHOST_MASK;}void null(a)FIELD2N *a;{        INDEX i;        SUMLOOP(i)  a->e[i] = 0;}void copy (a,b)FIELD2N *a,*b;{        INDEX i;        SUMLOOP(i)  b->e[i] = a->e[i];}/*  binary search for most significant bit within word *//*INDEX log_2( x)ELEMENT x;{	INDEX	k, lg2;	ELEMENT ebit, bitsave, bitmask;	lg2 = 0;	bitsave = x;				/* grab bits we're interested in.  *//*	k = WORDSIZE/2;					/* first see if msb is in top half  *//*	bitmask = -1L<<k;				/* of all bits  *//*	while (k)	{		ebit = bitsave & bitmask;	/* did we hit a bit?  *//*		if (ebit)					/* yes  *//*		{			lg2 += k;				/* increment degree by minimum possible offset  *//*			bitsave = ebit;			/* and zero out non useful bits  *//*		}		k /= 2;		bitmask ^= (bitmask >> k);	}	return( lg2);}*//*  Initialize globals for ring math system.  These terms used in several places.  */static void init_ring_math(void){	INDEX n, i, j;	j = 1;	for ( i=0;  i<field_prime;  i++ ) 	{	    two_inx[i] = LONGWORD-(j / WORDSIZE);	    two_bit[i] = 1L << (j % WORDSIZE);            j = (j << 1) % field_prime;	}	for ( i=1; i<256; i++ )	    shift_by[i] = 0;	shift_by[0] = 1;	for ( j=2; j<256; j+=j )        for ( i=0; i<256; i+=j )	    shift_by[i]++;	n = 	NUMBITS/2 + 1;	for( i=0; i<n; i++)	{		sqr_inx[i] = LONGWORD - ((2*i)/WORDSIZE);		sqr_bit[i] = 1L << ((2*i) % WORDSIZE);		sqr_inx[i+n] = LONGWORD - ((2*i+1)/WORDSIZE);		sqr_bit[i+n] = 1L << ((2*i+1) % WORDSIZE);	}}/*  Ring multiply for Type I ONB	Taken from J.H. Silverman "Fast Multiplication in Finite Fields GF(2^n)",	CHES workshop '99 (to appear in LNCS, Springer).  This method only works	for Type I ONB at present but has complexity n+1, so is twice as fast as	any other method.*/void ring_mul( FIELD2N *a,  FIELD2N *b, FIELD2N *c){	INDEX	i, j, k;	ELEMENT	mask;		null( c);	mask = 1L;	j = NUMWORD;	for( i=0; i<field_prime; i++)    /*  i counts over bits, j is the ELEMENT index */	{		if( mask & a->e[j]) 			SUMLOOP(k) c->e[k] ^= b->e[k];		ring_right( c);		mask <<= 1;		if( !mask)		{			mask = 1L;			j--;		}	}/*  if msb is set, flip back to GF(2^n).  Otherwise we're already there */	if( c->e[0] & GHOST_BIT)	{		SUMLOOP(k) c->e[k] ^= ~0;		c->e[0] &= UPRMASK;	}}/*  Square a number in ring R_p.  Since this is modulo the cyclotomic	polynomial, the bottom half bits spread out and the upper half bits	interleave between them.  The initialization routine builds this 	table as an index and bit mask which we can use to permute the 	input bits.*/void ring_square( FIELD2N *a, FIELD2N *c){	INDEX	i, j;	ELEMENT	 mask;		null( c);	j = NUMWORD;	mask = 1;	for( i=0; i<field_prime; i++)	{		if( a->e[j] & mask)			c->e[sqr_inx[i]] |= sqr_bit[i];		mask <<= 1;		if( !mask)		{			mask = 1;			j--;		}	}	if( c->e[0] & GHOST_BIT)	{		SUMLOOP(i)  c->e[i] ^= ~0;		c->e[0] &= UPRMASK;	}}/*  compute square root of number in R_p  */void ring_sqroot( FIELD2N *a, FIELD2N *c){	INDEX	i, j;	ELEMENT	mask;		null( c);	j = NUMWORD;	mask = 1;	for( i=0; i<field_prime; i++)	{		if( a->e[sqr_inx[i]] & sqr_bit[i])			c->e[j] |= mask;		mask <<= 1;		if( !mask)		{			mask = 1;			j--;		}	}	if( c->e[0] & GHOST_BIT)	{		SUMLOOP(i)  c->e[i] ^= ~0;		c->e[0] &= UPRMASK;	}}/*  Routine to divide input a by x^k.	Enter with pointer to a, value of k and pointer to	result b.	Returns with b = a/x^k in R_p.  This is a k fold	shift of all field_prime bits to the right.*/void ring_divk( FIELD2N *a, INDEX k, FIELD2N *b){	INDEX	bottom1, bottom2, top1, top2, i, j, start;	ELEMENT	mask1, mask2;		null( b);	k = k % field_prime;	if ( !k )	{		copy( a, b);		return;	}	start = NUMWORD  - k/WORDSIZE;	bottom2 = k % 	WORDSIZE;	if( !bottom2) start++;	bottom1 =  WORDSIZE - bottom2;	mask1 = ~(~0 << bottom1);/*  copy top to bottom  */	j = start;	i = LONGWORD;	while ( i>=0)	{		b->e[i] = ( a->e[j] >> bottom2) & mask1;		j--;		if( j<0 ) break;		b->e[i] |= a->e[j] << bottom1;		i--;	}/*  mask off unused portion that got transfered  */	top2 = ( field_prime - k ) % WORDSIZE;	top1 = WORDSIZE - top2;	mask1 = ~(~0 << top2);	b->e[i] &= mask1;	j = LONGWORD;	i = LONGWORD - (field_prime - k) / WORDSIZE;	mask2 = ~( ~0 << top1);	while ( j>=0 )	{		b->e[i] |= a->e[j] << top2;		i--;		if (i<0) break;		if(i) b->e[i] |= ( a->e[j] >> top1) & mask1;		else b->e[0] |= a->e[j] >> top1;		j--;	 }	b->e[0] &= GHOST_MASK;}/* This algorithm is the Almost Inverse Algorithm of Schroeppel, et al. given   in "Fast Key Exchange with Elliptic Curve Systems   Code originally written by Dave Dahm.    Modified to work with R_p by removing conversion to polynomial basis.   Conversion to R_p only requires one extra bit*/void ring_inv(FIELD2N *a, FIELD2N *dest){	FIELD2N		f, b, c, g;	INDEX		i, j, k, m, n, f_top, c_top;    	ELEMENT		bits, t, mask;	/* f, b, c, and g are not in optimal normal basis format: they are held	    in 'customary format', i.e. a0 + a1*u^1 + a2*u^2 + ...; For the	    comments in this routine, the polynomials are assumed to be	    polynomials in u. */	/* Set g to polynomial (u^p-1)/(u-1) */	for ( i=1; i<=LONGWORD; i++ )	    g.e[i] = ~0;        g.e[0] = GHOST_MASK;	/* Set c to 0, b to 1, and n to 0, f to a*/	null(&c);	null(&b);	b.e[LONGWORD] = 1;	n = 0;	copy( a, &f);	/* Now find a polynomial b, such that a*b = u^n */	/* f and g shrink, b and c grow.  The code takes advantage of this.	c_top and f_top are the variables which control this behavior */	c_top = LONGWORD;	f_top = 0;	do {	    i = shift_by[f.e[LONGWORD] & 0xff];	    if(!i) break;	    n+=i;    /* Shift f right i (divide by u^i) */	    m = 0;	    for ( j=f_top; j<=LONGWORD; j++ ) {		bits = f.e[j];		f.e[j] = (bits>>i) | ((ELEMENT)m << (WORDSIZE-i));		m = bits;	    }	} while ( i == 8 && (f.e[LONGWORD] & 1) == 0 );	for ( j=0; j<LONGWORD; j++ )	    if ( f.e[j] ) break;	if ( j<LONGWORD || f.e[LONGWORD] != 1 )	{	/* There are two loops here: whenever we need to exchange f with g and		b with c, jump to the other loop which has the names reversed! */			    do 	    {	    /* Shorten f and g when possible */	    		while ( f.e[f_top] == 0 && g.e[f_top] == 0 ) f_top++;			    /* f needs to be bigger - if not, exchange f with g and b with c.	       (Actually jump to the other loop instead of doing the exchange)	       The published algorithm requires deg f >= deg g, but we don't	       need to be so fine */	       		if ( f.e[f_top] < g.e[f_top] ) goto loop2;loop1:	    /* f = f+g, making f divisible by u */	    		for ( i=f_top; i<=LONGWORD; i++ )		    f.e[i] ^= g.e[i];    	    /* b = b+c */	    		for ( i=c_top; i<=LONGWORD; i++ )		    b.e[i] ^= c.e[i];		do 		{		    i = shift_by[f.e[LONGWORD] & 0xff];		    if( !i) break;		    n+=i;		    	    /* Shift c left i (multiply by u^i), lengthening it if needed */	    		    m = 0;		    for ( j=LONGWORD; j>=c_top; j-- ) 		    {			bits = c.e[j];			c.e[j] = (bits<<i) | m;			m = bits >> (WORDSIZE-i);		    }		    if ( m ) 		    {		    	c.e[j] = m;		    	c_top=j;		    }	    /* Shift f right i (divide by u^i) */	    		    m = 0;		    for ( j=f_top; j<=LONGWORD; j++ ) 		    {			bits = f.e[j];			f.e[j] = (bits>>i) | ((ELEMENT)m << (WORDSIZE-i));			m = bits;		    }		} while ( i == 8 && (f.e[LONGWORD] & 1) == 0 );			    /* Check if we are done (f=1) */	    		for ( j=f_top; j<LONGWORD; j++ )		    if ( f.e[j] ) break;	    } while ( j<LONGWORD || f.e[LONGWORD] != 1 );	    	    if ( j>0 )   goto done;	    	    do 	    {	    /* Shorten f and g when possible */	    		while ( g.e[f_top] == 0 && f.e[f_top] == 0 ) f_top++;			    /* g needs to be bigger - if not, exchange f with g and b with c.	       (Actually jump to the other loop instead of doing the exchange)	       The published algorithm requires deg g >= deg f, but we don't	       need to be so fine */	       		if ( g.e[f_top] < f.e[f_top] ) goto loop1;loop2:	    /* g = f+g, making g divisible by u */	    		for ( i=f_top; i<=LONGWORD; i++ )		    g.e[i] ^= f.e[i];	    /* c = b+c */	    		for ( i=c_top; i<=LONGWORD; i++ )		    c.e[i] ^= b.e[i];		do 		{		    i = shift_by[g.e[LONGWORD] & 0xff];		    if( !i) break;		    n+=i;		    	    /* Shift b left i (multiply by u^i), lengthening it if needed */	    		    m = 0;		    for ( j=LONGWORD; j>=c_top; j-- ) 		    {			bits = b.e[j];			b.e[j] = (bits<<i) | m;			m = bits >> (WORDSIZE-i);		    }		    if ( m )		    {		    	b.e[j] = m;		    	c_top=j;		    }	    /* Shift g right i (divide by u^i) */	    		    m = 0;		    for ( j=f_top; j<=LONGWORD; j++ ) 		    {			bits = g.e[j];			g.e[j] = (bits>>i) | ((ELEMENT)m << (WORDSIZE-i));			m = bits;		    }		} while ( i == 8 && (g.e[LONGWORD] & 1) == 0 );			    /* Check if we are done (g=1) */	    		for ( j=f_top; j<LONGWORD; j++ )		    if ( g.e[j] ) break;		    	    } while ( j<LONGWORD || g.e[LONGWORD] != 1 );            copy(&c, &b);	}done:	/* Now b is a polynomial such that a*b = u^n, so multiply b by u^(-n) */	ring_divk(&b,  n, &c);        /* Convert b back to optimal normal basis form (into dest) from ring */	if (c.e[0] & GHOST_BIT)	{		SUMLOOP(i) c.e[i] ^= ~0;		c.e[0] &= UPRMASK;	}	copy( &c, dest);} /* ring_inv *//*  Solving quadratic formula in R_p	Expand on Silverman's description to compute a solution	to y^2 + ay + b = 0    via a change in variables to	az = y,  c = b/a^2 and then solve for z^2 + z + c = 0.		Enter with a, b an pointer to y[2] storage.	Returns 0 error and y filled with 2 results or	             1 error and y values = 0*/int ring_quadratic( FIELD2N *a, FIELD2N *b, FIELD2N *y){	INDEX	i, j, bits;	ELEMENT	r, mask;	FIELD2N	c, temp1, temp2, z;	/*  test for a = 0 and return y = b^(1/2)  (square root of b)  */	r = 0;	SUMLOOP(i) r |= a->e[i];	if  ( !r)	{		ring_sqroot( b, y);		copy( &y[0], &y[1]);		return (0);	}/*  compute c = b/a^2  */	ring_square( a, &temp1);	ring_inv( &temp1, &temp2);	ring_mul(b, &temp2, &c);/*  if c[0] = 0, check that Tr(c) = 0. 	Otherwise, compliement c, then check trace  */	if( c.e[NUMWORD] & 1)	{		SUMLOOP(i) c.e[i] ^= ~0;		c.e[0] &= GHOST_MASK;	}/*  next comput Tr(c)  */	r = 0;	SUMLOOP(i) r ^= c.e[i];	mask = ~0;	for( bits=WORDSIZE/2; bits>0; bits >>= 1)	{		mask >>= bits;		r = ( ( r & mask) ^ ( r >> bits));	}/*  if not zero, return error code  */	if ( r)	{		null( &y[0]);		null( &y[1]);		return(1);	}/*  Good chance we have a solution, so let's try.	Set z[0] = 0, z[1] = 1 an index j = 2*i mod field_prime	for i = 1 to NUMBITS.*/	null( &z);	z.e[NUMWORD] = 2;	j = NUMWORD;	for( bits=1; bits<NUMBITS; bits++)	{		i = j;		j = two_inx[bits];		r = ( c.e[j] & two_bit[bits]) ? 1 : 0;		mask = ( z.e[i] & two_bit[bits - 1]) ? 1 : 0;		if( r ^ mask) z.e[j] |= two_bit[bits];	}/*  check that final bit is consistent with full solution.      If not, then this ring element has no solution.*/	j = NUMWORD - ((NUMBITS/2 + 1) / WORDSIZE);	r = 1L << ( (NUMBITS/2 + 1) % WORDSIZE);	mask = (z.e[NUMWORD] ^ c.e[NUMWORD]) & 2L;	if( ((z.e[j] & r) && !mask) || ( !(z.e[j] & r) && mask))	{		null( &y[0]);		null( &y[1]);		return (1);	}/*  convert back to GF(2^n)  */	if( z.e[0] & GHOST_BIT)	{		SUMLOOP(i) z.e[i] ^= ~0;		z.e[0] &= UPRMASK;	}/*  return correct y = az values  */	ring_mul( &z, a,  &y[0]);	null( &y[1]);	SUMLOOP(i) y[1].e[i] = y[0].e[i] ^ a->e[i];	return (0);}/*  test basic low level math routines  */main(){	FIELD2N	t1, t2, t3;	FIELD2N    a, b, y[2];	INDEX i;	int error;	char message[32];	init_ring_math();	null(&t1);/*	t1.e[0] = UPRBIT<<1;	t1.e[1] = 0x8000;	t1.e[NUMWORD] = 1;	for(i=0; i<field_prime; i++)	{	  ring_divk(&t1, i, &t2);	  sprintf(message, "bit %d", i);	  print_field( message, &t2);	}*/	t1.e[0] = 0x1;	t1.e[NUMWORD] |= 0x13;	print_field("t1", &t1);	ring_inv(&t1, &t2);	print_field("t2 =", &t2);	ring_mul(&t1, &t2, &t3);	print_field("t1*t2 = ", &t3);	exit(0);	null(&t2);	t2.e[NUMWORD] = 0x25;	ring_mul( &t1, &t2, &t3);	ring_square( &t3, &t1);	ring_sqroot(&t1, &t2);	ring_inv(&t2, &t3);	ring_mul(&t3, &t2, &t1);	copy(&t3, &a);	copy(&t2, &b); 	null( &a);	a.e[NUMWORD] = 1;	null( &b);	b.e[NUMWORD] = 7;	error = ring_quadratic(&a, &b, y);	b.e[NUMWORD] = 6;	error = ring_quadratic(&a, &b, y);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -