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);
}
Exemple #3
0
/* Allocates some memory for a brainfuck program */
Memory *make_memory(void) {
  int i;
  Memory *mem;

  mem = malloc(sizeof(Memory));
  mem->mp = 0;

  if(wrap) {
    /* memory cells are unsigned char */
    mem->pos_mem = malloc(INIT_MEM_SIZE);
    mem->pos_len = INIT_MEM_SIZE;
    memset(mem->pos_mem, 0, INIT_MEM_SIZE);

    mem->neg_mem = malloc(INIT_MEM_SIZE);
    mem->neg_len = INIT_MEM_SIZE;
    memset(mem->neg_mem, 0, INIT_MEM_SIZE);
  } else {
    /* memory cells are bigint */
    mem->pos_mem = malloc(INIT_MEM_SIZE * sizeof(bigint));
    mem->pos_len = INIT_MEM_SIZE;

    /* we have to cast to "bigint *" here for the pointer arithmetic to work */
    for(i = 0; i < mem->pos_len; i++) bigint_init((bigint *)mem->pos_mem + i);

    mem->neg_mem = malloc(INIT_MEM_SIZE * sizeof(bigint));
    mem->neg_len = INIT_MEM_SIZE;
    for(i = 0; i < mem->neg_len; i++) bigint_init((bigint *)mem->neg_mem + i);
  }

  return mem;
}
int bii_test_modexp(void){
	bigint dest, base, exp, mod;
	bigint_init(&dest);
	bigint_init(&base);
	bigint_init(&exp);
	bigint_init(&mod);
	
	bigint_setval32(&base, 375);
	bigint_setval32(&exp, 249);
	bigint_setval32(&mod, 388);
	buf = calloc(1, sizeof(char));
	
	bigint_modexp(&dest, base, exp, mod);
	if(!bigint_isval(dest, 175)){ 
		printf("Failed.\n");
		return 1;
	} 
	
	bigint_setval32(&base,2);
	bigint_setvalhex(&mod, "444291e51b3ea5fd16673e95674b01e7b");
	//bigint_setval32(&mod, 0x25);
	bigint_setvalrand(&exp, 400);
	bigint_modequals(&exp,mod);
	
	
	bigint_tohex(base,&buf);
	printf("modexp(%s, ",buf);
	
	bigint_tohex(exp, &buf);
	printf("%s, ", buf);
	
	bigint_tohex(mod, &buf);
	printf("%s)\n ", buf);
	fflush(stdout);
	
	bigint_modexp(&dest, base, exp, mod);
	printf("done.\n");fflush(stdout);
	
	bigint_tohex(base,&buf);
	printf("%s",buf);
	printf(" ** ");
	
	bigint_tohex(exp, &buf);
	printf("%s", buf);
	printf(" %% ");
	
	bigint_tohex(mod, &buf);
	printf("%s == ", buf);
	
	bigint_tohex(dest, &buf);
	printf("%s\n", buf);
	
	
	free(buf);
	
	return 0;
}
Exemple #5
0
int bigint_multiply(bigint_s *dst, bigint_s *a, bigint_s *b) {
    if (!dst || !a || !b || !dst->bytes || !a->bytes || !b->bytes) return BIGINT_INVALID_ARGUMENT;
    if (a->bytes_alloced != b->bytes_alloced) return BIGINT_DIFFRENT_SIZE;  // TODO: allow different sizes (padding)

    uint32_t buffer_size = dst->bytes_alloced;
    
    /*
     * multiply two big numbers (in columns with carry)
     * assuming that:
     *       (b-number)     first row
     *     x (a-number)     second row
     *    -------------
     *           result
     */
    bool add = false;
    for (uint32_t i = 0; i < a->bytes_used; i++) {    // second row on paper
        bigint_s tmp;
        bigint_init(&tmp);
        
        uint32_t k = i;
        uint16_t rest = 0, carry = 0;
        for (uint32_t j = 0; j < b->bytes_used; j++) {
            uint16_t result = (uint16_t) a->bytes[i] * (uint16_t) b->bytes[j] + carry;
            
            carry = result/BIGINT_BASE;
            rest = result % BIGINT_BASE;
            
            if (k >= buffer_size) return BIGINT_OUT_OF_MEMORY;
            tmp.bytes[k++] = (uint8_t) rest;
        }
        if (k >= buffer_size) return BIGINT_OUT_OF_MEMORY;
        if (carry > 0) tmp.bytes[k++] = (uint8_t) carry;
        tmp.bytes_used = k;
        
        if (!add) {
            bigint_swap(dst, &tmp);
            add = true;
        } else {
            bigint_s r;
            bigint_init(&r);
            int rr = bigint_add(&r, dst, &tmp);
            if (rr != BIGINT_OK) return rr;
            bigint_swap(dst, &r);
            bigint_free(&r);
        }

        while (dst->bytes_used > 0 && dst->bytes[dst->bytes_used - 1] == 0) { dst->bytes_used--; }  // sometimes result is prefixed with zeros, cutting them off
        bigint_free(&tmp);
    }

    return BIGINT_OK;
}
Exemple #6
0
/** Multiply two big integers.
 *
 * The big integers @a a and @a b are multiplied and the result is stored in
 * @a dest.
 *
 * @param a		First factor.
 * @param b		Second factor.
 * @param dest		Destination bigint.
 */
void bigint_mul(bigint_t *a, bigint_t *b, bigint_t *dest)
{
	size_t idx;
	bigint_t dprod;
	bigint_t sum;
	bigint_t tmp;

#ifdef DEBUG_BIGINT_TRACE
	printf("Multiply bigints.\n");
#endif
	bigint_init(&sum, 0);
	for (idx = 0; idx < b->length; ++idx) {
		bigint_shift_mul_dig(a, b->digit[idx], idx, &dprod);
		bigint_add(&dprod, &sum, &tmp);
		bigint_destroy(&dprod);

		bigint_destroy(&sum);
		bigint_shallow_copy(&tmp, &sum);
	}

	if (b->negative)
		sum.negative = !sum.negative;

	bigint_shallow_copy(&sum, dest);
}
Exemple #7
0
/** Get value of big integer.
 *
 * Allows to obtain the value of big integer, provided that it fits
 * into a small integer.
 *
 * @param bigint	Bigint to obtain value from.
 * @param dval		Place to store value.
 * @return		EOK on success, ELIMIT if bigint is too big to fit
 *			to @a dval.
 */
int bigint_get_value_int(bigint_t *bigint, int *dval)
{
	bigint_t vval, diff;
	size_t idx;
	int val;
	bool_t zf;

#ifdef DEBUG_BIGINT_TRACE
	printf("Get int value of bigint.\n");
#endif
	val = 0;
	for (idx = 0; idx < bigint->length; ++idx) {
		val = val * BIGINT_BASE + bigint->digit[idx];
	}

	if (bigint->negative)
		val = - val;

	/* If the value did not fit @c val now contains garbage. Verify. */
	bigint_init(&vval, val);

	bigint_sub(bigint, &vval, &diff);
	zf = bigint_is_zero(&diff);

	bigint_destroy(&vval);
	bigint_destroy(&diff);

	/* If the difference is not zero, the verification failed. */
	if (zf != b_true)
		return EINVAL;

	*dval = val;
	return EOK;
}
int bii_test_egcd(void){
	bigint a;
	bigint b;
	bigint c;
	bigint x; 
	bigint y;
	
	bigint_initrand(&a, 128);
	bigint_initrand(&b, 128);
	bigint_initrand(&c, 64);
	bigint_init(&x);
	bigint_init(&y);
	
	do{
		bigint_egcd(a,b,c,&x,&y);
	}while(bigint_isval(x,0) && bigint_isval(y,0));
	
	bigint_timesequals(&x,a);
	bigint_timesequals(&y,b);
	bigint_minusequals(&c,x);
	bigint_minusequals(&c,y);
	
	if(!bigint_isval(c,0)){
		printf("egcd failed.\n");
		return 1;
	}
	
	bigint_setval32(&a,4);
	bigint_setval32(&b,3);
	bigint_setval32(&c,1);
	
	bigint_egcd(a,b,c,&x,&y);
	if(!bigint_isval(x,1) || !(bigint_isval(y,1) && y.sign == BII_NEG)){
		printf("egcd(4,3,1) failed.\n");
		return 1;
	}
	
	bigint_free(&a);
	bigint_free(&b);
	bigint_free(&c);
	bigint_free(&x);
	bigint_free(&y);
	return 0;
}
Exemple #9
0
/* Returns a pointer to the current cell of memory in mem. Sorts out the
   growing of memory where necessary */
static inline void *get_cell(Memory *memory) {
  int i;
  int *len;
  void **mem;
  int mp;

  /* positive or negative address? */
  if(memory->mp >= 0) {
    len = &(memory->pos_len);
    mp = memory->mp;

    mem = &(memory->pos_mem);
  } else {
    if(noneg) {
      fprintf(stderr, "%s: negative memory, perhaps you need to stop using "
              "the --no-negative option or fix a memory leak in your "
              "program.\n",
              program_name);
      stop_program = 1;
      return NULL;
    }

    len = &(memory->neg_len);
    mp = -memory->mp;

    mem = &(memory->neg_mem);
  }

  /* check that mp is within range */
  if(maxmem && mp > maxmem) {
    fprintf(stderr, "%s: memory overflow, perhaps you need to adjust the "
            "--max-mem option or fix a memory leak in your program.\n",
            program_name);
    stop_program = 1;
    return NULL;
  }

  /* double the size of memory until we are within range */
  while(mp >= *len) {
    if(wrap) {
      *mem = realloc(*mem, *len * 2);
      memset(*mem + *len, 0, *len);
    } else {
      *mem = realloc(*mem, *len * 2 * sizeof(bigint));

      /* the cast is to make the pointer arithmetic happy */
      for(i = 0; i < *len; i++) bigint_init((bigint *)*mem + *len + i);
    }

    *len *= 2;
  }

  if(wrap) return *mem + mp;
  else return *(bigint **)mem + mp;
}
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);
}
Exemple #11
0
/* Read input to the current cell */
void input(Memory *mem) {
  void *cell;
  bigint input;
  int c;
  char buf[1024];
  char *p;

  if(!(cell = get_cell(mem))) return;

  if(chario) {
    /* character io */
    fflush(stdout);
    c = fgetc(stdin);

    if(c == EOF) goto handle_eof;
    else {
      if(wrap) *(unsigned char *)cell = c;
      else bigint_from_int(cell, c);
    }
  } else {
    /* number io */
    bigint_init(&input);

    /* use bigint for input even if we're reading to wrapping cells */
    do {
      if(prompt) {
        fprintf(stderr, "Input: ");
        fflush(stderr);
      }

      if(!(fgets(buf, 1024, stdin))) goto handle_eof;
      if((p = strchr(buf, '\n'))) *p = '\0';
    } while(bigint_from_string(&input, buf) == BIGINT_ILLEGAL_PARAM);

    if(wrap) *(unsigned char *)cell = bigint_to_int(&input);
    else bigint_copy(cell, &input);

    bigint_release(&input);
  }

  return;

 handle_eof:
  if(strcasecmp(eof_value, "nochange") != 0) {
    bigint_from_string(cell, eof_value);
  }
}
Exemple #12
0
/**
 * Perform modular exponentiation of big integers
 *
 * @v base0		Element 0 of big integer base
 * @v modulus0		Element 0 of big integer modulus
 * @v exponent0		Element 0 of big integer exponent
 * @v result0		Element 0 of big integer to hold result
 * @v size		Number of elements in base, modulus, and result
 * @v exponent_size	Number of elements in exponent
 * @v tmp		Temporary working space
 */
void bigint_mod_exp_raw ( const bigint_element_t *base0,
			  const bigint_element_t *modulus0,
			  const bigint_element_t *exponent0,
			  bigint_element_t *result0,
			  unsigned int size, unsigned int exponent_size,
			  void *tmp ) {
	const bigint_t ( size ) __attribute__ (( may_alias )) *base =
		( ( const void * ) base0 );
	const bigint_t ( size ) __attribute__ (( may_alias )) *modulus =
		( ( const void * ) modulus0 );
	const bigint_t ( exponent_size ) __attribute__ (( may_alias ))
		*exponent = ( ( const void * ) exponent0 );
	bigint_t ( size ) __attribute__ (( may_alias )) *result =
		( ( void * ) result0 );
	size_t mod_multiply_len = bigint_mod_multiply_tmp_len ( modulus );
	struct {
		bigint_t ( size ) base;
		bigint_t ( exponent_size ) exponent;
		uint8_t mod_multiply[mod_multiply_len];
	} *temp = tmp;
	static const uint8_t start[1] = { 0x01 };

	memcpy ( &temp->base, base, sizeof ( temp->base ) );
	memcpy ( &temp->exponent, exponent, sizeof ( temp->exponent ) );
	bigint_init ( result, start, sizeof ( start ) );

	while ( ! bigint_is_zero ( &temp->exponent ) ) {
		if ( bigint_bit_is_set ( &temp->exponent, 0 ) ) {
			bigint_mod_multiply ( result, &temp->base, modulus,
					      result, temp->mod_multiply );
		}
		bigint_ror ( &temp->exponent );
		bigint_mod_multiply ( &temp->base, &temp->base, modulus,
				      &temp->base, temp->mod_multiply );
	}
}
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);

}