Пример #1
0
            /* @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);
            }