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 ¶ms) |
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 ¶ms) : 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 |