mqv.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. // mqv.h - originally written and placed in the public domain by Wei Dai
  2. /// \file mqv.h
  3. /// \brief Classes for Menezes–Qu–Vanstone (MQV) key agreement
  4. /// \since Crypto++ 3.0
  5. #ifndef CRYPTOPP_MQV_H
  6. #define CRYPTOPP_MQV_H
  7. #include "cryptlib.h"
  8. #include "gfpcrypt.h"
  9. #include "modarith.h"
  10. #include "integer.h"
  11. #include "algebra.h"
  12. #include "misc.h"
  13. NAMESPACE_BEGIN(CryptoPP)
  14. /// \brief MQV domain for performing authenticated key agreement
  15. /// \tparam GROUP_PARAMETERS doamin parameters
  16. /// \tparam COFACTOR_OPTION cofactor option
  17. /// \details GROUP_PARAMETERS parameters include the curve coefcients and the base point.
  18. /// Binary curves use a polynomial to represent its characteristic, while prime curves
  19. /// use a prime number.
  20. /// \sa MQV, HMQV, FHMQV, and AuthenticatedKeyAgreementDomain
  21. /// \since Crypto++ 3.0
  22. template <class GROUP_PARAMETERS, class COFACTOR_OPTION = typename GROUP_PARAMETERS::DefaultCofactorOption>
  23. class MQV_Domain : public AuthenticatedKeyAgreementDomain
  24. {
  25. public:
  26. typedef GROUP_PARAMETERS GroupParameters;
  27. typedef typename GroupParameters::Element Element;
  28. typedef MQV_Domain<GROUP_PARAMETERS, COFACTOR_OPTION> Domain;
  29. /// \brief Construct a MQV domain
  30. MQV_Domain() {}
  31. /// \brief Construct a MQV domain
  32. /// \param params group parameters and options
  33. MQV_Domain(const GroupParameters &params)
  34. : m_groupParameters(params) {}
  35. /// \brief Construct a MQV domain
  36. /// \param bt BufferedTransformation with group parameters and options
  37. MQV_Domain(BufferedTransformation &bt)
  38. {m_groupParameters.BERDecode(bt);}
  39. /// \brief Construct a MQV domain
  40. /// \tparam T1 template parameter used as a constructor parameter
  41. /// \tparam T2 template parameter used as a constructor parameter
  42. /// \param v1 first parameter
  43. /// \param v2 second parameter
  44. /// \details v1 and v2 are passed directly to the GROUP_PARAMETERS object.
  45. template <class T1, class T2>
  46. MQV_Domain(T1 v1, T2 v2)
  47. {m_groupParameters.Initialize(v1, v2);}
  48. /// \brief Construct a MQV domain
  49. /// \tparam T1 template parameter used as a constructor parameter
  50. /// \tparam T2 template parameter used as a constructor parameter
  51. /// \tparam T3 template parameter used as a constructor parameter
  52. /// \param v1 first parameter
  53. /// \param v2 second parameter
  54. /// \param v3 third parameter
  55. /// \details v1, v2 and v3 are passed directly to the GROUP_PARAMETERS object.
  56. template <class T1, class T2, class T3>
  57. MQV_Domain(T1 v1, T2 v2, T3 v3)
  58. {m_groupParameters.Initialize(v1, v2, v3);}
  59. /// \brief Construct a MQV domain
  60. /// \tparam T1 template parameter used as a constructor parameter
  61. /// \tparam T2 template parameter used as a constructor parameter
  62. /// \tparam T3 template parameter used as a constructor parameter
  63. /// \tparam T4 template parameter used as a constructor parameter
  64. /// \param v1 first parameter
  65. /// \param v2 second parameter
  66. /// \param v3 third parameter
  67. /// \param v4 third parameter
  68. /// \details v1, v2, v3 and v4 are passed directly to the GROUP_PARAMETERS object.
  69. template <class T1, class T2, class T3, class T4>
  70. MQV_Domain(T1 v1, T2 v2, T3 v3, T4 v4)
  71. {m_groupParameters.Initialize(v1, v2, v3, v4);}
  72. /// \brief Retrieves the group parameters for this domain
  73. /// \return the group parameters for this domain as a const reference
  74. const GroupParameters & GetGroupParameters() const {return m_groupParameters;}
  75. /// \brief Retrieves the group parameters for this domain
  76. /// \return the group parameters for this domain as a non-const reference
  77. GroupParameters & AccessGroupParameters() {return m_groupParameters;}
  78. /// \brief Retrieves the crypto parameters for this domain
  79. /// \return the crypto parameters for this domain as a non-const reference
  80. CryptoParameters & AccessCryptoParameters() {return AccessAbstractGroupParameters();}
  81. /// \brief Provides the size of the agreed value
  82. /// \return size of agreed value produced in this domain
  83. /// \details The length is calculated using <tt>GetEncodedElementSize(false)</tt>,
  84. /// which means the element is encoded in a non-reversible format. A
  85. /// non-reversible format means its a raw byte array, and it lacks presentation
  86. /// format like an ASN.1 BIT_STRING or OCTET_STRING.
  87. unsigned int AgreedValueLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(false);}
  88. /// \brief Provides the size of the static private key
  89. /// \return size of static private keys in this domain
  90. /// \details The length is calculated using the byte count of the subgroup order.
  91. unsigned int StaticPrivateKeyLength() const {return GetAbstractGroupParameters().GetSubgroupOrder().ByteCount();}
  92. /// \brief Provides the size of the static public key
  93. /// \return size of static public keys in this domain
  94. /// \details The length is calculated using <tt>GetEncodedElementSize(true)</tt>,
  95. /// which means the element is encoded in a reversible format. A reversible
  96. /// format means it has a presentation format, and its an ANS.1 encoded element
  97. /// or point.
  98. unsigned int StaticPublicKeyLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(true);}
  99. /// \brief Generate static private key in this domain
  100. /// \param rng a RandomNumberGenerator derived class
  101. /// \param privateKey a byte buffer for the generated private key in this domain
  102. /// \details The private key is a random scalar used as an exponent in the range
  103. /// <tt>[1,MaxExponent()]</tt>.
  104. /// \pre <tt>COUNTOF(privateKey) == PrivateStaticKeyLength()</tt>
  105. void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
  106. {
  107. Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent());
  108. x.Encode(privateKey, StaticPrivateKeyLength());
  109. }
  110. /// \brief Generate a static public key from a private key in this domain
  111. /// \param rng a RandomNumberGenerator derived class
  112. /// \param privateKey a byte buffer with the previously generated private key
  113. /// \param publicKey a byte buffer for the generated public key in this domain
  114. /// \details The public key is an element or point on the curve, and its stored
  115. /// in a revrsible format. A reversible format means it has a presentation
  116. /// format, and its an ANS.1 encoded element or point.
  117. /// \pre <tt>COUNTOF(publicKey) == PublicStaticKeyLength()</tt>
  118. void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
  119. {
  120. CRYPTOPP_UNUSED(rng);
  121. const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
  122. Integer x(privateKey, StaticPrivateKeyLength());
  123. Element y = params.ExponentiateBase(x);
  124. params.EncodeElement(true, y, publicKey);
  125. }
  126. /// \brief Provides the size of the ephemeral private key
  127. /// \return size of ephemeral private keys in this domain
  128. /// \details An ephemeral private key is a private key and public key.
  129. /// The serialized size is different than a static private key.
  130. unsigned int EphemeralPrivateKeyLength() const {return StaticPrivateKeyLength() + StaticPublicKeyLength();}
  131. /// \brief Provides the size of the ephemeral public key
  132. /// \return size of ephemeral public keys in this domain
  133. /// \details An ephemeral public key is a public key.
  134. /// The serialized size is the same as a static public key.
  135. unsigned int EphemeralPublicKeyLength() const {return StaticPublicKeyLength();}
  136. /// \brief Generate ephemeral private key in this domain
  137. /// \param rng a RandomNumberGenerator derived class
  138. /// \param privateKey a byte buffer for the generated private key in this domain
  139. /// \pre <tt>COUNTOF(privateKey) == EphemeralPrivateKeyLength()</tt>
  140. void GenerateEphemeralPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
  141. {
  142. const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
  143. Integer x(rng, Integer::One(), params.GetMaxExponent());
  144. x.Encode(privateKey, StaticPrivateKeyLength());
  145. Element y = params.ExponentiateBase(x);
  146. params.EncodeElement(true, y, privateKey+StaticPrivateKeyLength());
  147. }
  148. /// \brief Generate ephemeral public key from a private key in this domain
  149. /// \param rng a RandomNumberGenerator derived class
  150. /// \param privateKey a byte buffer with the previously generated private key
  151. /// \param publicKey a byte buffer for the generated public key in this domain
  152. /// \pre <tt>COUNTOF(publicKey) == EphemeralPublicKeyLength()</tt>
  153. void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
  154. {
  155. CRYPTOPP_UNUSED(rng);
  156. std::memcpy(publicKey, privateKey+StaticPrivateKeyLength(), EphemeralPublicKeyLength());
  157. }
  158. /// \brief Derive agreed value or shared secret
  159. /// \param agreedValue the shared secret
  160. /// \param staticPrivateKey your long term private key
  161. /// \param ephemeralPrivateKey your ephemeral private key
  162. /// \param staticOtherPublicKey couterparty's long term public key
  163. /// \param ephemeralOtherPublicKey couterparty's ephemeral public key
  164. /// \param validateStaticOtherPublicKey flag indicating validation
  165. /// \return true upon success, false in case of failure
  166. /// \details Agree() performs the authenticated key agreement. Agree()
  167. /// derives a shared secret from your private keys and couterparty's
  168. /// public keys. Each instance or run of the protocol should use a new
  169. /// ephemeral key pair.
  170. /// \details The other's ephemeral public key will always be validated at
  171. /// Level 1 to ensure it is a point on the curve.
  172. /// <tt>validateStaticOtherPublicKey</tt> determines how thoroughly other's
  173. /// static public key is validated. If you have previously validated the
  174. /// couterparty's static public key, then use
  175. /// <tt>validateStaticOtherPublicKey=false</tt> to save time.
  176. /// \pre <tt>COUNTOF(agreedValue) == AgreedValueLength()</tt>
  177. /// \pre <tt>COUNTOF(staticPrivateKey) == StaticPrivateKeyLength()</tt>
  178. /// \pre <tt>COUNTOF(ephemeralPrivateKey) == EphemeralPrivateKeyLength()</tt>
  179. /// \pre <tt>COUNTOF(staticOtherPublicKey) == StaticPublicKeyLength()</tt>
  180. /// \pre <tt>COUNTOF(ephemeralOtherPublicKey) == EphemeralPublicKeyLength()</tt>
  181. bool Agree(byte *agreedValue,
  182. const byte *staticPrivateKey, const byte *ephemeralPrivateKey,
  183. const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey,
  184. bool validateStaticOtherPublicKey=true) const
  185. {
  186. try
  187. {
  188. const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
  189. Element WW = params.DecodeElement(staticOtherPublicKey, validateStaticOtherPublicKey);
  190. Element VV = params.DecodeElement(ephemeralOtherPublicKey, true);
  191. Integer s(staticPrivateKey, StaticPrivateKeyLength());
  192. Integer u(ephemeralPrivateKey, StaticPrivateKeyLength());
  193. Element V = params.DecodeElement(ephemeralPrivateKey+StaticPrivateKeyLength(), false);
  194. const Integer &r = params.GetSubgroupOrder();
  195. Integer h2 = Integer::Power2((r.BitCount()+1)/2);
  196. Integer e = ((h2+params.ConvertElementToInteger(V)%h2)*s+u) % r;
  197. Integer tt = h2 + params.ConvertElementToInteger(VV) % h2;
  198. if (COFACTOR_OPTION::ToEnum() == NO_COFACTOR_MULTIPLICTION)
  199. {
  200. Element P = params.ExponentiateElement(WW, tt);
  201. P = m_groupParameters.MultiplyElements(P, VV);
  202. Element R[2];
  203. const Integer e2[2] = {r, e};
  204. params.SimultaneousExponentiate(R, P, e2, 2);
  205. if (!params.IsIdentity(R[0]) || params.IsIdentity(R[1]))
  206. return false;
  207. params.EncodeElement(false, R[1], agreedValue);
  208. }
  209. else
  210. {
  211. const Integer &k = params.GetCofactor();
  212. if (COFACTOR_OPTION::ToEnum() == COMPATIBLE_COFACTOR_MULTIPLICTION)
  213. e = ModularArithmetic(r).Divide(e, k);
  214. Element P = m_groupParameters.CascadeExponentiate(VV, k*e, WW, k*(e*tt%r));
  215. if (params.IsIdentity(P))
  216. return false;
  217. params.EncodeElement(false, P, agreedValue);
  218. }
  219. }
  220. catch (DL_BadElement &)
  221. {
  222. return false;
  223. }
  224. return true;
  225. }
  226. private:
  227. DL_GroupParameters<Element> & AccessAbstractGroupParameters() {return m_groupParameters;}
  228. const DL_GroupParameters<Element> & GetAbstractGroupParameters() const {return m_groupParameters;}
  229. GroupParameters m_groupParameters;
  230. };
  231. /// Menezes-Qu-Vanstone in GF(p) with key validation, AKA <a href="http://www.weidai.com/scan-mirror/ka.html#MQV">MQV</a>
  232. /// \sa MQV, HMQV_Domain, FHMQV_Domain, AuthenticatedKeyAgreementDomain
  233. /// \since Crypto++ 3.0
  234. typedef MQV_Domain<DL_GroupParameters_GFP_DefaultSafePrime> MQV;
  235. NAMESPACE_END
  236. #endif