/* * Modular Exponentiation Proxy * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ #include #include #include namespace Botan { /* * Power_Mod Constructor */ Power_Mod::Power_Mod(const BigInt& n, Usage_Hints hints) { core = 0; set_modulus(n, hints); } /* * Power_Mod Copy Constructor */ Power_Mod::Power_Mod(const Power_Mod& other) { core = 0; if(other.core) core = other.core->copy(); } /* * Power_Mod Assignment Operator */ Power_Mod& Power_Mod::operator=(const Power_Mod& other) { delete core; core = 0; if(other.core) core = other.core->copy(); return (*this); } /* * Power_Mod Destructor */ Power_Mod::~Power_Mod() { delete core; } /* * Set the modulus */ void Power_Mod::set_modulus(const BigInt& n, Usage_Hints hints) const { delete core; core = 0; if(n != 0) { Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory()); while(const Engine* engine = i.next()) { core = engine->mod_exp(n, hints); if(core) break; } if(!core) throw Lookup_Error("Power_Mod: Unable to find a working engine"); } } /* * Set the base */ void Power_Mod::set_base(const BigInt& b) const { if(b.is_zero() || b.is_negative()) throw Invalid_Argument("Power_Mod::set_base: arg must be > 0"); if(!core) throw Internal_Error("Power_Mod::set_base: core was NULL"); core->set_base(b); } /* * Set the exponent */ void Power_Mod::set_exponent(const BigInt& e) const { if(e.is_negative()) throw Invalid_Argument("Power_Mod::set_exponent: arg must be > 0"); if(!core) throw Internal_Error("Power_Mod::set_exponent: core was NULL"); core->set_exponent(e); } /* * Compute the result */ BigInt Power_Mod::execute() const { if(!core) throw Internal_Error("Power_Mod::execute: core was NULL"); return core->execute(); } /* * Try to choose a good window size */ size_t Power_Mod::window_bits(size_t exp_bits, size_t, Power_Mod::Usage_Hints hints) { static const size_t wsize[][2] = { { 2048, 7 }, { 1024, 6 }, { 256, 5 }, { 128, 4 }, { 64, 3 }, { 0, 0 } }; size_t window_bits = 1; if(exp_bits) { for(size_t j = 0; wsize[j][0]; ++j) { if(exp_bits >= wsize[j][0]) { window_bits += wsize[j][1]; break; } } } if(hints & Power_Mod::BASE_IS_FIXED) window_bits += 2; if(hints & Power_Mod::EXP_IS_LARGE) ++window_bits; return window_bits; } namespace { /* * Choose potentially useful hints */ Power_Mod::Usage_Hints choose_base_hints(const BigInt& b, const BigInt& n) { if(b == 2) return Power_Mod::Usage_Hints(Power_Mod::BASE_IS_2 | Power_Mod::BASE_IS_SMALL); const size_t b_bits = b.bits(); const size_t n_bits = n.bits(); if(b_bits < n_bits / 32) return Power_Mod::BASE_IS_SMALL; if(b_bits > n_bits / 4) return Power_Mod::BASE_IS_LARGE; return Power_Mod::NO_HINTS; } /* * Choose potentially useful hints */ Power_Mod::Usage_Hints choose_exp_hints(const BigInt& e, const BigInt& n) { const size_t e_bits = e.bits(); const size_t n_bits = n.bits(); if(e_bits < n_bits / 32) return Power_Mod::BASE_IS_SMALL; if(e_bits > n_bits / 4) return Power_Mod::BASE_IS_LARGE; return Power_Mod::NO_HINTS; } } /* * Fixed_Exponent_Power_Mod Constructor */ Fixed_Exponent_Power_Mod::Fixed_Exponent_Power_Mod(const BigInt& e, const BigInt& n, Usage_Hints hints) : Power_Mod(n, Usage_Hints(hints | EXP_IS_FIXED | choose_exp_hints(e, n))) { set_exponent(e); } /* * Fixed_Base_Power_Mod Constructor */ Fixed_Base_Power_Mod::Fixed_Base_Power_Mod(const BigInt& b, const BigInt& n, Usage_Hints hints) : Power_Mod(n, Usage_Hints(hints | BASE_IS_FIXED | choose_base_hints(b, n))) { set_base(b); } }