Ejemplo n.º 1
0
void test_reduce_bigint(void){
	bigint_t a, b, c;
	cli_putstr_P(PSTR("\r\nreduce test\r\n"));
	for (;;) {
		cli_putstr_P(PSTR("\r\nenter a:"));
		if (bigint_read_hex_echo(&a, 0)) {
			cli_putstr_P(PSTR("\r\n end reduce test"));
			return;
		}
		cli_putstr_P(PSTR("\r\nenter b:"));
		if (bigint_read_hex_echo(&b, 0)) {
			free(a.wordv);
			cli_putstr_P(PSTR("\r\n end reduce test"));
			return;
		}
		cli_putstr_P(PSTR("\r\n "));
		bigint_print_hex(&a);
		cli_putstr_P(PSTR(" % "));
		bigint_print_hex(&b);
		cli_putstr_P(PSTR(" = "));
		memset(&c, 0, sizeof(c));
		bigint_divide(NULL, &c, &a, &b);
		bigint_print_hex(&c);
		cli_putstr_P(PSTR("\r\n"));
        bigint_free(&c);
        bigint_free(&b);
		bigint_free(&a);
	}
}
Ejemplo n.º 2
0
void test_div_bigint(void){
    bigint_t a, b, c, d;
    printf_P(PSTR("\ndiv test\n"));
    for (;;) {
        printf_P(PSTR("\nenter a:"));
        if (bigint_read_hex_echo(&a, 0)) {
            printf_P(PSTR("\n end div test"));
            return;
        }
        printf_P(PSTR("\nenter b:"));
        if (bigint_read_hex_echo(&b, 0)) {
            free(a.wordv);
            printf_P(PSTR("\n end div test"));
            return;
        }
        printf_P(PSTR("\n "));
        bigint_print_hex(&a);
        printf_P(PSTR(" / "));
        bigint_print_hex(&b);
        printf_P(PSTR(" = "));
        memset(&c, 0, sizeof(c));
        memset(&d, 0, sizeof(d));
        bigint_divide(&d, &c, &a, &b);
        bigint_print_hex(&d);
        printf_P(PSTR("; R = "));
        bigint_print_hex(&c);
        printf_P(PSTR("\n"));
        bigint_free(&d);
        bigint_free(&c);
        bigint_free(&b);
        bigint_free(&a);
    }
}
Ejemplo n.º 3
0
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);
}
Ejemplo n.º 4
0
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);
}
Ejemplo n.º 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;
}
Ejemplo n.º 6
0
void test_sub_bigint(void){
    bigint_t a, b, c;
    printf_P(PSTR("\nadd test\n"));
    for (;;) {
        printf_P(PSTR("\nenter a:"));
        if (bigint_read_hex_echo(&a, 512)) {
            printf_P(PSTR("\n end add test"));
            return;
        }
        printf_P(PSTR("\nenter b:"));
        if (bigint_read_hex_echo(&b, 512)) {
            free(a.wordv);
            printf_P(PSTR("\n end add test"));
            return;
        }
        printf_P(PSTR("\n "));
        bigint_print_hex(&a);
        printf_P(PSTR(" - "));
        bigint_print_hex(&b);
        printf_P(PSTR(" = "));
        memset(&c, 0, sizeof(c));
        bigint_sub_u(&c, &a, &b);
        bigint_print_hex(&c);
        cli_putstr_P(PSTR("\r\n"));
        free(a.wordv);
        free(b.wordv);
        bigint_free(&c);
    }
}
Ejemplo n.º 7
0
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;
}
Ejemplo n.º 8
0
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);
}
Ejemplo n.º 9
0
void test_gcdext_bigint(void){
	bigint_t a, b, c, d, e;
	cli_putstr_P(PSTR("\r\ngcdext test\r\n"));
	for (;;) {
		cli_putstr_P(PSTR("\r\nenter a:"));
		if (bigint_read_hex_echo(&a, 0)) {
			cli_putstr_P(PSTR("\r\n end gcdext test"));
			return;
		}
		cli_putstr_P(PSTR("\r\nenter b:"));
		if (bigint_read_hex_echo(&b, 0)) {
			bigint_free(&a);
			cli_putstr_P(PSTR("\r\n end gcdext test"));
			return;
		}

		memset(&c, 0, sizeof(c));
        memset(&d, 0, sizeof(d));
        memset(&e, 0, sizeof(e));
		cli_putstr_P(PSTR("\r\n gcdext( "));
		bigint_print_hex(&a);
		cli_putstr_P(PSTR(", "));
		bigint_print_hex(&b);
		cli_putstr_P(PSTR(") => "));
		bigint_gcdext(&c, &d, &e, &a, &b);
		cli_putstr_P(PSTR("a = "));
		bigint_print_hex(&d);
		cli_putstr_P(PSTR("; b = "));
		bigint_print_hex(&e);
		cli_putstr_P(PSTR("; gcd = "));
		bigint_print_hex(&c);

		cli_putstr_P(PSTR("\r\n"));
		bigint_free(&a);
        bigint_free(&b);
        bigint_free(&c);
        bigint_free(&d);
        bigint_free(&e);
	}
}
Ejemplo n.º 10
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);
}
Ejemplo n.º 11
0
struct bigint_t bigint_sub(const struct bigint_t * left, const struct bigint_t * right)
{
  /* If the left is less than the right, bigint_sub always returns 0. */

  if (left->len < right->len)
    return bigint_new_empty();

  if (left->len == right->len && left->digits[left->len - 1] < right->digits[right->len - 1])
    return bigint_new_empty();

  /* Now, the following expressions holds at all times:
   *   left.len                     >= right.len
   *   left->digits[left->len - 1]  >= right->digits[right->len - 1]
   */

  struct bigint_t ret = bigint_new_empty();
  size_t max_len      = left->len;
  unsigned long *tmp  = realloc(ret.digits, max_len * (sizeof (unsigned long)));
  ret.len             = max_len;
  ret.digits          = tmp;
  int carry_down      = 0;

  for (int i = 0; i < max_len; ++i)
  {
    unsigned long left_digit  = left->len   < i + 1 ? 0 : left->digits[i];
    unsigned long right_digit = right->len  < i + 1 ? 0 : right->digits[i];

    if (left_digit >= right_digit + carry_down)
    {
      unsigned long ret_digit   = left_digit - right_digit - carry_down;
      ret.digits[i]             = ret_digit;
      carry_down                = 0;
    }
    else
    {
      unsigned long ret_digit   = left_digit + bigint_max - right_digit - carry_down;
      ret.digits[i]             = ret_digit;
      carry_down                = 1;
    }
  }

  if (carry_down)
  {
    /* If left < right, */
    bigint_free(&ret);
    return bigint_new_empty();
  }

  int strip_len = 0;

  for (int i = 0; i < max_len - 1; ++i)
  {
    if (ret.digits[max_len - i - 1] != 0)
      break;
    ++strip_len;
  }

  tmp         = realloc(ret.digits, (max_len - strip_len) * (sizeof (unsigned long)));
  ret.len     = max_len - strip_len;
  ret.digits  = tmp;

  return ret;
}
Ejemplo n.º 12
0
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);

}