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 import botan.math.bigint.bigint; 19 import std.traits : isPointer; 20 21 /** 22 * Modular Reducer (using Barrett's technique) 23 */ 24 struct ModularReducer 25 { 26 public: 27 ref const(BigInt) getModulus() const return { return m_modulus; } 28 29 /* 30 * Barrett Reduction 31 */ 32 BigInt reduce(BigInt x) const 33 { 34 if (m_mod_words == 0) 35 throw new InvalidState("ModularReducer: Never initalized"); 36 if (x.cmp(m_modulus, false) < 0) 37 { 38 if (x.isNegative()) 39 return x + m_modulus; // make positive 40 return x.move; 41 } 42 else if (x.cmp(m_modulus_2, false) < 0) 43 { 44 BigInt t1 = x.clone; 45 t1.setSign(BigInt.Positive); 46 t1 >>= (MP_WORD_BITS * (m_mod_words - 1)); 47 t1 *= m_mu; 48 49 t1 >>= (MP_WORD_BITS * (m_mod_words + 1)); 50 t1 *= m_modulus; 51 52 t1.maskBits(MP_WORD_BITS * (m_mod_words + 1)); 53 54 BigInt t2 = x.move; 55 t2.setSign(BigInt.Positive); 56 t2.maskBits(MP_WORD_BITS * (m_mod_words + 1)); 57 58 t2 -= t1; 59 60 if (t2.isNegative()) 61 { 62 t2 += BigInt.powerOf2(MP_WORD_BITS * (m_mod_words + 1)); 63 } 64 while (t2 >= m_modulus) 65 t2 -= m_modulus; 66 67 if (x.isPositive()) 68 return t2.move(); 69 else 70 return m_modulus - t2; 71 } 72 else 73 { 74 // too big, fall back to normal division 75 return (x % m_modulus); 76 } 77 } 78 79 /** 80 * Multiply mod p 81 * Params: 82 * x = integer 83 * y = integer 84 * Returns: (x * y) % p 85 */ 86 BigInt multiply(const(BigInt)* x, const(BigInt)* y) const 87 { 88 return reduce((*x) * y); 89 } 90 91 /** 92 * Square mod p 93 * Params: 94 * x = integer 95 * Returns: (x * x) % p 96 */ 97 BigInt square()(const(BigInt)* x) const 98 { 99 return reduce(x.square()); 100 } 101 102 /** 103 * Cube mod p 104 * Params: 105 * x = integer 106 * Returns: (x * x * x) % p 107 */ 108 BigInt cube()(const(BigInt)* x) const 109 { return multiply(x, this.square(x)); } 110 111 bool initialized() const { return (m_mod_words != 0); } 112 /* 113 * ModularReducer Constructor 114 */ 115 this(const ref BigInt mod) 116 { 117 if (mod <= 0) 118 throw new InvalidArgument("ModularReducer: modulus must be positive"); 119 m_modulus = mod.clone; 120 m_mod_words = m_modulus.sigWords(); 121 m_modulus_2 = .square(&m_modulus); 122 auto po2 = BigInt.powerOf2(2 * MP_WORD_BITS * m_mod_words); 123 m_mu = po2 / m_modulus; 124 } 125 126 @property ModularReducer clone() const { 127 return ModularReducer(m_modulus); 128 } 129 130 private: 131 BigInt m_modulus, m_modulus_2, m_mu; 132 size_t m_mod_words; 133 }