/* @brief Perform a modular exponentiation. * This function requires bi_set_mod() to have been called previously. This is * one of the optimisations used for performance. * @param ctx [in] The bigint session context. * @param bi [in] The bigint on which to perform the mod power operation. * @param biexp [in] The bigint exponent. * @return The result of the mod exponentiation operation * @see bi_set_mod(). */ internal bigint bi_mod_power(bigint bi, bigint biexp) { int i = biexp.find_max_exp_index(); int window_size = 1; bigint biR = this.int_to_bi(1); this.g = new bigint[] { this.bi_clone(bi) }; this.window = 1; this.g[0].bi_permanent(); /* if sliding-window is off, then only one bit will be done at a time and * will reduce to standard left-to-right exponentiation */ do { if (biexp.exp_bit_is_one(i)) { int l = i - window_size + 1; int part_exp = 0; if (l < 0) { /* LSB of exponent will always be 1 */ l = 0; } else { while (!biexp.exp_bit_is_one(l)) { l++; /* go back up */ } } /* build up the section of the exponent */ for (int j = i; j >= l; j--) { biR = this.bi_Modulo(this.bi_square(biR)); if (biexp.exp_bit_is_one(j)) { part_exp++; } if (j != l) { part_exp <<= 1; } } part_exp = (part_exp - 1) / 2; /* adjust for array */ biR = this.bi_Modulo(this.bi_multiply(biR, this.g[part_exp])); i = l - 1; } else /* square it */ { biR = this.bi_Modulo(this.bi_square(biR)); i--; } } while (i >= 0); /* cleanup */ for (i = 0; i < this.window; i++) { bi_depermanent(this.g[i]); this.bi_free(this.g[i]); } this.g = null; this.bi_free(bi); this.bi_free(biexp); return(biR); }