Ejemplo n.º 1
0
/**
 * Encode the message of given length, using the public key (exponent, modulus)
 * The resulting array will be of size len/bytes, each index being the encryption
 * of "bytes" consecutive characters, given by m = (m1 + m2*128 + m3*128^2 + ..),
 * encoded = m^exponent mod modulus
 */
bignum *encodeMessage(int len, int bytes, char *message, bignum *exponent, bignum *modulus) {
    /* Calloc works here because capacity = 0 forces a realloc by callees but we should really
     * bignum_init() all of these */
    int i, j;
    bignum *encoded = calloc(len/bytes, sizeof(bignum));
    bignum *num128 = bignum_init(), *num128pow = bignum_init();
    bignum *x = bignum_init(), *current = bignum_init();
    bignum_fromint(num128, 128);
    bignum_fromint(num128pow, 1);
    for(i = 0; i < len; i += bytes) {
        bignum_fromint(x, 0);
        bignum_fromint(num128pow, 1);
        /* Compute buffer[0] + buffer[1]*128 + buffer[2]*128^2 etc (base 128 representation for characters->int encoding)*/
        for(j = 0; j < bytes; j++) {
            bignum_fromint(current, message[i + j]);
            bignum_imultiply(current, num128pow);
            bignum_iadd(x, current); /*x += buffer[i + j] * (1 << (7 * j)) */
            bignum_imultiply(num128pow, num128);
        }
        encode(x, exponent, modulus, &encoded[i/bytes]);
#ifndef NOPRINT
        bignum_print(&encoded[i/bytes]);
        printf(" ");
#endif
    }
    return encoded;
}
Ejemplo n.º 2
0
/**
 * Perform an in place divide of source. source = source/div.
 */
void bignum_idivide(bignum *source, bignum *div) {
    bignum *q = bignum_init(), *r = bignum_init();
    bignum_divide(q, r, source, div);
    bignum_copy(q, source);
    bignum_deinit(q);
    bignum_deinit(r);
}
Ejemplo n.º 3
0
Bool bignum_div4(BigNum b1, BigNum b2, BigNum *b3, BigNum *b4)
{
  //----  局所宣言
  int uni;     // 節数の差
  BigNum t;    // 一時変数
  int a;       // 各節の整商
  int k;       // 反復変数

  //----  事前処理
  // 除数の吟味(0除算の禁止)
  if ( bignum_zero(b2) == TRUE ) { return FALSE; }

  //----  初期処理
  bignum_init(b3, 0);                  // 整商の初期化(0)
  bignum_init(b4, 0);                  // 剰余の初期化(0)
  uni = b1.uni - b2.uni +1;            // 節数の差(整商の節数)

  t = b2;
  bignum_shift(&t, uni-1);

  //----  計算処理
  for ( k = uni-1; k >= 0; k-- ) {
    bignum_div1(b1, t, &a, b4);
    b1 = *b4;
    bignum_shift(&t, -1);
    b3->num[k] = a;
  }

  //----  事後処理
  bignum_chk(b3);
  bignum_chk(b4);

  //----  返却処理
  return TRUE;    // 正常に処理完了
}
Ejemplo n.º 4
0
Archivo: bignum.c Proyecto: rtfb/82k
void bignum_init_base_convert(size_t size, int base) {
    bignum multiplier;
    bignum_init(&multiplier);
    bignum_from_int(&multiplier, 1);
    mul_lut = malloc(size * sizeof(bignum));
    mul_lut_size = size;
    for (int i = 0; i < size; ++i) {
        bignum_init(&mul_lut[i]);
        bignum_copy(&mul_lut[i], &multiplier);
        bignum_mul_int(&multiplier, base);
    }
    bignum_free(&multiplier);

    bignum sum;
    bignum_init(&sum);
    for (int i = 0; i < SUMSZ; ++i) {
        for (int j = 0; j < 256; ++j) {
            int m = i*8;
            bignum_from_int(&sum, 0);
            for (uint8_t mask = 1; mask != 0; mask <<= 1) {
                if (j & mask) {
                    bignum_add(&sum, &mul_lut[m]);
                }
                ++m;
            }
            bignum_init(&sum_lut[i][j]);
            bignum_copy(&sum_lut[i][j], &sum);
        }
    }
    bignum_free(&sum);
}
Ejemplo n.º 5
0
Bool bignum_div5(BigNum b1, BigNum b2, BigNum *b3, BigNum *b4)
{
  //----  局所宣言
  BigNum t;
  int a;
  int uni;
  int k;

  //----  事前処理
  if ( bignum_zero(b2) == TRUE ) { return FALSE; }

  //----  初期処理
  bignum_init(b3, 0);
  bignum_init(b4, 0);
  uni = b1.uni - b2.uni+1;

  bignum_shift(&b2, uni);

  //----  計算処理
  for ( k = uni; k >= 0; k-- ) {
    bignum_div3(b1, b2, &t, b4);
    b1 = *b4;
    bignum_shift(&b2, -1);
    b3->num[k] = t.num[0];
  }

  //----  事後処理
  bignum_chk(b3);
  bignum_chk(b4);

  //----  返却処理
  return TRUE;    // 正常に処理完了
}
Ejemplo n.º 6
0
/**
 * Modulate the source by the modulus. source = source % modulus
 */
void bignum_imodulate(bignum* source, bignum* modulus) {
    bignum *q = bignum_init(), *r = bignum_init();
    bignum_divide(q, r, source, modulus);
    bignum_copy(r, source);
    bignum_deinit(q);
    bignum_deinit(r);
}
Ejemplo n.º 7
0
int crypto_mod_exp(const u8 *base, size_t base_len,
                   const u8 *power, size_t power_len,
                   const u8 *modulus, size_t modulus_len,
                   u8 *result, size_t *result_len)
{
    struct bignum *bn_base, *bn_exp, *bn_modulus, *bn_result;
    int ret = 0;

    bn_base = bignum_init();
    bn_exp = bignum_init();
    bn_modulus = bignum_init();
    bn_result = bignum_init();

    if (bn_base == NULL || bn_exp == NULL || bn_modulus == NULL ||
            bn_result == NULL)
        goto error;

    if (bignum_set_unsigned_bin(bn_base, base, base_len) < 0 ||
            bignum_set_unsigned_bin(bn_exp, power, power_len) < 0 ||
            bignum_set_unsigned_bin(bn_modulus, modulus, modulus_len) < 0)
        goto error;

    if (bignum_exptmod(bn_base, bn_exp, bn_modulus, bn_result) < 0)
        goto error;

    ret = bignum_get_unsigned_bin(bn_result, result, result_len);

error:
    bignum_deinit(bn_base);
    bignum_deinit(bn_exp);
    bignum_deinit(bn_modulus);
    bignum_deinit(bn_result);
    return ret;
}
Ejemplo n.º 8
0
/**
 * Perform an in place divide of source, also producing a remainder.
 * source = source/div and remainder = source - source/div.
 */
void bignum_idivider(bignum* source, bignum* div, bignum* remainder) {
    bignum *q = bignum_init(), *r = bignum_init();
    bignum_divide(q, r, source, div);
    bignum_copy(q, source);
    bignum_copy(r, remainder);
    bignum_deinit(q);
    bignum_deinit(r);
}
Ejemplo n.º 9
0
Bool bignum_div3(BigNum b1, BigNum b2, BigNum *b3, BigNum *b4)
{
  //----  局所宣言
  BigNum low;    // 下端
  BigNum hig;    // 上端
  BigNum mid;    // 中央
  BigNum val;     // 計算値(除数と仮整商の積)
  BigNum t;      // 一時変数
  int sft;       // 上端の節数
  int cmp;       // 大小比較の結果

  //----  事前処理
  // 除数の吟味(0除算の禁止)
  if ( bignum_zero(b2) == TRUE ) { return FALSE; }

  //----  初期処理
  bignum_init(&low, 0);       // 下端の初期化(0)
  bignum_init(&hig, 1);       // 上端の仮値(1)
  sft = b1.uni-b2.uni+1;   // 上端の節数
  bignum_shift(&hig, sft);    // 上端の初期化(節移動)
  //----  計算処理
  //--  整商の計算
  while ( bignum_near(low, hig, 1) == 0 ) {
    //   上端と下端の中点として中央値をmidに格納
    bignum_add(low, hig, &mid);

    bignum_half(&mid);
    //   中央値midとb2の乗算をvalに格納l
    if ( bignum_mlt(mid, b2, &val) == FALSE ) {
      return FALSE;
    }
    //   b1とvalが等しければ脱出
    cmp = bignum_cmp(val, b1);
    if ( cmp == 0 ) {
      low = mid;
      break;
    }
    //   異なれば上端または下端を更新
    else if ( cmp > 0 ) {
      hig = mid;
    } else {
      low = mid;
    }
  }
  //--  整商の格納と剰余の計算
  // 下端値lowを整商*b3として格納
  *b3 = low;
  // 整商*b3とb2の乗算をvalに格納l
  bignum_mlt(*b3, b2, &val);
  // b1とvalの差を剰余として*b4に格納
  bignum_sub(b1, val, b4);
  //----  事後処理
  bignum_chk(b3);    // 節数の更新
  bignum_chk(b4);

  //----  返却処理
  return TRUE;    // 正常に処理完了
}
Ejemplo n.º 10
0
Bool bignum_sub(BigNum b1, BigNum b2, BigNum *b0)
{
  //----  局所宣言
  int c;    // 節の繰下り
  int v;    // 当該の節値
  int k;    // 反復変数

  //----  初期処理
  bignum_init(b0, 0);    // 和の初期化
  c = 0;                 // 繰下りを0に

  //----  減算
  for ( k = 0; k < UNI; k++ ) {           // 下位節から
    v = b1.num[k] - b2.num[k] - c;        // 節同士の加算(繰上り付)
    c = 0;                                // 繰下りの初期化
    while ( v < 0 ) { v += RAD; c++; }    // 繰下りの計算(剰余による)
    b0->num[k] = v;                       // 節値の格納
  }

  //----  事後処理
  if ( c != 0 ) { return FALSE; }    // 最上位桁での繰下りの吟味
  bignum_chk(b0);                    // 節数と桁数の格納

  //----  返却処理
  return TRUE;    // 正常に処理完了
}
Ejemplo n.º 11
0
Bool bignum_div2(BigNum b1, int a2, BigNum *b3, int *a4)
{
  //----  局所宣言
  int k;    // 反復変数

  //----  事前処理
  // 除数の吟味(0除算の禁止)

  //----  初期処理
  bignum_init(b3, 0);    // 整商の初期化
  *a4 = 0;               // 剰余の初期化

  //----  計算処理
  // 多倍長の各節をa2で除算
  for ( k = b1.uni-1; k > 0; k-- ) {
    // 整商を各節に格納し、剰余を更新
    b3->num[k] = b1.num[k] / a2;
    b1.num[k-1] += (b1.num[k] % a2) * RAD;
  }
  b3->num[0] = b1.num[k]/a2;
  *a4 = b1.num[k] % a2;
  //----  事後処理
  bignum_chk(b3);    // 節数と桁数の格納

  //----  返却処理
  return TRUE;    // 正常に処理完了
}
Ejemplo n.º 12
0
Bool bignum_gcd1(BigNum b1, BigNum b2, BigNum *b0)
{
  //----  局所宣言
  BigNum e;
  BigNum t;
  int a;
  bignum_init(&e, 1);

  //----  計算処理
  while ( 1 ) {
    if ( bignum_zero(b1) ) { bignum_mlt(b2, e, b0);return; }
    if ( bignum_zero(b2) ) { bignum_mlt(b1, e, b0);return; }
    if ( bignum_cmp(b1, b2) == 0 ) { bignum_mlt(b1, e, b0);return; }
    if ( b1.num[0]%2 == 0 && b2.num[0]%2 == 0 ) {
      bignum_div2(b1, 2, &t, &a); b1 = t;
      bignum_div2(b2, 2, &t, &a); b2 = t;
      bignum_scl(&e, 2);
      continue;
    }
    if ( b1.num[0]%2 == 0 ) { bignum_div2(b1, 2, &t, &a); b1 = t; continue; }
    if ( b2.num[0]%2 == 0 ) { bignum_div2(b2, 2, &t, &a); b2 = t; continue; }
    if ( bignum_cmp(b1, b2) == 1 ) { bignum_sub(b1, b2, &t); b1 = t; }
    else { bignum_sub(b2, b1, &t); b2 = t; }
  }


  //----  返却処理
  return TRUE;    // 正常に処理完了
}
Ejemplo n.º 13
0
bignum_t * bignum_get_str (const char * value) {
	bignum_t * num = x_malloc (sizeof (bignum_t));

	bignum_init (num);

	while (isblank (*value))
		value++;

	if (*value == '-')
		num->sign = true;

	const char * tail_ptr = NULL;

	if (!*value)
		tail_ptr = value;
	else
		tail_ptr = value + strlen (value) - 1;

	while (tail_ptr > value && isspace (*tail_ptr))
		tail_ptr--;

	while (tail_ptr >= value && isdigit (*tail_ptr)) {
		ensure_allocation (num);
		num->digits[num->used++] = *tail_ptr - '0';

		tail_ptr--;
	}

	if (num->allocated == 0) {
		free (num);
		return bignum_get (0);
	}

	return num;
}
Ejemplo n.º 14
0
Archivo: bignum.c Proyecto: rtfb/82k
// a %= b
void bignum_mod(bignum *a, bignum *b) {
    bignum tmp;
    bignum_init(&tmp);
    bignum_div_mod(a, b, &tmp);
    bignum_copy(a, &tmp);
    bignum_free(&tmp);
}
Ejemplo n.º 15
0
Bool bignum_pow1(BigNum b1, int e, BigNum *b0)
{
  //----  局所宣言
  // 一時変数
  BigNum bt;

  //----  事前処理
  // 計算範囲の吟味
  if ( e < 0 ) { return FALSE; }
  if ( b1.dig * e > UNI*LEV ) { return FALSE; }
  //----  初期処理
  // 結果*b0を1に初期化
  bignum_init(b0, 1);

  //----  計算処理
  // 素朴法による累乗計算
  while ( e-- > 0 ) {
    bt = *b0;
    bignum_mlt(b1, bt, b0);
  }
  //----  事後処理
  // 節数と桁数の格納
  bignum_chk(b0);
  //----  返却処理
  return TRUE;    // 正常に処理完了
}
Ejemplo n.º 16
0
Archivo: bignum.c Proyecto: rtfb/82k
// a *= b
void bignum_mul_int(bignum *a, unsigned int b) {
    bignum tmp;
    bignum_init(&tmp);
    uint8_t b_bytes[] = {
         b & 0x000000ff,
        (b & 0x0000ff00) >> 8,
        (b & 0x00ff0000) >> 16,
        (b & 0xff000000) >> 24,
    };
    int b_size = 3;
    while (b_size > 1 && b_bytes[b_size] == 0) --b_size;
    for (int bi = 0; bi < b_size; ++bi) {
        int carry = 0;
        for (int ai = 0; ai < a->size; ++ai) {
            int prod = carry + a->data[ai] * b_bytes[bi];
            carry = prod / 256;
            tmp.data[ai + bi] = prod % 256;
        }
        tmp.data[bi + a->size] = carry;
    }
    tmp.size = a->size + b_size;
    while (tmp.size > 0 && tmp.data[tmp.size - 1] == 0) {
        --tmp.size;
    }
    if (tmp.size == 0) {
        tmp.size = 1;
    }
    bignum_copy(a, &tmp);
    bignum_free(&tmp);
}
Ejemplo n.º 17
0
/**
 * Construit un bignum avec le code ASCII du char c
 */
bignum* bignum_fromchar(char c) {
    int i;

    bignum* num = bignum_init();
    num->sign = BIGNUM_POSITIVE;

    bigdigit* digit = NULL;
    bigdigit** next = &num->first;

    for(i = 0; c; i++) {
        digit = bigdigit_init();

        digit->value = (c % 10);
        c /= 10;

        *next = digit;
        next = &digit->next;
    }

    *next = NULL;

    bignum_clean(num);

    return num;
}
Ejemplo n.º 18
0
/**
 * Construit un bignum avec les digits de num inversés
 */
bignum* bignum_rev(bignum num) {
    bignum* rev = bignum_init();

    bigdigit* rev_digit = NULL;
    bigdigit** digit_addr = &num.first;
    bigdigit* prev_addr = NULL;

    // Construit le nouveau bignum à l'envers
    while(*digit_addr != NULL) {

        rev_digit = bigdigit_init();

        please_dont_segfault(rev_digit);

        rev_digit->next = prev_addr;
        rev_digit->value = (*digit_addr)->value;

        prev_addr = rev_digit;
        digit_addr = &(*digit_addr)->next;
    }

    rev->sign = num.sign;
    rev->first = prev_addr;
    rev->refs = 1;

    // Attention : les trailing zéros sont importants dans le contexte d'un bignum inversé

    return rev;
}
Ejemplo n.º 19
0
Bool bignum_input(BigNum *n)
{
  //----  局所宣言
  int u;    // 多倍長の節数
  int t;    // 一時変数
  int k;    // 反復変数

  //----  初期処理
  bignum_init(n, 0);    // 結果を0に初期化

  //----  節数の入力と確認
  scanf("%d", &u);    // 節数の入力
  if ( u > UNI ) { return FALSE; }    // 節数の超上なら打切

  //----  各節の入力と確認
  for ( k = u-1; k >= 0; k-- ) {    // 上位節から
    scanf("%d", &t);    // 入力値の各格納
    if ( t >= RAD ) { return FALSE; }    // 節値が基数の以上なら打切
    (*n).num[k] = t;    // 構造体の配列メンバに節値を格納
  }

  //----  事後処理
  bignum_chk(n);    // 実際の桁数の計算

  //----  返却処理
  return TRUE;    // 処理が正常に完了
}
Ejemplo n.º 20
0
Bool bignum_add(BigNum b1, BigNum b2, BigNum *b0)
{
  //----  局所宣言
  int c;    // 節の繰上り
  int v;    // 当該の節値
  int k;    // 反復変数

  //----  初期処理
  bignum_init(b0, 0);    // 和を0に
  c = 0;                 // 繰上りを0に

  //----  計算処理
  for ( k = 0; k < UNI; k++ ) {       // 下位節から
    v = b1.num[k] + b2.num[k] + c;    // 節同士の加算(繰上り付)
    c = v / RAD;                      // 繰上りの計算(整商による)
    b0->num[k] = v % RAD;             // 繰上りの清算(剰余による)
  }

  //----  事後処理
  if ( c != 0 ) { return FALSE; }    // 最上位桁での繰上りの吟味
  bignum_chk(b0);                    // 節数と桁数の格納

  //----  返却処理
  return TRUE;    // 正常に処理完了
}
Ejemplo n.º 21
0
Bool bignum_sqrt(BigNum b1, BigNum *b0)
{
  //----  局所宣言
  BigNum low;    // 下端
  BigNum hig;    // 上端
  BigNum mid;    // 中央
  BigNum val;    // 二乗値
  int sft;       // 上端の節数
  int cmp;       // 大小比較の結果

  //----  初期処理
  // lowを最下端0に初期化
  bignum_init(&low, 0);
  // higを最上端に初期化
  // 最上端は結果が含まれる範囲でキリの良い値
  // 1で初期化し、適当な節だけ左シフト
  sft = (UNI-1)/2;
  bignum_init(&hig, 1);
  bignum_shift(&hig, sft);
  //----  計算処理
  while ( bignum_near(hig, low, 1) == FALSE ) {
    //   上端と下端の中点として中央値midの計算
    bignum_add(low, hig, &mid);
    bignum_half(&mid);
    //   中央値midの二乗値val
    bignum_mlt(mid, mid, &val);
    //   二乗値valが入力値b1と等しければ脱出
    cmp = bignum_cmp(val, b1);
    if ( cmp == 0 ) {
      break;
    }//   異なれば上端または下端を更新
    else if ( cmp > 0 ) {
      hig = mid;
    } else {
      low = mid;
    }
  }

  //----  事後処理
  // 中央値midを結果b0に格納
  *b0 = mid;
  // 節数と桁数の更新
  bignum_chk(b0);
  //----  返却処理
  return TRUE;    // 正常に処理完了
}
Ejemplo n.º 22
0
/**
 * Compute the inverse of a mod m. Or, result = a^-1 mod m.
 */
void bignum_inverse(bignum* a, bignum* m, bignum* result) {
    bignum *remprev = bignum_init(), *rem = bignum_init();
    bignum *auxprev = bignum_init(), *aux = bignum_init();
    bignum *rcur = bignum_init(), *qcur = bignum_init(), *acur = bignum_init();
    
    bignum_copy(m, remprev);
    bignum_copy(a, rem);
    bignum_fromint(auxprev, 0);
    bignum_fromint(aux, 1);
    while(bignum_greater(rem, &NUMS[1])) {
        bignum_divide(qcur, rcur, remprev, rem);
        /* Observe we are finding the inverse in a finite field so we can use
         * a modified algorithm that avoids negative numbers here */
        bignum_subtract(acur, m, qcur);
        bignum_imultiply(acur, aux);
        bignum_iadd(acur, auxprev);
        bignum_imodulate(acur, m);
        
        bignum_copy(rem, remprev);
        bignum_copy(aux, auxprev);
        bignum_copy(rcur, rem);
        bignum_copy(acur, aux);
    }
    
    bignum_copy(acur, result);
    
    bignum_deinit(remprev);
    bignum_deinit(rem);
    bignum_deinit(auxprev);
    bignum_deinit(aux);
    bignum_deinit(rcur);
    bignum_deinit(qcur);
    bignum_deinit(acur);
}
Ejemplo n.º 23
0
/**
 * Compute the gcd of two bignums. result = gcd(b1, b2)
 */
void bignum_gcd(bignum* b1, bignum* b2, bignum* result) {
    bignum *a = bignum_init(), *b = bignum_init(), *remainder = bignum_init();
    bignum *temp = bignum_init(), *discard = bignum_init();
    bignum_copy(b1, a);
    bignum_copy(b2, b);
    while(!bignum_equal(b, &NUMS[0])) {
        bignum_copy(b, temp);
        bignum_imodulate(a, b);
        bignum_copy(a, b);
        bignum_copy(temp, a);
    }
    bignum_copy(a, result);
    bignum_deinit(a);
    bignum_deinit(b);
    bignum_deinit(remainder);
    bignum_deinit(temp);
    bignum_deinit(discard);
}
Ejemplo n.º 24
0
bignum* bignum_add(bignum a, bignum b) {
    char carry = 0;

    /* Indique l'opération à  faire en valeur absolue
       1 si les deux nombres sont additionnés en valeur absolue
       -1 s'il s'agit d'une soustraction
    */
    char op = 1;

    int i = 0;
    int size_a = bignum_len(a), size_b = bignum_len(b), max_size = MAX(size_a, size_b);

    bignum* sum = bignum_init();

    bigdigit* digit = NULL;
    bigdigit** da = &a.first;
    bigdigit** db = &b.first;
    bigdigit** next = &sum->first;

    if(a.sign == b.sign) {
        sum->sign = a.sign;
    } else {
        // Assure que |a| >= |b| par la suite
        if(bignum_absgt(b, a)) {
            bignum_destoroyah(sum);
            return bignum_add(b, a);
        }

        sum->sign = a.sign;
        op = -1;
    }

    for(i = 0; i < max_size + 1; i++) {
        digit = bigdigit_init();

        digit->value = carry;

        if(i < size_a) {
            digit->value += (*da)->value;
            da = &(*da)->next;
        }
        if(i < size_b) {
            digit->value += op * (*db)->value;
            db = &(*db)->next;
        }

        carry = op * (digit->value >= 10 || digit->value < 0);
        digit->value = (digit->value + 10) % 10;
        *next = digit;
        next = &digit->next;
    }

    *next = NULL;
    bignum_clean(sum);

    return sum;
}
Ejemplo n.º 25
0
/**
 * Decode the cryptogram of given length, using the private key (exponent, modulus)
 * Each encrypted packet should represent "bytes" characters as per encodeMessage.
 * The returned message will be of size len * bytes.
 */
int *decodeMessage(int len, int bytes, bignum *cryptogram, bignum *exponent, bignum *modulus) {
    int *decoded = malloc(len * bytes * sizeof(int));
    int i, j;
    bignum *x = bignum_init(), *remainder = bignum_init();
    bignum *num128 = bignum_init();
    bignum_fromint(num128, 128);
    for(i = 0; i < len; i++) {
        decode(&cryptogram[i], exponent, modulus, x);
        for(j = 0; j < bytes; j++) {
            bignum_idivider(x, num128, remainder);
            if(remainder->length == 0) decoded[i*bytes + j] = (char)0;
            else decoded[i*bytes + j] = (char)(remainder->data[0]);
#ifndef NOPRINT
            printf("%c", (char)(decoded[i*bytes + j]));
#endif
        }
    }
    return decoded;
}
Ejemplo n.º 26
0
Bool bignum_div4(BigNum b1, BigNum b2, BigNum *b3, BigNum *b4)
{
  //----  局所宣言
  int uni;     // 節数の差
  BigNum t, p;    // 一時変数
  int a;       // 各節の整商
  int k;       // 反復変数

  //----  事前処理
  // 除数の吟味(0除算の禁止)
  if ( bignum_zero(b2) == TRUE ) { return FALSE; }

  //----  初期処理
  bignum_init(b3, 0);                  // 整商の初期化(0)
  bignum_init(b4, 0);                  // 剰余の初期化(0)
  uni = b1.uni - b2.uni +1;            // 節数の差(整商の節数)

  //----  計算処理
  for ( k = uni; k >= 0; k-- ) {
    bignum_scl(b4, RAD);
    bignum_add(b1, *b4, &t);
    b1 = t;

    b2 = t;
    bignum_shift(&t, k);
    bignum_output(b1);
    bignum_output(t);
    bignum_div1(b1, t, &a, b4);
    bignum_scl(&t, a);
    bignum_sub(b1, t, &p);
    b1 = p;
    b3->num[k] = a;
  }

  //----  事後処理
  bignum_chk(b3);
  bignum_chk(b4);

  //----  返却処理
  return TRUE;    // 正常に処理完了
}
Ejemplo n.º 27
0
Bool bignum_pow1(BigNum b1, int e, BigNum *b0)
{
  //----  局所宣言
  // 一時変数
  int k1, k2;
  BigNum bt;
  int c;
  //----  事前処理
  // 計算範囲の吟味
  if ( e < -1 ) { return FALSE; }
  if ( b1.dig * e > UNI*LEV ) { return FALSE; }
  //----  初期処理
  // 結果*b0を1に初期化
  bignum_init(b0, 1);

  //----  計算処理
  // 素朴法による累乗計算
  while ( e-- > 0 ) {
    bt = *b0;
    bignum_init(b0, 0);
    for ( k1 = 0; k1 < b1.uni; k1++ ) {
      for ( k2 = 0; k2 < bt.uni; k2++ ) {
        if ( k1 + k2 >= UNI ) { continue; }           // 添字の範囲外
        b0->num[k1+k2] += b1.num[k1] * bt.num[k2];    // 桁ごとの加算
      }
    }

    // 繰上りの清算
    c = 0;
    for ( k1 = 0; k1 < UNI; k1++ ) {                // 下位桁から
      b0->num[k1] += c;                             // 桁同士の加算
      c = b0->num[k1] / RAD; b0->num[k1] %= RAD;    // 繰上りの清算
    }
    bignum_chk(b0);
  }

  //----  事後処理
  // 節数と桁数の格納
  //----  返却処理
  return TRUE;    // 正常に処理完了
}
Ejemplo n.º 28
0
Archivo: bignum.c Proyecto: rtfb/82k
// a *= b
void bignum_mul_int_silly_loop(bignum *a, unsigned int b) {
    bignum tmp;
    bignum_init(&tmp);
    bignum_copy(&tmp, a);
    --b;
    // XXX: this loop is probably quite inefficient, think of something better
    while (b > 0) {
        bignum_add(a, &tmp);
        --b;
    }
    bignum_free(&tmp);
}
Ejemplo n.º 29
0
/**
 * Check whether a is a Euler witness for n. That is, if a^(n - 1)/2 != Ja(a, n) mod n
 */
int solovayPrime(int a, bignum* n) {
    bignum *ab = bignum_init(), *res = bignum_init(), *pow = bignum_init();
    bignum *modpow = bignum_init();
    int x, result;
    
    bignum_fromint(ab, a);
    x = bignum_jacobi(ab, n);
    if(x == -1) bignum_subtract(res, n, &NUMS[1]);
    else bignum_fromint(res, x);
    bignum_copy(n, pow);
    bignum_isubtract(pow, &NUMS[1]);
    bignum_idivide(pow, &NUMS[2]);
    bignum_modpow(ab, pow, n, modpow);
    
    result = !bignum_equal(res, &NUMS[0]) && bignum_equal(modpow, res);
    bignum_deinit(ab);
    bignum_deinit(res);
    bignum_deinit(pow);
    bignum_deinit(modpow);
    return result;
}
Ejemplo n.º 30
0
/**
 * Print a bignum to stdout as base 10 integer. This is done by
 * repeated division by 10. We can make it more efficient by dividing by
 * 10^9 for example, then doing single precision arithmetic to retrieve the
 * 9 remainders
 */
void bignum_print(bignum* b) {
    int cap = 100, len = 0, i;
    char* buffer = malloc(cap * sizeof(char));
    bignum *copy = bignum_init(), *remainder = bignum_init();
    if(b->length == 0 || bignum_iszero(b)) printf("0");
    else {
        bignum_copy(b, copy);
        while(bignum_isnonzero(copy)) {
            bignum_idivider(copy, &NUMS[10], remainder);
            buffer[len++] = remainder->data[0];
            if(len >= cap) {
                cap *= 2;
                buffer = realloc(buffer, cap * sizeof(char));
            }
        }
        for(i = len - 1; i >= 0; i--) printf("%d", buffer[i]);
    }
    bignum_deinit(copy);
    bignum_deinit(remainder);
    free(buffer);
}