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