1 /** 2 * Modular Reducer 3 * 4 * Copyright: 5 * (C) 1999-2010 Jack Lloyd 6 * (C) 2014-2015 Etienne Cimon 7 * 8 * License: 9 * Botan is released under the Simplified BSD License (see LICENSE.md) 10 */ 11 module botan.math.numbertheory.reducer; 12 13 import botan.constants; 14 static if (BOTAN_HAS_PUBLIC_KEY_CRYPTO): 15 16 import botan.math.numbertheory.numthry; 17 import botan.math.mp.mp_core; 18 19 /** 20 * Modular Reducer (using Barrett's technique) 21 */ 22 struct ModularReducer 23 { 24 public: 25 ref const(BigInt) getModulus() const { return m_modulus; } 26 27 /* 28 * Barrett Reduction 29 */ 30 BigInt reduce(BigInt x) const 31 { 32 if (m_mod_words == 0) 33 throw new InvalidState("ModularReducer: Never initalized"); 34 if (x.cmp(m_modulus, false) < 0) 35 { 36 if (x.isNegative()) 37 return x + m_modulus; // make positive 38 return x.move; 39 } 40 else if (x.cmp(m_modulus_2, false) < 0) 41 { 42 BigInt t1 = x.dup; 43 t1.setSign(BigInt.Positive); 44 t1 >>= (MP_WORD_BITS * (m_mod_words - 1)); 45 t1 *= m_mu; 46 47 t1 >>= (MP_WORD_BITS * (m_mod_words + 1)); 48 t1 *= m_modulus; 49 50 t1.maskBits(MP_WORD_BITS * (m_mod_words + 1)); 51 52 BigInt t2 = x.move; 53 t2.setSign(BigInt.Positive); 54 t2.maskBits(MP_WORD_BITS * (m_mod_words + 1)); 55 56 t2 -= t1; 57 58 if (t2.isNegative()) 59 { 60 t2 += BigInt.powerOf2(MP_WORD_BITS * (m_mod_words + 1)); 61 } 62 while (t2 >= m_modulus) 63 t2 -= m_modulus; 64 65 if (x.isPositive()) 66 return t2.move(); 67 else 68 return m_modulus - t2; 69 } 70 else 71 { 72 // too big, fall back to normal division 73 return (x % m_modulus); 74 } 75 } 76 77 /** 78 * Multiply mod p 79 * Params: 80 * x = integer 81 * y = integer 82 * Returns: (x * y) % p 83 */ 84 BigInt multiply()(auto const ref BigInt x, auto const ref BigInt y) const 85 { 86 return reduce(x * y); 87 } 88 89 /** 90 * Square mod p 91 * Params: 92 * x = integer 93 * Returns: (x * x) % p 94 */ 95 BigInt square()(auto const ref BigInt x) const 96 { 97 return reduce(x.square()); 98 } 99 100 /** 101 * Cube mod p 102 * Params: 103 * x = integer 104 * Returns: (x * x * x) % p 105 */ 106 BigInt cube()(auto const ref BigInt x) const 107 { return multiply(x, this.square(x)); } 108 109 bool initialized() const { return (m_mod_words != 0); } 110 /* 111 * ModularReducer Constructor 112 */ 113 this(const ref BigInt mod) 114 { 115 if (mod <= 0) 116 throw new InvalidArgument("ModularReducer: modulus must be positive"); 117 m_modulus = mod.dup; 118 m_mod_words = m_modulus.sigWords(); 119 m_modulus_2 = .square(m_modulus); 120 auto po2 = BigInt.powerOf2(2 * MP_WORD_BITS * m_mod_words); 121 m_mu = po2 / m_modulus; 122 } 123 124 @property ModularReducer dup() const { 125 return ModularReducer(m_modulus); 126 } 127 128 private: 129 BigInt m_modulus, m_modulus_2, m_mu; 130 size_t m_mod_words; 131 }