gf2n.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. // gf2n.h - originally written and placed in the public domain by Wei Dai
  2. /// \file gf2n.h
  3. /// \brief Classes and functions for schemes over GF(2^n)
  4. #ifndef CRYPTOPP_GF2N_H
  5. #define CRYPTOPP_GF2N_H
  6. #include "cryptlib.h"
  7. #include "secblock.h"
  8. #include "algebra.h"
  9. #include "misc.h"
  10. #include "asn.h"
  11. #include <iosfwd>
  12. #if CRYPTOPP_MSC_VERSION
  13. # pragma warning(push)
  14. # pragma warning(disable: 4231 4275)
  15. #endif
  16. NAMESPACE_BEGIN(CryptoPP)
  17. /// \brief Polynomial with Coefficients in GF(2)
  18. /*! \nosubgrouping */
  19. class CRYPTOPP_DLL PolynomialMod2
  20. {
  21. public:
  22. /// \name ENUMS, EXCEPTIONS, and TYPEDEFS
  23. //@{
  24. /// \brief Exception thrown when divide by zero is encountered
  25. class DivideByZero : public Exception
  26. {
  27. public:
  28. DivideByZero() : Exception(OTHER_ERROR, "PolynomialMod2: division by zero") {}
  29. };
  30. typedef unsigned int RandomizationParameter;
  31. //@}
  32. /// \name CREATORS
  33. //@{
  34. /// \brief Construct the zero polynomial
  35. PolynomialMod2();
  36. /// Copy construct a PolynomialMod2
  37. PolynomialMod2(const PolynomialMod2& t);
  38. /// \brief Construct a PolynomialMod2 from a word
  39. /// \details value should be encoded with the least significant bit as coefficient to x^0
  40. /// and most significant bit as coefficient to x^(WORD_BITS-1)
  41. /// bitLength denotes how much memory to allocate initially
  42. PolynomialMod2(word value, size_t bitLength=WORD_BITS);
  43. /// \brief Construct a PolynomialMod2 from big-endian byte array
  44. PolynomialMod2(const byte *encodedPoly, size_t byteCount)
  45. {Decode(encodedPoly, byteCount);}
  46. /// \brief Construct a PolynomialMod2 from big-endian form stored in a BufferedTransformation
  47. PolynomialMod2(BufferedTransformation &encodedPoly, size_t byteCount)
  48. {Decode(encodedPoly, byteCount);}
  49. /// \brief Create a uniformly distributed random polynomial
  50. /// \details Create a random polynomial uniformly distributed over all polynomials with degree less than bitcount
  51. PolynomialMod2(RandomNumberGenerator &rng, size_t bitcount)
  52. {Randomize(rng, bitcount);}
  53. /// \brief Provides x^i
  54. /// \return x^i
  55. static PolynomialMod2 CRYPTOPP_API Monomial(size_t i);
  56. /// \brief Provides x^t0 + x^t1 + x^t2
  57. /// \return x^t0 + x^t1 + x^t2
  58. static PolynomialMod2 CRYPTOPP_API Trinomial(size_t t0, size_t t1, size_t t2);
  59. /// \brief Provides x^t0 + x^t1 + x^t2 + x^t3 + x^t4
  60. /// \return x^t0 + x^t1 + x^t2 + x^t3 + x^t4
  61. static PolynomialMod2 CRYPTOPP_API Pentanomial(size_t t0, size_t t1, size_t t2, size_t t3, size_t t4);
  62. /// \brief Provides x^(n-1) + ... + x + 1
  63. /// \return x^(n-1) + ... + x + 1
  64. static PolynomialMod2 CRYPTOPP_API AllOnes(size_t n);
  65. /// \brief The Zero polinomial
  66. /// \return the zero polynomial
  67. static const PolynomialMod2 & CRYPTOPP_API Zero();
  68. /// \brief The One polinomial
  69. /// \return the one polynomial
  70. static const PolynomialMod2 & CRYPTOPP_API One();
  71. //@}
  72. /// \name ENCODE/DECODE
  73. //@{
  74. /// minimum number of bytes to encode this polynomial
  75. /*! MinEncodedSize of 0 is 1 */
  76. unsigned int MinEncodedSize() const {return STDMAX(1U, ByteCount());}
  77. /// encode in big-endian format
  78. /// \details if outputLen < MinEncodedSize, the most significant bytes will be dropped
  79. /// if outputLen > MinEncodedSize, the most significant bytes will be padded
  80. void Encode(byte *output, size_t outputLen) const;
  81. ///
  82. void Encode(BufferedTransformation &bt, size_t outputLen) const;
  83. ///
  84. void Decode(const byte *input, size_t inputLen);
  85. ///
  86. //* Precondition: bt.MaxRetrievable() >= inputLen
  87. void Decode(BufferedTransformation &bt, size_t inputLen);
  88. /// encode value as big-endian octet string
  89. void DEREncodeAsOctetString(BufferedTransformation &bt, size_t length) const;
  90. /// decode value as big-endian octet string
  91. void BERDecodeAsOctetString(BufferedTransformation &bt, size_t length);
  92. //@}
  93. /// \name ACCESSORS
  94. //@{
  95. /// number of significant bits = Degree() + 1
  96. unsigned int BitCount() const;
  97. /// number of significant bytes = ceiling(BitCount()/8)
  98. unsigned int ByteCount() const;
  99. /// number of significant words = ceiling(ByteCount()/sizeof(word))
  100. unsigned int WordCount() const;
  101. /// return the n-th bit, n=0 being the least significant bit
  102. bool GetBit(size_t n) const {return GetCoefficient(n)!=0;}
  103. /// return the n-th byte
  104. byte GetByte(size_t n) const;
  105. /// the zero polynomial will return a degree of -1
  106. signed int Degree() const {return (signed int)(BitCount()-1U);}
  107. /// degree + 1
  108. unsigned int CoefficientCount() const {return BitCount();}
  109. /// return coefficient for x^i
  110. int GetCoefficient(size_t i) const
  111. {return (i/WORD_BITS < reg.size()) ? int(reg[i/WORD_BITS] >> (i % WORD_BITS)) & 1 : 0;}
  112. /// return coefficient for x^i
  113. int operator[](unsigned int i) const {return GetCoefficient(i);}
  114. ///
  115. bool IsZero() const {return !*this;}
  116. ///
  117. bool Equals(const PolynomialMod2 &rhs) const;
  118. //@}
  119. /// \name MANIPULATORS
  120. //@{
  121. ///
  122. PolynomialMod2& operator=(const PolynomialMod2& t);
  123. ///
  124. PolynomialMod2& operator&=(const PolynomialMod2& t);
  125. ///
  126. PolynomialMod2& operator^=(const PolynomialMod2& t);
  127. ///
  128. PolynomialMod2& operator+=(const PolynomialMod2& t) {return *this ^= t;}
  129. ///
  130. PolynomialMod2& operator-=(const PolynomialMod2& t) {return *this ^= t;}
  131. ///
  132. PolynomialMod2& operator*=(const PolynomialMod2& t);
  133. ///
  134. PolynomialMod2& operator/=(const PolynomialMod2& t);
  135. ///
  136. PolynomialMod2& operator%=(const PolynomialMod2& t);
  137. ///
  138. PolynomialMod2& operator<<=(unsigned int);
  139. ///
  140. PolynomialMod2& operator>>=(unsigned int);
  141. ///
  142. void Randomize(RandomNumberGenerator &rng, size_t bitcount);
  143. ///
  144. void SetBit(size_t i, int value = 1);
  145. /// set the n-th byte to value
  146. void SetByte(size_t n, byte value);
  147. ///
  148. void SetCoefficient(size_t i, int value) {SetBit(i, value);}
  149. ///
  150. void swap(PolynomialMod2 &a) {reg.swap(a.reg);}
  151. //@}
  152. /// \name UNARY OPERATORS
  153. //@{
  154. ///
  155. bool operator!() const;
  156. ///
  157. PolynomialMod2 operator+() const {return *this;}
  158. ///
  159. PolynomialMod2 operator-() const {return *this;}
  160. //@}
  161. /// \name BINARY OPERATORS
  162. //@{
  163. ///
  164. PolynomialMod2 And(const PolynomialMod2 &b) const;
  165. ///
  166. PolynomialMod2 Xor(const PolynomialMod2 &b) const;
  167. ///
  168. PolynomialMod2 Plus(const PolynomialMod2 &b) const {return Xor(b);}
  169. ///
  170. PolynomialMod2 Minus(const PolynomialMod2 &b) const {return Xor(b);}
  171. ///
  172. PolynomialMod2 Times(const PolynomialMod2 &b) const;
  173. ///
  174. PolynomialMod2 DividedBy(const PolynomialMod2 &b) const;
  175. ///
  176. PolynomialMod2 Modulo(const PolynomialMod2 &b) const;
  177. ///
  178. PolynomialMod2 operator>>(unsigned int n) const;
  179. ///
  180. PolynomialMod2 operator<<(unsigned int n) const;
  181. //@}
  182. /// \name OTHER ARITHMETIC FUNCTIONS
  183. //@{
  184. /// sum modulo 2 of all coefficients
  185. unsigned int Parity() const;
  186. /// check for irreducibility
  187. bool IsIrreducible() const;
  188. /// is always zero since we're working modulo 2
  189. PolynomialMod2 Doubled() const {return Zero();}
  190. ///
  191. PolynomialMod2 Squared() const;
  192. /// only 1 is a unit
  193. bool IsUnit() const {return Equals(One());}
  194. /// return inverse if *this is a unit, otherwise return 0
  195. PolynomialMod2 MultiplicativeInverse() const {return IsUnit() ? One() : Zero();}
  196. /// greatest common divisor
  197. static PolynomialMod2 CRYPTOPP_API Gcd(const PolynomialMod2 &a, const PolynomialMod2 &n);
  198. /// calculate multiplicative inverse of *this mod n
  199. PolynomialMod2 InverseMod(const PolynomialMod2 &) const;
  200. /// calculate r and q such that (a == d*q + r) && (deg(r) < deg(d))
  201. static void CRYPTOPP_API Divide(PolynomialMod2 &r, PolynomialMod2 &q, const PolynomialMod2 &a, const PolynomialMod2 &d);
  202. //@}
  203. /// \name INPUT/OUTPUT
  204. //@{
  205. ///
  206. friend std::ostream& operator<<(std::ostream& out, const PolynomialMod2 &a);
  207. //@}
  208. private:
  209. friend class GF2NT;
  210. friend class GF2NT233;
  211. SecWordBlock reg;
  212. };
  213. ///
  214. inline bool operator==(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b)
  215. {return a.Equals(b);}
  216. ///
  217. inline bool operator!=(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b)
  218. {return !(a==b);}
  219. /// compares degree
  220. inline bool operator> (const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b)
  221. {return a.Degree() > b.Degree();}
  222. /// compares degree
  223. inline bool operator>=(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b)
  224. {return a.Degree() >= b.Degree();}
  225. /// compares degree
  226. inline bool operator< (const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b)
  227. {return a.Degree() < b.Degree();}
  228. /// compares degree
  229. inline bool operator<=(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b)
  230. {return a.Degree() <= b.Degree();}
  231. ///
  232. inline CryptoPP::PolynomialMod2 operator&(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.And(b);}
  233. ///
  234. inline CryptoPP::PolynomialMod2 operator^(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.Xor(b);}
  235. ///
  236. inline CryptoPP::PolynomialMod2 operator+(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.Plus(b);}
  237. ///
  238. inline CryptoPP::PolynomialMod2 operator-(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.Minus(b);}
  239. ///
  240. inline CryptoPP::PolynomialMod2 operator*(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.Times(b);}
  241. ///
  242. inline CryptoPP::PolynomialMod2 operator/(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.DividedBy(b);}
  243. ///
  244. inline CryptoPP::PolynomialMod2 operator%(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.Modulo(b);}
  245. // CodeWarrior 8 workaround: put these template instantiations after overloaded operator declarations,
  246. // but before the use of QuotientRing<EuclideanDomainOf<PolynomialMod2> > for VC .NET 2003
  247. CRYPTOPP_DLL_TEMPLATE_CLASS AbstractGroup<PolynomialMod2>;
  248. CRYPTOPP_DLL_TEMPLATE_CLASS AbstractRing<PolynomialMod2>;
  249. CRYPTOPP_DLL_TEMPLATE_CLASS AbstractEuclideanDomain<PolynomialMod2>;
  250. CRYPTOPP_DLL_TEMPLATE_CLASS EuclideanDomainOf<PolynomialMod2>;
  251. CRYPTOPP_DLL_TEMPLATE_CLASS QuotientRing<EuclideanDomainOf<PolynomialMod2> >;
  252. /// \brief GF(2^n) with Polynomial Basis
  253. class CRYPTOPP_DLL GF2NP : public QuotientRing<EuclideanDomainOf<PolynomialMod2> >
  254. {
  255. public:
  256. GF2NP(const PolynomialMod2 &modulus);
  257. virtual GF2NP * Clone() const {return new GF2NP(*this);}
  258. virtual void DEREncode(BufferedTransformation &bt) const
  259. {CRYPTOPP_UNUSED(bt); CRYPTOPP_ASSERT(false);} // no ASN.1 syntax yet for general polynomial basis
  260. void DEREncodeElement(BufferedTransformation &out, const Element &a) const;
  261. void BERDecodeElement(BufferedTransformation &in, Element &a) const;
  262. bool Equal(const Element &a, const Element &b) const
  263. {CRYPTOPP_ASSERT(a.Degree() < m_modulus.Degree() && b.Degree() < m_modulus.Degree()); return a.Equals(b);}
  264. bool IsUnit(const Element &a) const
  265. {CRYPTOPP_ASSERT(a.Degree() < m_modulus.Degree()); return !!a;}
  266. unsigned int MaxElementBitLength() const
  267. {return m;}
  268. unsigned int MaxElementByteLength() const
  269. {return (unsigned int)BitsToBytes(MaxElementBitLength());}
  270. Element SquareRoot(const Element &a) const;
  271. Element HalfTrace(const Element &a) const;
  272. // returns z such that z^2 + z == a
  273. Element SolveQuadraticEquation(const Element &a) const;
  274. protected:
  275. unsigned int m;
  276. };
  277. /// \brief GF(2^n) with Trinomial Basis
  278. class CRYPTOPP_DLL GF2NT : public GF2NP
  279. {
  280. public:
  281. // polynomial modulus = x^t0 + x^t1 + x^t2, t0 > t1 > t2
  282. GF2NT(unsigned int t0, unsigned int t1, unsigned int t2);
  283. GF2NP * Clone() const {return new GF2NT(*this);}
  284. void DEREncode(BufferedTransformation &bt) const;
  285. const Element& Multiply(const Element &a, const Element &b) const;
  286. const Element& Square(const Element &a) const
  287. {return Reduced(a.Squared());}
  288. const Element& MultiplicativeInverse(const Element &a) const;
  289. protected:
  290. const Element& Reduced(const Element &a) const;
  291. unsigned int t0, t1;
  292. mutable PolynomialMod2 result;
  293. };
  294. /// \brief GF(2^n) for b233 and k233
  295. /// \details GF2NT233 is a specialization of GF2NT that provides Multiply()
  296. /// and Square() operations when carryless multiplies is available.
  297. class CRYPTOPP_DLL GF2NT233 : public GF2NT
  298. {
  299. public:
  300. // polynomial modulus = x^t0 + x^t1 + x^t2, t0 > t1 > t2
  301. GF2NT233(unsigned int t0, unsigned int t1, unsigned int t2);
  302. GF2NP * Clone() const {return new GF2NT233(*this);}
  303. const Element& Multiply(const Element &a, const Element &b) const;
  304. const Element& Square(const Element &a) const;
  305. };
  306. /// \brief GF(2^n) with Pentanomial Basis
  307. class CRYPTOPP_DLL GF2NPP : public GF2NP
  308. {
  309. public:
  310. // polynomial modulus = x^t0 + x^t1 + x^t2 + x^t3 + x^t4, t0 > t1 > t2 > t3 > t4
  311. GF2NPP(unsigned int t0, unsigned int t1, unsigned int t2, unsigned int t3, unsigned int t4)
  312. : GF2NP(PolynomialMod2::Pentanomial(t0, t1, t2, t3, t4)), t1(t1), t2(t2), t3(t3) {}
  313. GF2NP * Clone() const {return new GF2NPP(*this);}
  314. void DEREncode(BufferedTransformation &bt) const;
  315. private:
  316. unsigned int t1, t2, t3;
  317. };
  318. // construct new GF2NP from the ASN.1 sequence Characteristic-two
  319. CRYPTOPP_DLL GF2NP * CRYPTOPP_API BERDecodeGF2NP(BufferedTransformation &bt);
  320. NAMESPACE_END
  321. #ifndef __BORLANDC__
  322. NAMESPACE_BEGIN(std)
  323. template<> inline void swap(CryptoPP::PolynomialMod2 &a, CryptoPP::PolynomialMod2 &b)
  324. {
  325. a.swap(b);
  326. }
  327. NAMESPACE_END
  328. #endif
  329. #if CRYPTOPP_MSC_VERSION
  330. # pragma warning(pop)
  331. #endif
  332. #endif