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