Coverage Report

Created: 2024-11-21 07:03

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