/* * Modular Exponentiation Proxy * (C) 1999-2007 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ #include #include namespace Botan { /* * Power_Mod Constructor */ Power_Mod::Power_Mod(const BigInt& n, Usage_Hints hints) { m_core = nullptr; set_modulus(n, hints); } /* * Power_Mod Copy Constructor */ Power_Mod::Power_Mod(const Power_Mod& other) { m_core = nullptr; if(other.m_core) m_core = other.m_core->copy(); } /* * Power_Mod Assignment Operator */ Power_Mod& Power_Mod::operator=(const Power_Mod& other) { delete m_core; m_core = nullptr; if(other.m_core) m_core = other.m_core->copy(); return (*this); } /* * Power_Mod Destructor */ Power_Mod::~Power_Mod() { delete m_core; m_core = nullptr; } /* * Set the modulus */ void Power_Mod::set_modulus(const BigInt& n, Usage_Hints hints) const { delete m_core; if(n.is_odd()) m_core = new Montgomery_Exponentiator(n, hints); else if(n != 0) m_core = new Fixed_Window_Exponentiator(n, hints); } /* * 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(!m_core) throw Internal_Error("Power_Mod::set_base: m_core was NULL"); m_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(!m_core) throw Internal_Error("Power_Mod::set_exponent: m_core was NULL"); m_core->set_exponent(e); } /* * Compute the result */ BigInt Power_Mod::execute() const { if(!m_core) throw Internal_Error("Power_Mod::execute: m_core was NULL"); return m_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] = { { 1434, 7 }, { 539, 6 }, { 197, 4 }, { 70, 3 }, { 25, 2 }, { 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); } }