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; // 正常に処理完了 }
Bool bignum_div1(BigNum b1, BigNum b2, int *a3, BigNum *b4) { //---- 局所宣言 BigNum t; // 一時変数 int k; // 反復変数 //---- 初期処理 *a3 = 0; // 整商の初期化 *b4 = b1; // 剰余の初期化 //---- 計算処理 // b1からb2を引けるだけ引く for ( k = 0; bignum_cmp(b1, b2) >= 0; k++ ) { bignum_sub(b1, b2, b4); b1 = *b4; (*a3)++; } // 引いた回数が整商で残った値が剰余 //---- 事後処理 if ( *a3 >= RAD ) { return FALSE; } // 桁溢れ //---- 返却処理 return TRUE; // 正常に処理完了 }
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; // 正常に処理完了 }
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; // 正常に処理完了 }
/** * Algo de karatsuba pour la multiplication de grands entiers */ bignum* bignum_mul(bignum a, bignum b) { int len_a = bignum_len(a); int len_b = bignum_len(b); // Multiplication stupide pour les petits nombres if(len_a < 2 || len_b < 2) { return bignum_dumb_mul(a, b); } int max = MAX(len_a, len_b); int max_middle = max/2; bignum* high_a = bignum_init(); bignum* high_b = bignum_init(); bignum* low_a = bignum_init(); bignum* low_b = bignum_init(); bignum_split(a, max-max_middle, high_a, low_a); bignum_split(b, max-max_middle, high_b, low_b); bignum* z2 = bignum_mul(*high_a, *high_b); bignum* z0 = bignum_mul(*low_a, *low_b); // Je voudrais de l'operator overloading : (z2*10^(max))+((z1-z2-z0)*10^(max_middle))+(z0) bignum* sum_a = bignum_add(*low_a, *high_a); bignum* sum_b = bignum_add(*low_b, *high_b); bignum_destoroyah(high_a); bignum_destoroyah(high_b); bignum_destoroyah(low_a); bignum_destoroyah(low_b); // z1 = (sum_a*sum_b) - z2 - z0 bignum* mul_of_sum = bignum_mul(*sum_a, *sum_b); bignum* diff_a = bignum_sub(*mul_of_sum,*z2); bignum* z1 = bignum_sub(*diff_a, *z0); bignum_destoroyah(mul_of_sum); bignum_destoroyah(diff_a); bignum_destoroyah(sum_a); bignum_destoroyah(sum_b); //arrondir pour avoir la bonne puissance de 10 dans les shifts. float inter = (float)max; inter = inter/2.0f; inter += 0.5f; max_middle = (int) inter; if(max%2 == 1){ max++; } //r1 = z2*10^(max) bignum* r1 = bignum_copy(z2); bignum_shift_left(r1, max); //r2 = z1 bignum* r2 = bignum_copy(z1); //r2 = r2*10^(max_middle) bignum_shift_left(r2, max_middle); //r3 = r2 + z0 bignum* r3 = bignum_add(*r2, *z0); //bignum_destoroyah(z0); bignum_destoroyah(r2); //rf = r1+r3 bignum* rf = bignum_add(*r1, *r3); bignum_destoroyah(r1); bignum_destoroyah(r3); bignum_destoroyah(z0); bignum_destoroyah(z1); bignum_destoroyah(z2); return rf; }
/** * crypto_rsa_exptmod - RSA modular exponentiation * @in: Input data * @inlen: Input data length * @out: Buffer for output data * @outlen: Maximum size of the output buffer and used size on success * @key: RSA key * @use_private: 1 = Use RSA private key, 0 = Use RSA public key * Returns: 0 on success, -1 on failure */ int crypto_rsa_exptmod(const u8 *in, size_t inlen, u8 *out, size_t *outlen, struct crypto_rsa_key *key, int use_private) { struct bignum *tmp, *a = NULL, *b = NULL; int ret = -1; size_t modlen; if (use_private && !key->private_key) return -1; tmp = bignum_init(); if (tmp == NULL) return -1; if (bignum_set_unsigned_bin(tmp, in, inlen) < 0) goto error; if (bignum_cmp(key->n, tmp) < 0) { /* Too large input value for the RSA key modulus */ goto error; } if (use_private) { /* * Decrypt (or sign) using Chinese remainer theorem to speed * up calculation. This is equivalent to tmp = tmp^d mod n * (which would require more CPU to calculate directly). * * dmp1 = (1/e) mod (p-1) * dmq1 = (1/e) mod (q-1) * iqmp = (1/q) mod p, where p > q * m1 = c^dmp1 mod p * m2 = c^dmq1 mod q * h = q^-1 (m1 - m2) mod p * m = m2 + hq */ a = bignum_init(); b = bignum_init(); if (a == NULL || b == NULL) goto error; /* a = tmp^dmp1 mod p */ if (bignum_exptmod(tmp, key->dmp1, key->p, a) < 0) goto error; /* b = tmp^dmq1 mod q */ if (bignum_exptmod(tmp, key->dmq1, key->q, b) < 0) goto error; /* tmp = (a - b) * (1/q mod p) (mod p) */ if (bignum_sub(a, b, tmp) < 0 || bignum_mulmod(tmp, key->iqmp, key->p, tmp) < 0) goto error; /* tmp = b + q * tmp */ if (bignum_mul(tmp, key->q, tmp) < 0 || bignum_add(tmp, b, tmp) < 0) goto error; } else { /* Encrypt (or verify signature) */ /* tmp = tmp^e mod N */ if (bignum_exptmod(tmp, key->e, key->n, tmp) < 0) goto error; } modlen = crypto_rsa_get_modulus_len(key); if (modlen > *outlen) { *outlen = modlen; goto error; } if (bignum_get_unsigned_bin_len(tmp) > modlen) goto error; /* should never happen */ *outlen = modlen; os_memset(out, 0, modlen); if (bignum_get_unsigned_bin( tmp, out + (modlen - bignum_get_unsigned_bin_len(tmp)), NULL) < 0) goto error; ret = 0; error: bignum_deinit(tmp); bignum_deinit(a); bignum_deinit(b); return ret; }