dh.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. // dh.h - originally written and placed in the public domain by Wei Dai
  2. /// \file dh.h
  3. /// \brief Classes for Diffie-Hellman key exchange
  4. #ifndef CRYPTOPP_DH_H
  5. #define CRYPTOPP_DH_H
  6. #include "cryptlib.h"
  7. #include "gfpcrypt.h"
  8. #include "algebra.h"
  9. NAMESPACE_BEGIN(CryptoPP)
  10. /// \brief Diffie-Hellman domain
  11. /// \tparam GROUP_PARAMETERS group parameters
  12. /// \tparam COFACTOR_OPTION cofactor multiplication option
  13. /// \details A Diffie-Hellman domain is a set of parameters that must be shared
  14. /// by two parties in a key agreement protocol, along with the algorithms
  15. /// for generating key pairs and deriving agreed values.
  16. /// \details For COFACTOR_OPTION, see CofactorMultiplicationOption.
  17. /// \sa DL_SimpleKeyAgreementDomainBase
  18. /// \since Crypto++ 1.0
  19. template <class GROUP_PARAMETERS, class COFACTOR_OPTION = typename GROUP_PARAMETERS::DefaultCofactorOption>
  20. class DH_Domain : public DL_SimpleKeyAgreementDomainBase<typename GROUP_PARAMETERS::Element>
  21. {
  22. typedef DL_SimpleKeyAgreementDomainBase<typename GROUP_PARAMETERS::Element> Base;
  23. public:
  24. typedef GROUP_PARAMETERS GroupParameters;
  25. typedef typename GroupParameters::Element Element;
  26. typedef DL_KeyAgreementAlgorithm_DH<Element, COFACTOR_OPTION> DH_Algorithm;
  27. typedef DH_Domain<GROUP_PARAMETERS, COFACTOR_OPTION> Domain;
  28. virtual ~DH_Domain() {}
  29. /// \brief Construct a Diffie-Hellman domain
  30. DH_Domain() {}
  31. /// \brief Construct a Diffie-Hellman domain
  32. /// \param params group parameters and options
  33. DH_Domain(const GroupParameters &params)
  34. : m_groupParameters(params) {}
  35. /// \brief Construct a Diffie-Hellman domain
  36. /// \param bt BufferedTransformation with group parameters and options
  37. DH_Domain(BufferedTransformation &bt)
  38. {m_groupParameters.BERDecode(bt);}
  39. /// \brief Create a Diffie-Hellman domain
  40. /// \tparam T2 template parameter used as a constructor parameter
  41. /// \param v1 RandomNumberGenerator derived class
  42. /// \param v2 second parameter
  43. /// \details v1 and v2 are passed directly to the GROUP_PARAMETERS object.
  44. template <class T2>
  45. DH_Domain(RandomNumberGenerator &v1, const T2 &v2)
  46. {m_groupParameters.Initialize(v1, v2);}
  47. /// \brief Create a Diffie-Hellman domain
  48. /// \tparam T2 template parameter used as a constructor parameter
  49. /// \tparam T3 template parameter used as a constructor parameter
  50. /// \param v1 RandomNumberGenerator derived class
  51. /// \param v2 second parameter
  52. /// \param v3 third parameter
  53. /// \details v1, v2 and v3 are passed directly to the GROUP_PARAMETERS object.
  54. template <class T2, class T3>
  55. DH_Domain(RandomNumberGenerator &v1, const T2 &v2, const T3 &v3)
  56. {m_groupParameters.Initialize(v1, v2, v3);}
  57. /// \brief Create a Diffie-Hellman domain
  58. /// \tparam T2 template parameter used as a constructor parameter
  59. /// \tparam T3 template parameter used as a constructor parameter
  60. /// \tparam T4 template parameter used as a constructor parameter
  61. /// \param v1 RandomNumberGenerator derived class
  62. /// \param v2 second parameter
  63. /// \param v3 third parameter
  64. /// \param v4 fourth parameter
  65. /// \details v1, v2, v3 and v4 are passed directly to the GROUP_PARAMETERS object.
  66. template <class T2, class T3, class T4>
  67. DH_Domain(RandomNumberGenerator &v1, const T2 &v2, const T3 &v3, const T4 &v4)
  68. {m_groupParameters.Initialize(v1, v2, v3, v4);}
  69. /// \brief Construct a Diffie-Hellman domain
  70. /// \tparam T1 template parameter used as a constructor parameter
  71. /// \tparam T2 template parameter used as a constructor parameter
  72. /// \param v1 first parameter
  73. /// \param v2 second parameter
  74. /// \details v1 and v2 are passed directly to the GROUP_PARAMETERS object.
  75. template <class T1, class T2>
  76. DH_Domain(const T1 &v1, const T2 &v2)
  77. {m_groupParameters.Initialize(v1, v2);}
  78. /// \brief Construct a Diffie-Hellman domain
  79. /// \tparam T1 template parameter used as a constructor parameter
  80. /// \tparam T2 template parameter used as a constructor parameter
  81. /// \tparam T3 template parameter used as a constructor parameter
  82. /// \param v1 first parameter
  83. /// \param v2 second parameter
  84. /// \param v3 third parameter
  85. /// \details v1, v2 and v3 are passed directly to the GROUP_PARAMETERS object.
  86. template <class T1, class T2, class T3>
  87. DH_Domain(const T1 &v1, const T2 &v2, const T3 &v3)
  88. {m_groupParameters.Initialize(v1, v2, v3);}
  89. /// \brief Construct a Diffie-Hellman domain
  90. /// \tparam T1 template parameter used as a constructor parameter
  91. /// \tparam T2 template parameter used as a constructor parameter
  92. /// \tparam T3 template parameter used as a constructor parameter
  93. /// \tparam T4 template parameter used as a constructor parameter
  94. /// \param v1 first parameter
  95. /// \param v2 second parameter
  96. /// \param v3 third parameter
  97. /// \param v4 fourth parameter
  98. /// \details v1, v2, v3 and v4 are passed directly to the GROUP_PARAMETERS object.
  99. template <class T1, class T2, class T3, class T4>
  100. DH_Domain(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4)
  101. {m_groupParameters.Initialize(v1, v2, v3, v4);}
  102. /// \brief Retrieves the group parameters for this domain
  103. /// \return the group parameters for this domain as a const reference
  104. const GroupParameters & GetGroupParameters() const {return m_groupParameters;}
  105. /// \brief Retrieves the group parameters for this domain
  106. /// \return the group parameters for this domain as a non-const reference
  107. GroupParameters & AccessGroupParameters() {return m_groupParameters;}
  108. /// \brief Generate a public key from a private key in this domain
  109. /// \param rng RandomNumberGenerator derived class
  110. /// \param privateKey byte buffer with the previously generated private key
  111. /// \param publicKey byte buffer for the generated public key in this domain
  112. /// \details If using a FIPS 140-2 validated library on Windows, then this class will perform
  113. /// a self test to ensure the key pair is pairwise consistent. Non-FIPS and non-Windows
  114. /// builds of the library do not provide FIPS validated cryptography, so the code should be
  115. /// removed by the optimizer.
  116. /// \pre <tt>COUNTOF(publicKey) == PublicKeyLength()</tt>
  117. void GeneratePublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
  118. {
  119. Base::GeneratePublicKey(rng, privateKey, publicKey);
  120. if (FIPS_140_2_ComplianceEnabled())
  121. {
  122. SecByteBlock privateKey2(this->PrivateKeyLength());
  123. this->GeneratePrivateKey(rng, privateKey2);
  124. SecByteBlock publicKey2(this->PublicKeyLength());
  125. Base::GeneratePublicKey(rng, privateKey2, publicKey2);
  126. SecByteBlock agreedValue(this->AgreedValueLength()), agreedValue2(this->AgreedValueLength());
  127. bool agreed1 = this->Agree(agreedValue, privateKey, publicKey2);
  128. bool agreed2 = this->Agree(agreedValue2, privateKey2, publicKey);
  129. if (!agreed1 || !agreed2 || agreedValue != agreedValue2)
  130. throw SelfTestFailure(this->AlgorithmName() + ": pairwise consistency test failed");
  131. }
  132. }
  133. static std::string CRYPTOPP_API StaticAlgorithmName()
  134. {return GroupParameters::StaticAlgorithmNamePrefix() + DH_Algorithm::StaticAlgorithmName();}
  135. std::string AlgorithmName() const {return StaticAlgorithmName();}
  136. private:
  137. const DL_KeyAgreementAlgorithm<Element> & GetKeyAgreementAlgorithm() const
  138. {return Singleton<DH_Algorithm>().Ref();}
  139. DL_GroupParameters<Element> & AccessAbstractGroupParameters()
  140. {return m_groupParameters;}
  141. GroupParameters m_groupParameters;
  142. };
  143. CRYPTOPP_DLL_TEMPLATE_CLASS DH_Domain<DL_GroupParameters_GFP_DefaultSafePrime>;
  144. /// \brief Diffie-Hellman in GF(p)
  145. /// \details DH() class is a typedef of DH_Domain(). The documentation that follows
  146. /// does not exist. Rather the documentation was created in response to <a href="https://github.com/weidai11/cryptopp/issues/328">Issue
  147. /// 328, Diffie-Hellman example code not compiling</a>.
  148. /// \details Generally speaking, a DH() object is ephemeral and is intended to execute one instance of the Diffie-Hellman protocol. The
  149. /// private and public key parts are not intended to be set or persisted. Rather, a new set of domain parameters are generated each
  150. /// time an object is created.
  151. /// \details Once a DH() object is created, once can retrieve the ephemeral public key for the other party with code similar to the
  152. /// following.
  153. /// <pre> AutoSeededRandomPool prng;
  154. /// Integer p, q, g;
  155. /// PrimeAndGenerator pg;
  156. ///
  157. /// pg.Generate(1, prng, 512, 511);
  158. /// p = pg.Prime();
  159. /// q = pg.SubPrime();
  160. /// g = pg.Generator();
  161. ///
  162. /// DH dh(p, q, g);
  163. /// SecByteBlock t1(dh.PrivateKeyLength()), t2(dh.PublicKeyLength());
  164. /// dh.GenerateKeyPair(prng, t1, t2);
  165. /// Integer k1(t1, t1.size()), k2(t2, t2.size());
  166. ///
  167. /// cout << "Private key:\n";
  168. /// cout << hex << k1 << endl;
  169. ///
  170. /// cout << "Public key:\n";
  171. /// cout << hex << k2 << endl;</pre>
  172. ///
  173. /// \details Output of the program above will be similar to the following.
  174. /// <pre> $ ./cryptest.exe
  175. /// Private key:
  176. /// 72b45a42371545e9d4880f48589aefh
  177. /// Public key:
  178. /// 45fdb13f97b1840626f0250cec1dba4a23b894100b51fb5d2dd13693d789948f8bfc88f9200014b2
  179. /// ba8dd8a6debc471c69ef1e2326c61184a2eca88ec866346bh</pre>
  180. /// \sa <a href="http://www.cryptopp.com/wiki/Diffie-Hellman">Diffie-Hellman on the Crypto++ wiki</a> and
  181. /// <a href="http://www.weidai.com/scan-mirror/ka.html#DH">Diffie-Hellman</a> in GF(p) with key validation
  182. /// \since Crypto++ 1.0
  183. #if defined(CRYPTOPP_DOXYGEN_PROCESSING)
  184. struct DH : public DH_Domain<DL_GroupParameters_GFP_DefaultSafePrime>
  185. {
  186. typedef DH_Domain<DL_GroupParameters_GFP_DefaultSafePrime> GroupParameters;
  187. typedef GroupParameters::Element Element;
  188. virtual ~DH() {}
  189. /// \brief Create an uninitialized Diffie-Hellman object
  190. DH() : DH_Domain() {}
  191. /// \brief Initialize a Diffie-Hellman object
  192. /// \param bt BufferedTransformation with group parameters and options
  193. DH(BufferedTransformation &bt) : DH_Domain(bt) {}
  194. /// \brief Initialize a Diffie-Hellman object
  195. /// \param params group parameters and options
  196. DH(const GroupParameters &params) : DH_Domain(params) {}
  197. /// \brief Create a Diffie-Hellman object
  198. /// \param rng a RandomNumberGenerator derived class
  199. /// \param modulusBits the size of the modulus, in bits
  200. /// \details This function overload of Initialize() creates a new Diffie-Hellman object because it
  201. /// takes a RandomNumberGenerator() as a parameter.
  202. DH(RandomNumberGenerator &rng, unsigned int modulusBits) : DH_Domain(rng, modulusBits) {}
  203. /// \brief Initialize a Diffie-Hellman object
  204. /// \param p the modulus
  205. /// \param g the generator
  206. DH(const Integer &p, const Integer &g) : DH_Domain(p, g) {}
  207. /// \brief Initialize a Diffie-Hellman object
  208. /// \param p the modulus
  209. /// \param q the subgroup order
  210. /// \param g the generator
  211. DH(const Integer &p, const Integer &q, const Integer &g) : DH_Domain(p, q, g) {}
  212. /// \brief Creates a Diffie-Hellman object
  213. /// \param rng a RandomNumberGenerator derived class
  214. /// \param modulusBits the size of the modulus, in bits
  215. /// \details This function overload of Initialize() creates a new Diffie-Hellman object because it
  216. /// takes a RandomNumberGenerator() as a parameter.
  217. void Initialize(RandomNumberGenerator &rng, unsigned int modulusBits)
  218. {AccessGroupParameters().Initialize(rng, modulusBits);}
  219. /// \brief Initialize a Diffie-Hellman object
  220. /// \param p the modulus
  221. /// \param g the generator
  222. void Initialize(const Integer &p, const Integer &g)
  223. {AccessGroupParameters().Initialize(p, g);}
  224. /// \brief Initialize a Diffie-Hellman object
  225. /// \param p the modulus
  226. /// \param q the subgroup order
  227. /// \param g the generator
  228. void Initialize(const Integer &p, const Integer &q, const Integer &g)
  229. {AccessGroupParameters().Initialize(p, q, g);}
  230. };
  231. #else
  232. // The real DH class is a typedef.
  233. typedef DH_Domain<DL_GroupParameters_GFP_DefaultSafePrime> DH;
  234. #endif
  235. NAMESPACE_END
  236. #endif