void bii_binarymodpow_powerof2(bigint *dest, bigint base, bigint exp, uint32_t modpow){
	//if the modulus is a power of 2, division and modular arithmetic is very fast. 
	if(modpow==0){
		bigint_setval32(dest, 0);
		return;
	}
	bigint res, B, E, tmp1;
	bigint_init(&res);
	bigint_init(&B);
	bigint_init(&E);
	bigint_init(&tmp1);
	
	bigint_setval32(&res,1);
	bigint_getsigbits(&B,base, modpow);
	bigint_setval(&E, exp);
	
	while(!bigint_isval(E,0)){
		if(bigint_parity(E)==1){
			bigint_multiply(&tmp1, res, B);
			bigint_getsigbits(&res, tmp1, modpow);
		}
		bigint_rightshift(&E,1);
		bigint_multiply(&tmp1, B,B);
		bigint_getsigbits(&B,tmp1,modpow);
	}
	bigint_setval(dest, res);
	
	bigint_free(&res);
	bigint_free(&B);
	bigint_free(&E);
	bigint_free(&tmp1);
}
void bii_monproduct(bigint *dest, bigint abar, bigint bbar, bigint n, bigint nprime, uint32_t rpow){
	bigint t, m, u, tmp1, tmp2;
	bigint_init(&t);
	bigint_init(&m);
	bigint_init(&u);
	bigint_init(&tmp1);
	bigint_init(&tmp2);
	
	bigint_multiply(&t, abar, bbar);
	
	bigint_multiply(&tmp1, t, nprime);
	bigint_getsigbits(&m, tmp1, rpow);
	bigint_multiply(&tmp1, m,n);
	bigint_add(&u,t,tmp1);
	bigint_rightshift(&u,rpow);
	
	if(bigint_cmp(u,n)>=0) bigint_subtract(dest,u,n);
	else bigint_setval(dest, u);
	
	bigint_free(&t);
	bigint_free(&m);
	bigint_free(&u);
	bigint_free(&tmp1);
	bigint_free(&tmp2);
}
void bii_modexpodd(bigint *dest, bigint a, bigint e, bigint n){
	/*
	 * Modular exponentiation, returns a**e mod n
	 * Uses the Mongtomery Product algorithm to speed up a standard repeated-squaring routine
	 */
	 	 
	bigint r, nprime, tmp1, tmp2, abar, xbar;
	
	bigint_init(&r);
	bigint_init(&nprime);
	bigint_init(&tmp1);
	bigint_init(&tmp2);
	bigint_init(&abar);
	bigint_init(&xbar);

	//r is the least power of 2 which is larger than n. 
	bigint_setval32(&r,1);
	uint32_t rpow = bii_sigbits(n)-1;
	bigint_leftshift(&r, rpow);
	if(bigint_cmp(r,n)==-1){
		bigint_leftshift(&r,1);
		rpow++;
	}
	 
	//r * r^{-1} - n*n' = 1. Use the euclidean algorithm to find n'.
	bigint_setval32(&tmp1, 1);
	bigint_egcd(r,n, tmp1, &tmp2, &nprime);
	bigint_setpos(&nprime);
	 
	//abar = a * r mod n
	bigint_multiply(&tmp1,a,r);
	bigint_divide(&tmp2,&abar,tmp1,n);
	 
	bigint_divide(&tmp1,&xbar,r,n);
	 
	fflush(stdout);
	for(int i = bii_sigbits(e)-1; i>=0; i--){
		bii_monproduct(&tmp1, xbar, xbar, n, nprime, rpow);
		bigint_setval(&xbar, tmp1);
		bigint_setval(&tmp2,e);
		bigint_rightshift(&tmp2,i);
		if(bigint_parity(tmp2)==1){
			bii_monproduct(&tmp1,abar,xbar,n,nprime,rpow);
			bigint_setval(&xbar,tmp1);
		}
	}
	bigint_setval32(&tmp1, 1);
	bii_monproduct(dest, xbar, tmp1, n, nprime, rpow);
	 
	bigint_free(&r);
	bigint_free(&nprime);
	bigint_free(&tmp1);
	bigint_free(&tmp2);
	bigint_free(&abar);
	bigint_free(&xbar);
}
Example #4
0
/**
 * Perform modular multiplication of big integers
 *
 * @v multiplicand0	Element 0 of big integer to be multiplied
 * @v multiplier0	Element 0 of big integer to be multiplied
 * @v modulus0		Element 0 of big integer modulus
 * @v result0		Element 0 of big integer to hold result
 * @v size		Number of elements in base, modulus, and result
 * @v tmp		Temporary working space
 */
void bigint_mod_multiply_raw ( const bigint_element_t *multiplicand0,
			       const bigint_element_t *multiplier0,
			       const bigint_element_t *modulus0,
			       bigint_element_t *result0,
			       unsigned int size, void *tmp ) {
	const bigint_t ( size ) __attribute__ (( may_alias )) *multiplicand =
		( ( const void * ) multiplicand0 );
	const bigint_t ( size ) __attribute__ (( may_alias )) *multiplier =
		( ( const void * ) multiplier0 );
	const bigint_t ( size ) __attribute__ (( may_alias )) *modulus =
		( ( const void * ) modulus0 );
	bigint_t ( size ) __attribute__ (( may_alias )) *result =
		( ( void * ) result0 );
	struct {
		bigint_t ( size * 2 ) result;
		bigint_t ( size * 2 ) modulus;
	} *temp = tmp;
	int rotation;
	int i;

	/* Sanity check */
	assert ( sizeof ( *temp ) == bigint_mod_multiply_tmp_len ( modulus ) );

	/* Perform multiplication */
	bigint_multiply ( multiplicand, multiplier, &temp->result );

	/* Rescale modulus to match result */
	bigint_grow ( modulus, &temp->modulus );
	rotation = ( bigint_max_set_bit ( &temp->result ) -
		     bigint_max_set_bit ( &temp->modulus ) );
	for ( i = 0 ; i < rotation ; i++ )
		bigint_rol ( &temp->modulus );

	/* Subtract multiples of modulus */
	for ( i = 0 ; i <= rotation ; i++ ) {
		if ( bigint_is_geq ( &temp->result, &temp->modulus ) )
			bigint_subtract ( &temp->modulus, &temp->result );
		bigint_ror ( &temp->modulus );
	}

	/* Resize result */
	bigint_shrink ( &temp->result, result );

	/* Sanity check */
	assert ( bigint_is_geq ( modulus, result ) );
}
Example #5
0
void bigint_egcd(bigint a, bigint b, bigint c, bigint *x, bigint *y){

	bigint r0, r1, r2, s1, s2, t1, t2, q, r, tmp1, tmp2;
	int revflag = 0;
	
	bigint_init(&r0);
	bigint_init(&r1);
	bigint_init(&r2);
	bigint_init(&s1);
	bigint_init(&s2);
	bigint_init(&t1);
	bigint_init(&t2);
	bigint_init(&q);
	bigint_init(&r);
	bigint_init(&tmp1);
	bigint_init(&tmp2);
	
	if(bigint_cmp(a,b)==-1){
		revflag = 1;
		bigint_setval(&r0, b);
		bigint_setval(&r1, a);
	} else{
		bigint_setval(&r0, a);
		bigint_setval(&r1, b);
	}
	bigint_divide(&q,&r2,r0,r1);
	
	bigint_setval32(&s1, 0);
	bigint_setval32(&s2, 1);
	
	bigint_setval32(&t1, 1);
	bigint_setval(&t2, q);
	bigint_negate(&t2);
	
	if(bigint_isval(r2,0)){
		bigint_divide(&tmp1,&tmp2,c,b);
		if(bigint_isval(tmp2,0)){
			if(revflag == 0){
				bigint_setval32(x,0);
				bigint_setval(y,tmp1);
				return;
			}
			bigint_setval(x,tmp1);
			bigint_setval32(y,0);
			return;
		}
		bigint_setval32(x,0);
		bigint_setval32(y,0);
		return;
	}
	while(!bigint_isval(r2,0)){
		bigint_divide(&q,&r,r1,r2);
		
		bigint_setval(&r1, r2);
		bigint_setval(&r2, r);
		
		bigint_multiply(&tmp1,s2,q);
		bigint_subtract(&tmp2,s1,tmp1);
		bigint_setval(&s1, s2);
		bigint_setval(&s2, tmp2);
		
		bigint_multiply(&tmp1,t2,q);
		bigint_subtract(&tmp2,t1,tmp1);
		bigint_setval(&t1, t2);
		bigint_setval(&t2, tmp2);
	}

	bigint_divide(&q,&r,c,r1);
	if(!bigint_isval(r,0)){
		bigint_setval32(x,0);
		bigint_setval32(y,0);
		return;
	}
	if(revflag==1){
		bigint_setval(&tmp1, s1);
		bigint_setval(&s1, t1);
		bigint_setval(&t1, tmp1);
	}
	
	if(s1.sign == BII_NEG){
		bigint_setval(&tmp1, s1);
		bigint_setpos(&tmp1);
		bigint_divide(&tmp2,&r,tmp1,b); 
		bigint_setval(&tmp1, tmp2); 
		if(!bigint_isval(r,0)) bigint_incr(&tmp1);
		bigint_multiply(&tmp2,tmp1,b);
		bigint_plusequals(&s1,tmp2);
		bigint_multiply(&tmp2,tmp1,a);
		bigint_minusequals(&t1,tmp2);
	}

	
	bigint_multiply(x,q,s1);
	bigint_multiply(y,q,t1);
	

	bigint_free(&r0);
	bigint_free(&r1);
	bigint_free(&r2);
	bigint_free(&s1);
	bigint_free(&s2);
	bigint_free(&t1);
	bigint_free(&t2);
	bigint_free(&q);
	bigint_free(&r);
	bigint_free(&tmp1);
	bigint_free(&tmp2);
}
void bii_modexpeven(bigint *dest, bigint a, bigint e, bigint n){
	/*
	 * Returns a**e mod n for the case when n is even. 
	 * This algorithm is from the paper:
	 * Montgomery reduction with even modulus
	 * Koc,C.K.
	 * IEE Proceedings - Computers and Digital Techniques(1994),141(5):314
	 * http://dx.doi.org/10.1049/ip-cdt:19941291
	 */
	 
	bigint q, j, A, E, x1, x2, y,  qinv, tmp1, tmp2;
	bigint_init(&q);
	bigint_init(&j);
	bigint_init(&A);
	bigint_init(&E);
	bigint_init(&x1);
	bigint_init(&x2);
	bigint_init(&y);
	bigint_init(&qinv);
	bigint_init(&tmp1);
	bigint_init(&tmp2);
	
	//n = q * (2**jpow)
	bigint_setval(&q,n);
	uint32_t jpow = 0;
	bigint_setval32(&j,1);
	while(bigint_parity(q)==0){
		bigint_rightshift(&q,1);
		bigint_leftshift(&j,1);
		jpow++;
	}
	
	bigint_divide(&tmp1,&A,a,q);
	
	bii_modexpodd(&x1, A, e, q);
	
	bigint_getsigbits(&A,a,jpow);
	bigint_getsigbits(&E, e, jpow-1);
	
	bii_binarymodpow_powerof2(&x2,A,E,jpow);
	
	bigint_setval32(&tmp1, 1);
	bigint_egcd(q,j,tmp1, &qinv,&tmp2);
	
	bigint_subtract(&tmp1,x2,x1);
	
	bigint_multiply(&tmp2,tmp1,qinv);
	
	bigint_divide(&tmp1,&y,tmp2,j);

	bigint_multiply(&tmp1,q,y);
	bigint_add(dest,x1,tmp1);
	
	bigint_free(&q);
	bigint_free(&j);
	bigint_free(&A);
	bigint_free(&E);
	bigint_free(&x1);
	bigint_free(&x2);
	bigint_free(&y);
	bigint_free(&qinv);
	bigint_free(&tmp1);
	bigint_free(&tmp2);

}