Crypto++ 8.7
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
17NAMESPACE_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
27template <class GROUP_PARAMETERS, class COFACTOR_OPTION = typename GROUP_PARAMETERS::DefaultCofactorOption>
29{
30public:
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 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
254private:
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
266NAMESPACE_END
267
268#endif
Classes for performing mathematics over different fields.
Interface for domains of authenticated key agreement protocols.
Definition: cryptlib.h:3072
Interface for buffered transformations.
Definition: cryptlib.h:1652
Interface for crypto parameters.
Definition: cryptlib.h:2546
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 const Integer & GetSubgroupOrder() const =0
Retrieves the subgroup order.
virtual Element ExponentiateBase(const Integer &exponent) const
Exponentiates the base.
Definition: pubkey.h:869
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.
unsigned int BitCount() const
Determines the number of bits required to represent the Integer.
static const Integer & One()
Integer representing 1.
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
const GroupParameters & GetGroupParameters() const
Retrieves the group parameters for this domain.
Definition: mqv.h:86
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
CryptoParameters & AccessCryptoParameters()
Retrieves the crypto parameters for this domain.
Definition: mqv.h:94
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
MQV_Domain()
Construct a MQV domain.
Definition: mqv.h:36
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:1435
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