Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:55:05

0001 // modarith.h - originally written and placed in the public domain by Wei Dai

0002 
0003 /// \file modarith.h

0004 /// \brief Class file for performing modular arithmetic.

0005 
0006 #ifndef CRYPTOPP_MODARITH_H
0007 #define CRYPTOPP_MODARITH_H
0008 
0009 // implementations are in integer.cpp

0010 
0011 #include "cryptlib.h"
0012 #include "integer.h"
0013 #include "algebra.h"
0014 #include "secblock.h"
0015 #include "misc.h"
0016 
0017 #if CRYPTOPP_MSC_VERSION
0018 # pragma warning(push)
0019 # pragma warning(disable: 4231 4275)
0020 #endif
0021 
0022 NAMESPACE_BEGIN(CryptoPP)
0023 
0024 CRYPTOPP_DLL_TEMPLATE_CLASS AbstractGroup<Integer>;
0025 CRYPTOPP_DLL_TEMPLATE_CLASS AbstractRing<Integer>;
0026 CRYPTOPP_DLL_TEMPLATE_CLASS AbstractEuclideanDomain<Integer>;
0027 
0028 /// \brief Ring of congruence classes modulo n

0029 /// \details This implementation represents each congruence class as

0030 ///  the smallest non-negative integer in that class.

0031 /// \details <tt>const Element&</tt> returned by member functions are

0032 ///  references to internal data members. Since each object may have

0033 ///  only one such data member for holding results, you should use the

0034 ///  class like this:

0035 ///  <pre>    abcd = group.Add(a, group.Add(b, group.Add(c,d));</pre>

0036 ///  The following code will produce <i>incorrect</i> results:

0037 ///  <pre>    abcd = group.Add(group.Add(a,b), group.Add(c,d));</pre>

0038 /// \details If a ModularArithmetic() is copied or assigned the modulus

0039 ///  is copied, but not the internal data members. The internal data

0040 ///  members are undefined after copy or assignment.

0041 /// \sa <A HREF="https://cryptopp.com/wiki/Integer">Integer</A> on the

0042 ///  Crypto++ wiki.

0043 class CRYPTOPP_DLL ModularArithmetic : public AbstractRing<Integer>
0044 {
0045 public:
0046 
0047     typedef int RandomizationParameter;
0048     typedef Integer Element;
0049 
0050     virtual ~ModularArithmetic() {}
0051 
0052     /// \brief Construct a ModularArithmetic

0053     /// \param modulus congruence class modulus

0054     ModularArithmetic(const Integer &modulus = Integer::One())
0055         : m_modulus(modulus), m_result(static_cast<word>(0), modulus.reg.size()) {}
0056 
0057     /// \brief Copy construct a ModularArithmetic

0058     /// \param ma other ModularArithmetic

0059     ModularArithmetic(const ModularArithmetic &ma)
0060         : AbstractRing<Integer>(ma), m_modulus(ma.m_modulus), m_result(static_cast<word>(0), m_modulus.reg.size()) {}
0061 
0062     /// \brief Assign a ModularArithmetic

0063     /// \param ma other ModularArithmetic

0064     ModularArithmetic& operator=(const ModularArithmetic &ma) {
0065         if (this != &ma)
0066         {
0067             m_modulus = ma.m_modulus;
0068             m_result = Integer(static_cast<word>(0), m_modulus.reg.size());
0069         }
0070         return *this;
0071     }
0072 
0073     /// \brief Construct a ModularArithmetic

0074     /// \param bt BER encoded ModularArithmetic

0075     ModularArithmetic(BufferedTransformation &bt);  // construct from BER encoded parameters

0076 
0077     /// \brief Clone a ModularArithmetic

0078     /// \return pointer to a new ModularArithmetic

0079     /// \details Clone effectively copy constructs a new ModularArithmetic. The caller is

0080     ///   responsible for deleting the pointer returned from this method.

0081     virtual ModularArithmetic * Clone() const {return new ModularArithmetic(*this);}
0082 
0083     /// \brief Encodes in DER format

0084     /// \param bt BufferedTransformation object

0085     void DEREncode(BufferedTransformation &bt) const;
0086 
0087     /// \brief Encodes element in DER format

0088     /// \param out BufferedTransformation object

0089     /// \param a Element to encode

0090     void DEREncodeElement(BufferedTransformation &out, const Element &a) const;
0091 
0092     /// \brief Decodes element in DER format

0093     /// \param in BufferedTransformation object

0094     /// \param a Element to decode

0095     void BERDecodeElement(BufferedTransformation &in, Element &a) const;
0096 
0097     /// \brief Retrieves the modulus

0098     /// \return the modulus

0099     const Integer& GetModulus() const {return m_modulus;}
0100 
0101     /// \brief Sets the modulus

0102     /// \param newModulus the new modulus

0103     void SetModulus(const Integer &newModulus)
0104         {m_modulus = newModulus; m_result.reg.resize(m_modulus.reg.size());}
0105 
0106     /// \brief Retrieves the representation

0107     /// \return true if the if the modulus is in Montgomery form for multiplication, false otherwise

0108     virtual bool IsMontgomeryRepresentation() const {return false;}
0109 
0110     /// \brief Reduces an element in the congruence class

0111     /// \param a element to convert

0112     /// \return the reduced element

0113     /// \details ConvertIn is useful for derived classes, like MontgomeryRepresentation, which

0114     ///   must convert between representations.

0115     virtual Integer ConvertIn(const Integer &a) const
0116         {return a%m_modulus;}
0117 
0118     /// \brief Reduces an element in the congruence class

0119     /// \param a element to convert

0120     /// \return the reduced element

0121     /// \details ConvertOut is useful for derived classes, like MontgomeryRepresentation, which

0122     ///   must convert between representations.

0123     virtual Integer ConvertOut(const Integer &a) const
0124         {return a;}
0125 
0126     /// \brief Divides an element by 2

0127     /// \param a element to convert

0128     const Integer& Half(const Integer &a) const;
0129 
0130     /// \brief Compare two elements for equality

0131     /// \param a first element

0132     /// \param b second element

0133     /// \return true if the elements are equal, false otherwise

0134     /// \details Equal() tests the elements for equality using <tt>a==b</tt>

0135     bool Equal(const Integer &a, const Integer &b) const
0136         {return a==b;}
0137 
0138     /// \brief Provides the Identity element

0139     /// \return the Identity element

0140     const Integer& Identity() const
0141         {return Integer::Zero();}
0142 
0143     /// \brief Adds elements in the ring

0144     /// \param a first element

0145     /// \param b second element

0146     /// \return the sum of <tt>a</tt> and <tt>b</tt>

0147     const Integer& Add(const Integer &a, const Integer &b) const;
0148 
0149     /// \brief TODO

0150     /// \param a first element

0151     /// \param b second element

0152     /// \return TODO

0153     Integer& Accumulate(Integer &a, const Integer &b) const;
0154 
0155     /// \brief Inverts the element in the ring

0156     /// \param a first element

0157     /// \return the inverse of the element

0158     const Integer& Inverse(const Integer &a) const;
0159 
0160     /// \brief Subtracts elements in the ring

0161     /// \param a first element

0162     /// \param b second element

0163     /// \return the difference of <tt>a</tt> and <tt>b</tt>. The element <tt>a</tt> must provide a Subtract member function.

0164     const Integer& Subtract(const Integer &a, const Integer &b) const;
0165 
0166     /// \brief TODO

0167     /// \param a first element

0168     /// \param b second element

0169     /// \return TODO

0170     Integer& Reduce(Integer &a, const Integer &b) const;
0171 
0172     /// \brief Doubles an element in the ring

0173     /// \param a the element

0174     /// \return the element doubled

0175     /// \details Double returns <tt>Add(a, a)</tt>. The element <tt>a</tt> must provide an Add member function.

0176     const Integer& Double(const Integer &a) const
0177         {return Add(a, a);}
0178 
0179     /// \brief Retrieves the multiplicative identity

0180     /// \return the multiplicative identity

0181     /// \details the base class implementations returns 1.

0182     const Integer& MultiplicativeIdentity() const
0183         {return Integer::One();}
0184 
0185     /// \brief Multiplies elements in the ring

0186     /// \param a the multiplicand

0187     /// \param b the multiplier

0188     /// \return the product of a and b

0189     /// \details Multiply returns <tt>a*b\%n</tt>.

0190     const Integer& Multiply(const Integer &a, const Integer &b) const
0191         {return m_result1 = a*b%m_modulus;}
0192 
0193     /// \brief Square an element in the ring

0194     /// \param a the element

0195     /// \return the element squared

0196     /// \details Square returns <tt>a*a\%n</tt>. The element <tt>a</tt> must provide a Square member function.

0197     const Integer& Square(const Integer &a) const
0198         {return m_result1 = a.Squared()%m_modulus;}
0199 
0200     /// \brief Determines whether an element is a unit in the ring

0201     /// \param a the element

0202     /// \return true if the element is a unit after reduction, false otherwise.

0203     bool IsUnit(const Integer &a) const
0204         {return Integer::Gcd(a, m_modulus).IsUnit();}
0205 
0206     /// \brief Calculate the multiplicative inverse of an element in the ring

0207     /// \param a the element

0208     /// \details MultiplicativeInverse returns <tt>a<sup>-1</sup>\%n</tt>. The element <tt>a</tt> must

0209     ///   provide a InverseMod member function.

0210     const Integer& MultiplicativeInverse(const Integer &a) const
0211         {return m_result1 = a.InverseMod(m_modulus);}
0212 
0213     /// \brief Divides elements in the ring

0214     /// \param a the dividend

0215     /// \param b the divisor

0216     /// \return the quotient

0217     /// \details Divide returns <tt>a*b<sup>-1</sup>\%n</tt>.

0218     const Integer& Divide(const Integer &a, const Integer &b) const
0219         {return Multiply(a, MultiplicativeInverse(b));}
0220 
0221     /// \brief TODO

0222     /// \param x first element

0223     /// \param e1 first exponent

0224     /// \param y second element

0225     /// \param e2 second exponent

0226     /// \return TODO

0227     Integer CascadeExponentiate(const Integer &x, const Integer &e1, const Integer &y, const Integer &e2) const;
0228 
0229     /// \brief Exponentiates a base to multiple exponents in the ring

0230     /// \param results an array of Elements

0231     /// \param base the base to raise to the exponents

0232     /// \param exponents an array of exponents

0233     /// \param exponentsCount the number of exponents in the array

0234     /// \details SimultaneousExponentiate() raises the base to each exponent in the exponents array and stores the

0235     ///   result at the respective position in the results array.

0236     /// \details SimultaneousExponentiate() must be implemented in a derived class.

0237     /// \pre <tt>COUNTOF(results) == exponentsCount</tt>

0238     /// \pre <tt>COUNTOF(exponents) == exponentsCount</tt>

0239     void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
0240 
0241     /// \brief Provides the maximum bit size of an element in the ring

0242     /// \return maximum bit size of an element

0243     unsigned int MaxElementBitLength() const
0244         {return (m_modulus-1).BitCount();}
0245 
0246     /// \brief Provides the maximum byte size of an element in the ring

0247     /// \return maximum byte size of an element

0248     unsigned int MaxElementByteLength() const
0249         {return (m_modulus-1).ByteCount();}
0250 
0251     /// \brief Provides a random element in the ring

0252     /// \param rng RandomNumberGenerator used to generate material

0253     /// \param ignore_for_now unused

0254     /// \return a random element that is uniformly distributed

0255     /// \details RandomElement constructs a new element in the range <tt>[0,n-1]</tt>, inclusive.

0256     ///   The element's class must provide a constructor with the signature <tt>Element(RandomNumberGenerator rng,

0257     ///   Element min, Element max)</tt>.

0258     Element RandomElement(RandomNumberGenerator &rng, const RandomizationParameter &ignore_for_now = 0) const
0259         // left RandomizationParameter arg as ref in case RandomizationParameter becomes a more complicated struct

0260     {
0261         CRYPTOPP_UNUSED(ignore_for_now);
0262         return Element(rng, Integer::Zero(), m_modulus - Integer::One()) ;
0263     }
0264 
0265     /// \brief Compares two ModularArithmetic for equality

0266     /// \param rhs other ModularArithmetic

0267     /// \return true if this is equal to the other, false otherwise

0268     /// \details The operator tests for equality using <tt>this.m_modulus == rhs.m_modulus</tt>.

0269     bool operator==(const ModularArithmetic &rhs) const
0270         {return m_modulus == rhs.m_modulus;}
0271 
0272     static const RandomizationParameter DefaultRandomizationParameter;
0273 
0274 private:
0275     // TODO: Clang on OS X needs a real operator=.

0276     // Squash warning on missing assignment operator.

0277     // ModularArithmetic& operator=(const ModularArithmetic &ma);

0278 
0279 protected:
0280     Integer m_modulus;
0281     mutable Integer m_result, m_result1;
0282 };
0283 
0284 // const ModularArithmetic::RandomizationParameter ModularArithmetic::DefaultRandomizationParameter = 0 ;

0285 
0286 /// \brief Performs modular arithmetic in Montgomery representation for increased speed

0287 /// \details The Montgomery representation represents each congruence class <tt>[a]</tt> as

0288 ///   <tt>a*r\%n</tt>, where <tt>r</tt> is a convenient power of 2.

0289 /// \details <tt>const Element&</tt> returned by member functions are references to

0290 ///   internal data members. Since each object may have only one such data member for holding

0291 ///   results, the following code will produce incorrect results:

0292 ///   <pre>    abcd = group.Add(group.Add(a,b), group.Add(c,d));</pre>

0293 ///   But this should be fine:

0294 ///   <pre>    abcd = group.Add(a, group.Add(b, group.Add(c,d));</pre>

0295 class CRYPTOPP_DLL MontgomeryRepresentation : public ModularArithmetic
0296 {
0297 public:
0298     virtual ~MontgomeryRepresentation() {}
0299 
0300     /// \brief Construct a MontgomeryRepresentation

0301     /// \param modulus congruence class modulus

0302     /// \note The modulus must be odd.

0303     MontgomeryRepresentation(const Integer &modulus);
0304 
0305     /// \brief Clone a MontgomeryRepresentation

0306     /// \return pointer to a new MontgomeryRepresentation

0307     /// \details Clone effectively copy constructs a new MontgomeryRepresentation. The caller is

0308     ///   responsible for deleting the pointer returned from this method.

0309     virtual ModularArithmetic * Clone() const {return new MontgomeryRepresentation(*this);}
0310 
0311     bool IsMontgomeryRepresentation() const {return true;}
0312 
0313     Integer ConvertIn(const Integer &a) const
0314         {return (a<<(WORD_BITS*m_modulus.reg.size()))%m_modulus;}
0315 
0316     Integer ConvertOut(const Integer &a) const;
0317 
0318     const Integer& MultiplicativeIdentity() const
0319         {return m_result1 = Integer::Power2(WORD_BITS*m_modulus.reg.size())%m_modulus;}
0320 
0321     const Integer& Multiply(const Integer &a, const Integer &b) const;
0322 
0323     const Integer& Square(const Integer &a) const;
0324 
0325     const Integer& MultiplicativeInverse(const Integer &a) const;
0326 
0327     Integer CascadeExponentiate(const Integer &x, const Integer &e1, const Integer &y, const Integer &e2) const
0328         {return AbstractRing<Integer>::CascadeExponentiate(x, e1, y, e2);}
0329 
0330     void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const
0331         {AbstractRing<Integer>::SimultaneousExponentiate(results, base, exponents, exponentsCount);}
0332 
0333 private:
0334     Integer m_u;
0335     mutable IntegerSecBlock m_workspace;
0336 };
0337 
0338 NAMESPACE_END
0339 
0340 #if CRYPTOPP_MSC_VERSION
0341 # pragma warning(pop)
0342 #endif
0343 
0344 #endif