Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:54:56

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

0002 
0003 /// \file dh.h

0004 /// \brief Classes for Diffie-Hellman key exchange

0005 
0006 #ifndef CRYPTOPP_DH_H
0007 #define CRYPTOPP_DH_H
0008 
0009 #include "cryptlib.h"
0010 #include "gfpcrypt.h"
0011 #include "algebra.h"
0012 
0013 NAMESPACE_BEGIN(CryptoPP)
0014 
0015 /// \brief Diffie-Hellman domain

0016 /// \tparam GROUP_PARAMETERS group parameters

0017 /// \tparam COFACTOR_OPTION cofactor multiplication option

0018 /// \details A Diffie-Hellman domain is a set of parameters that must be shared

0019 ///   by two parties in a key agreement protocol, along with the algorithms

0020 ///   for generating key pairs and deriving agreed values.

0021 /// \details For COFACTOR_OPTION, see CofactorMultiplicationOption.

0022 /// \sa DL_SimpleKeyAgreementDomainBase

0023 /// \since Crypto++ 1.0

0024 template <class GROUP_PARAMETERS, class COFACTOR_OPTION = typename GROUP_PARAMETERS::DefaultCofactorOption>
0025 class DH_Domain : public DL_SimpleKeyAgreementDomainBase<typename GROUP_PARAMETERS::Element>
0026 {
0027     typedef DL_SimpleKeyAgreementDomainBase<typename GROUP_PARAMETERS::Element> Base;
0028 
0029 public:
0030     typedef GROUP_PARAMETERS GroupParameters;
0031     typedef typename GroupParameters::Element Element;
0032     typedef DL_KeyAgreementAlgorithm_DH<Element, COFACTOR_OPTION> DH_Algorithm;
0033     typedef DH_Domain<GROUP_PARAMETERS, COFACTOR_OPTION> Domain;
0034 
0035     virtual ~DH_Domain() {}
0036 
0037     /// \brief Construct a Diffie-Hellman domain

0038     DH_Domain() {}
0039 
0040     /// \brief Construct a Diffie-Hellman domain

0041     /// \param params group parameters and options

0042     DH_Domain(const GroupParameters &params)
0043         : m_groupParameters(params) {}
0044 
0045     /// \brief Construct a Diffie-Hellman domain

0046     /// \param bt BufferedTransformation with group parameters and options

0047     DH_Domain(BufferedTransformation &bt)
0048         {m_groupParameters.BERDecode(bt);}
0049 
0050     /// \brief Create a Diffie-Hellman domain

0051     /// \tparam T2 template parameter used as a constructor parameter

0052     /// \param v1 RandomNumberGenerator derived class

0053     /// \param v2 second parameter

0054     /// \details v1 and v2 are passed directly to the GROUP_PARAMETERS object.

0055     template <class T2>
0056     DH_Domain(RandomNumberGenerator &v1, const T2 &v2)
0057         {m_groupParameters.Initialize(v1, v2);}
0058 
0059     /// \brief Create a Diffie-Hellman domain

0060     /// \tparam T2 template parameter used as a constructor parameter

0061     /// \tparam T3 template parameter used as a constructor parameter

0062     /// \param v1 RandomNumberGenerator derived class

0063     /// \param v2 second parameter

0064     /// \param v3 third parameter

0065     /// \details v1, v2 and v3 are passed directly to the GROUP_PARAMETERS object.

0066     template <class T2, class T3>
0067     DH_Domain(RandomNumberGenerator &v1, const T2 &v2, const T3 &v3)
0068         {m_groupParameters.Initialize(v1, v2, v3);}
0069 
0070     /// \brief Create a Diffie-Hellman domain

0071     /// \tparam T2 template parameter used as a constructor parameter

0072     /// \tparam T3 template parameter used as a constructor parameter

0073     /// \tparam T4 template parameter used as a constructor parameter

0074     /// \param v1 RandomNumberGenerator derived class

0075     /// \param v2 second parameter

0076     /// \param v3 third parameter

0077     /// \param v4 fourth parameter

0078     /// \details v1, v2, v3 and v4 are passed directly to the GROUP_PARAMETERS object.

0079     template <class T2, class T3, class T4>
0080     DH_Domain(RandomNumberGenerator &v1, const T2 &v2, const T3 &v3, const T4 &v4)
0081         {m_groupParameters.Initialize(v1, v2, v3, v4);}
0082 
0083     /// \brief Construct a Diffie-Hellman domain

0084     /// \tparam T1 template parameter used as a constructor parameter

0085     /// \tparam T2 template parameter used as a constructor parameter

0086     /// \param v1 first parameter

0087     /// \param v2 second parameter

0088     /// \details v1 and v2 are passed directly to the GROUP_PARAMETERS object.

0089     template <class T1, class T2>
0090     DH_Domain(const T1 &v1, const T2 &v2)
0091         {m_groupParameters.Initialize(v1, v2);}
0092 
0093     /// \brief Construct a Diffie-Hellman domain

0094     /// \tparam T1 template parameter used as a constructor parameter

0095     /// \tparam T2 template parameter used as a constructor parameter

0096     /// \tparam T3 template parameter used as a constructor parameter

0097     /// \param v1 first parameter

0098     /// \param v2 second parameter

0099     /// \param v3 third parameter

0100     /// \details v1, v2 and v3 are passed directly to the GROUP_PARAMETERS object.

0101     template <class T1, class T2, class T3>
0102     DH_Domain(const T1 &v1, const T2 &v2, const T3 &v3)
0103         {m_groupParameters.Initialize(v1, v2, v3);}
0104 
0105     /// \brief Construct a Diffie-Hellman domain

0106     /// \tparam T1 template parameter used as a constructor parameter

0107     /// \tparam T2 template parameter used as a constructor parameter

0108     /// \tparam T3 template parameter used as a constructor parameter

0109     /// \tparam T4 template parameter used as a constructor parameter

0110     /// \param v1 first parameter

0111     /// \param v2 second parameter

0112     /// \param v3 third parameter

0113     /// \param v4 fourth parameter

0114     /// \details v1, v2, v3 and v4 are passed directly to the GROUP_PARAMETERS object.

0115     template <class T1, class T2, class T3, class T4>
0116     DH_Domain(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4)
0117         {m_groupParameters.Initialize(v1, v2, v3, v4);}
0118 
0119     /// \brief Retrieves the group parameters for this domain

0120     /// \return the group parameters for this domain as a const reference

0121     const GroupParameters & GetGroupParameters() const {return m_groupParameters;}
0122     /// \brief Retrieves the group parameters for this domain

0123     /// \return the group parameters for this domain as a non-const reference

0124     GroupParameters & AccessGroupParameters() {return m_groupParameters;}
0125 
0126     /// \brief Generate a public key from a private key in this domain

0127     /// \param rng RandomNumberGenerator derived class

0128     /// \param privateKey byte buffer with the previously generated private key

0129     /// \param publicKey byte buffer for the generated public key in this domain

0130     /// \details If using a FIPS 140-2 validated library on Windows, then this class will perform

0131     ///   a self test to ensure the key pair is pairwise consistent. Non-FIPS and non-Windows

0132     ///   builds of the library do not provide FIPS validated cryptography, so the code should be

0133     ///   removed by the optimizer.

0134     /// \pre <tt>COUNTOF(publicKey) == PublicKeyLength()</tt>

0135     void GeneratePublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
0136     {
0137         Base::GeneratePublicKey(rng, privateKey, publicKey);
0138 
0139         if (FIPS_140_2_ComplianceEnabled())
0140         {
0141             SecByteBlock privateKey2(this->PrivateKeyLength());
0142             this->GeneratePrivateKey(rng, privateKey2);
0143 
0144             SecByteBlock publicKey2(this->PublicKeyLength());
0145             Base::GeneratePublicKey(rng, privateKey2, publicKey2);
0146 
0147             SecByteBlock agreedValue(this->AgreedValueLength()), agreedValue2(this->AgreedValueLength());
0148             bool agreed1 = this->Agree(agreedValue, privateKey, publicKey2);
0149             bool agreed2 = this->Agree(agreedValue2, privateKey2, publicKey);
0150 
0151             if (!agreed1 || !agreed2 || agreedValue != agreedValue2)
0152                 throw SelfTestFailure(this->AlgorithmName() + ": pairwise consistency test failed");
0153         }
0154     }
0155 
0156     static std::string CRYPTOPP_API StaticAlgorithmName()
0157         {return GroupParameters::StaticAlgorithmNamePrefix() + DH_Algorithm::StaticAlgorithmName();}
0158     std::string AlgorithmName() const {return StaticAlgorithmName();}
0159 
0160 private:
0161     const DL_KeyAgreementAlgorithm<Element> & GetKeyAgreementAlgorithm() const
0162         {return Singleton<DH_Algorithm>().Ref();}
0163     DL_GroupParameters<Element> & AccessAbstractGroupParameters()
0164         {return m_groupParameters;}
0165 
0166     GroupParameters m_groupParameters;
0167 };
0168 
0169 CRYPTOPP_DLL_TEMPLATE_CLASS DH_Domain<DL_GroupParameters_GFP_DefaultSafePrime>;
0170 
0171 /// \brief Diffie-Hellman in GF(p)

0172 /// \details DH() class is a typedef of DH_Domain(). The documentation that follows

0173 ///   does not exist. Rather the documentation was created in response to <a href="https://github.com/weidai11/cryptopp/issues/328">Issue

0174 ///   328, Diffie-Hellman example code not compiling</a>.

0175 /// \details Generally speaking, a DH() object is ephemeral and is intended to execute one instance of the Diffie-Hellman protocol. The

0176 ///   private and public key parts are not intended to be set or persisted. Rather, a new set of domain parameters are generated each

0177 ///   time an object is created.

0178 /// \details Once a DH() object is created, once can retrieve the ephemeral public key for the other party with code similar to the

0179 ///   following.

0180 /// <pre>   AutoSeededRandomPool prng;

0181 ///   Integer p, q, g;

0182 ///   PrimeAndGenerator pg;

0183 ///

0184 ///   pg.Generate(1, prng, 512, 511);

0185 ///   p = pg.Prime();

0186 ///   q = pg.SubPrime();

0187 ///   g = pg.Generator();

0188 ///

0189 ///   DH dh(p, q, g);

0190 ///   SecByteBlock t1(dh.PrivateKeyLength()), t2(dh.PublicKeyLength());

0191 ///   dh.GenerateKeyPair(prng, t1, t2);

0192 ///   Integer k1(t1, t1.size()), k2(t2, t2.size());

0193 ///

0194 ///   cout << "Private key:\n";

0195 ///   cout << hex << k1 << endl;

0196 ///

0197 ///   cout << "Public key:\n";

0198 ///   cout << hex << k2 << endl;</pre>

0199 ///

0200 /// \details Output of the program above will be similar to the following.

0201 /// <pre>   $ ./cryptest.exe

0202 ///   Private key:

0203 ///   72b45a42371545e9d4880f48589aefh

0204 ///   Public key:

0205 ///   45fdb13f97b1840626f0250cec1dba4a23b894100b51fb5d2dd13693d789948f8bfc88f9200014b2

0206 ///   ba8dd8a6debc471c69ef1e2326c61184a2eca88ec866346bh</pre>

0207 /// \sa <a href="http://www.cryptopp.com/wiki/Diffie-Hellman">Diffie-Hellman on the Crypto++ wiki</a> and

0208 ///   <a href="http://www.weidai.com/scan-mirror/ka.html#DH">Diffie-Hellman</a> in GF(p) with key validation

0209 /// \since Crypto++ 1.0

0210 #if defined(CRYPTOPP_DOXYGEN_PROCESSING)
0211 struct DH : public DH_Domain<DL_GroupParameters_GFP_DefaultSafePrime>
0212 {
0213     typedef DH_Domain<DL_GroupParameters_GFP_DefaultSafePrime> GroupParameters;
0214     typedef GroupParameters::Element Element;
0215 
0216     virtual ~DH() {}
0217 
0218     /// \brief Create an uninitialized Diffie-Hellman object

0219     DH() : DH_Domain() {}
0220 
0221     /// \brief Initialize a Diffie-Hellman object

0222     /// \param bt BufferedTransformation with group parameters and options

0223     DH(BufferedTransformation &bt) : DH_Domain(bt) {}
0224 
0225     /// \brief Initialize a Diffie-Hellman object

0226     /// \param params group parameters and options

0227     DH(const GroupParameters &params) : DH_Domain(params) {}
0228 
0229     /// \brief Create a Diffie-Hellman object

0230     /// \param rng a RandomNumberGenerator derived class

0231     /// \param modulusBits the size of the modulus, in bits

0232     /// \details This function overload of Initialize() creates a new Diffie-Hellman object because it

0233     ///   takes a RandomNumberGenerator() as a parameter.

0234     DH(RandomNumberGenerator &rng, unsigned int modulusBits) : DH_Domain(rng, modulusBits) {}
0235 
0236     /// \brief Initialize a Diffie-Hellman object

0237     /// \param p the modulus

0238     /// \param g the generator

0239     DH(const Integer &p, const Integer &g) : DH_Domain(p, g) {}
0240 
0241     /// \brief Initialize a Diffie-Hellman object

0242     /// \param p the modulus

0243     /// \param q the subgroup order

0244     /// \param g the generator

0245     DH(const Integer &p, const Integer &q, const Integer &g) : DH_Domain(p, q, g) {}
0246 
0247     /// \brief Creates a Diffie-Hellman object

0248     /// \param rng a RandomNumberGenerator derived class

0249     /// \param modulusBits the size of the modulus, in bits

0250     /// \details This function overload of Initialize() creates a new Diffie-Hellman object because it

0251     ///   takes a RandomNumberGenerator() as a parameter.

0252     void Initialize(RandomNumberGenerator &rng, unsigned int modulusBits)
0253         {AccessGroupParameters().Initialize(rng, modulusBits);}
0254 
0255     /// \brief Initialize a Diffie-Hellman object

0256     /// \param p the modulus

0257     /// \param g the generator

0258     void Initialize(const Integer &p, const Integer &g)
0259         {AccessGroupParameters().Initialize(p, g);}
0260 
0261     /// \brief Initialize a Diffie-Hellman object

0262     /// \param p the modulus

0263     /// \param q the subgroup order

0264     /// \param g the generator

0265     void Initialize(const Integer &p, const Integer &q, const Integer &g)
0266         {AccessGroupParameters().Initialize(p, q, g);}
0267 };
0268 #else
0269 // The real DH class is a typedef.

0270 typedef DH_Domain<DL_GroupParameters_GFP_DefaultSafePrime> DH;
0271 #endif
0272 
0273 NAMESPACE_END
0274 
0275 #endif