|
||||
File indexing completed on 2025-01-18 09:55:05
0001 // mqv.h - originally written and placed in the public domain by Wei Dai 0002 0003 /// \file mqv.h 0004 /// \brief Classes for Menezes–Qu–Vanstone (MQV) key agreement 0005 /// \since Crypto++ 3.0 0006 0007 #ifndef CRYPTOPP_MQV_H 0008 #define CRYPTOPP_MQV_H 0009 0010 #include "cryptlib.h" 0011 #include "gfpcrypt.h" 0012 #include "modarith.h" 0013 #include "integer.h" 0014 #include "algebra.h" 0015 #include "misc.h" 0016 0017 NAMESPACE_BEGIN(CryptoPP) 0018 0019 /// \brief MQV domain for performing authenticated key agreement 0020 /// \tparam GROUP_PARAMETERS doamin parameters 0021 /// \tparam COFACTOR_OPTION cofactor option 0022 /// \details GROUP_PARAMETERS parameters include the curve coefcients and the base point. 0023 /// Binary curves use a polynomial to represent its characteristic, while prime curves 0024 /// use a prime number. 0025 /// \sa MQV, HMQV, FHMQV, and AuthenticatedKeyAgreementDomain 0026 /// \since Crypto++ 3.0 0027 template <class GROUP_PARAMETERS, class COFACTOR_OPTION = typename GROUP_PARAMETERS::DefaultCofactorOption> 0028 class MQV_Domain : public AuthenticatedKeyAgreementDomain 0029 { 0030 public: 0031 typedef GROUP_PARAMETERS GroupParameters; 0032 typedef typename GroupParameters::Element Element; 0033 typedef MQV_Domain<GROUP_PARAMETERS, COFACTOR_OPTION> Domain; 0034 0035 /// \brief Construct a MQV domain 0036 MQV_Domain() {} 0037 0038 /// \brief Construct a MQV domain 0039 /// \param params group parameters and options 0040 MQV_Domain(const GroupParameters ¶ms) 0041 : m_groupParameters(params) {} 0042 0043 /// \brief Construct a MQV domain 0044 /// \param bt BufferedTransformation with group parameters and options 0045 MQV_Domain(BufferedTransformation &bt) 0046 {m_groupParameters.BERDecode(bt);} 0047 0048 /// \brief Construct a MQV domain 0049 /// \tparam T1 template parameter used as a constructor parameter 0050 /// \tparam T2 template parameter used as a constructor parameter 0051 /// \param v1 first parameter 0052 /// \param v2 second parameter 0053 /// \details v1 and v2 are passed directly to the GROUP_PARAMETERS object. 0054 template <class T1, class T2> 0055 MQV_Domain(T1 v1, T2 v2) 0056 {m_groupParameters.Initialize(v1, v2);} 0057 0058 /// \brief Construct a MQV domain 0059 /// \tparam T1 template parameter used as a constructor parameter 0060 /// \tparam T2 template parameter used as a constructor parameter 0061 /// \tparam T3 template parameter used as a constructor parameter 0062 /// \param v1 first parameter 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 T1, class T2, class T3> 0067 MQV_Domain(T1 v1, T2 v2, T3 v3) 0068 {m_groupParameters.Initialize(v1, v2, v3);} 0069 0070 /// \brief Construct a MQV domain 0071 /// \tparam T1 template parameter used as a constructor parameter 0072 /// \tparam T2 template parameter used as a constructor parameter 0073 /// \tparam T3 template parameter used as a constructor parameter 0074 /// \tparam T4 template parameter used as a constructor parameter 0075 /// \param v1 first parameter 0076 /// \param v2 second parameter 0077 /// \param v3 third parameter 0078 /// \param v4 third parameter 0079 /// \details v1, v2, v3 and v4 are passed directly to the GROUP_PARAMETERS object. 0080 template <class T1, class T2, class T3, class T4> 0081 MQV_Domain(T1 v1, T2 v2, T3 v3, T4 v4) 0082 {m_groupParameters.Initialize(v1, v2, v3, v4);} 0083 0084 /// \brief Retrieves the group parameters for this domain 0085 /// \return the group parameters for this domain as a const reference 0086 const GroupParameters & GetGroupParameters() const {return m_groupParameters;} 0087 0088 /// \brief Retrieves the group parameters for this domain 0089 /// \return the group parameters for this domain as a non-const reference 0090 GroupParameters & AccessGroupParameters() {return m_groupParameters;} 0091 0092 /// \brief Retrieves the crypto parameters for this domain 0093 /// \return the crypto parameters for this domain as a non-const reference 0094 CryptoParameters & AccessCryptoParameters() {return AccessAbstractGroupParameters();} 0095 0096 /// \brief Provides the size of the agreed value 0097 /// \return size of agreed value produced in this domain 0098 /// \details The length is calculated using <tt>GetEncodedElementSize(false)</tt>, 0099 /// which means the element is encoded in a non-reversible format. A 0100 /// non-reversible format means its a raw byte array, and it lacks presentation 0101 /// format like an ASN.1 BIT_STRING or OCTET_STRING. 0102 unsigned int AgreedValueLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(false);} 0103 0104 /// \brief Provides the size of the static private key 0105 /// \return size of static private keys in this domain 0106 /// \details The length is calculated using the byte count of the subgroup order. 0107 unsigned int StaticPrivateKeyLength() const {return GetAbstractGroupParameters().GetSubgroupOrder().ByteCount();} 0108 0109 /// \brief Provides the size of the static public key 0110 /// \return size of static public keys in this domain 0111 /// \details The length is calculated using <tt>GetEncodedElementSize(true)</tt>, 0112 /// which means the element is encoded in a reversible format. A reversible 0113 /// format means it has a presentation format, and its an ANS.1 encoded element 0114 /// or point. 0115 unsigned int StaticPublicKeyLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(true);} 0116 0117 /// \brief Generate static private key in this domain 0118 /// \param rng a RandomNumberGenerator derived class 0119 /// \param privateKey a byte buffer for the generated private key in this domain 0120 /// \details The private key is a random scalar used as an exponent in the range 0121 /// <tt>[1,MaxExponent()]</tt>. 0122 /// \pre <tt>COUNTOF(privateKey) == PrivateStaticKeyLength()</tt> 0123 void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const 0124 { 0125 Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent()); 0126 x.Encode(privateKey, StaticPrivateKeyLength()); 0127 } 0128 0129 /// \brief Generate a static public key from a private key in this domain 0130 /// \param rng a RandomNumberGenerator derived class 0131 /// \param privateKey a byte buffer with the previously generated private key 0132 /// \param publicKey a byte buffer for the generated public key in this domain 0133 /// \details The public key is an element or point on the curve, and its stored 0134 /// in a revrsible format. A reversible format means it has a presentation 0135 /// format, and its an ANS.1 encoded element or point. 0136 /// \pre <tt>COUNTOF(publicKey) == PublicStaticKeyLength()</tt> 0137 void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const 0138 { 0139 CRYPTOPP_UNUSED(rng); 0140 const DL_GroupParameters<Element> ¶ms = GetAbstractGroupParameters(); 0141 Integer x(privateKey, StaticPrivateKeyLength()); 0142 Element y = params.ExponentiateBase(x); 0143 params.EncodeElement(true, y, publicKey); 0144 } 0145 0146 /// \brief Provides the size of the ephemeral private key 0147 /// \return size of ephemeral private keys in this domain 0148 /// \details An ephemeral private key is a private key and public key. 0149 /// The serialized size is different than a static private key. 0150 unsigned int EphemeralPrivateKeyLength() const {return StaticPrivateKeyLength() + StaticPublicKeyLength();} 0151 0152 /// \brief Provides the size of the ephemeral public key 0153 /// \return size of ephemeral public keys in this domain 0154 /// \details An ephemeral public key is a public key. 0155 /// The serialized size is the same as a static public key. 0156 unsigned int EphemeralPublicKeyLength() const {return StaticPublicKeyLength();} 0157 0158 /// \brief Generate ephemeral private key in this domain 0159 /// \param rng a RandomNumberGenerator derived class 0160 /// \param privateKey a byte buffer for the generated private key in this domain 0161 /// \pre <tt>COUNTOF(privateKey) == EphemeralPrivateKeyLength()</tt> 0162 void GenerateEphemeralPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const 0163 { 0164 const DL_GroupParameters<Element> ¶ms = GetAbstractGroupParameters(); 0165 Integer x(rng, Integer::One(), params.GetMaxExponent()); 0166 x.Encode(privateKey, StaticPrivateKeyLength()); 0167 Element y = params.ExponentiateBase(x); 0168 params.EncodeElement(true, y, privateKey+StaticPrivateKeyLength()); 0169 } 0170 0171 /// \brief Generate ephemeral public key from a private key in this domain 0172 /// \param rng a RandomNumberGenerator derived class 0173 /// \param privateKey a byte buffer with the previously generated private key 0174 /// \param publicKey a byte buffer for the generated public key in this domain 0175 /// \pre <tt>COUNTOF(publicKey) == EphemeralPublicKeyLength()</tt> 0176 void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const 0177 { 0178 CRYPTOPP_UNUSED(rng); 0179 std::memcpy(publicKey, privateKey+StaticPrivateKeyLength(), EphemeralPublicKeyLength()); 0180 } 0181 0182 /// \brief Derive agreed value or shared secret 0183 /// \param agreedValue the shared secret 0184 /// \param staticPrivateKey your long term private key 0185 /// \param ephemeralPrivateKey your ephemeral private key 0186 /// \param staticOtherPublicKey couterparty's long term public key 0187 /// \param ephemeralOtherPublicKey couterparty's ephemeral public key 0188 /// \param validateStaticOtherPublicKey flag indicating validation 0189 /// \return true upon success, false in case of failure 0190 /// \details Agree() performs the authenticated key agreement. Agree() 0191 /// derives a shared secret from your private keys and couterparty's 0192 /// public keys. Each instance or run of the protocol should use a new 0193 /// ephemeral key pair. 0194 /// \details The other's ephemeral public key will always be validated at 0195 /// Level 1 to ensure it is a point on the curve. 0196 /// <tt>validateStaticOtherPublicKey</tt> determines how thoroughly other's 0197 /// static public key is validated. If you have previously validated the 0198 /// couterparty's static public key, then use 0199 /// <tt>validateStaticOtherPublicKey=false</tt> to save time. 0200 /// \pre <tt>COUNTOF(agreedValue) == AgreedValueLength()</tt> 0201 /// \pre <tt>COUNTOF(staticPrivateKey) == StaticPrivateKeyLength()</tt> 0202 /// \pre <tt>COUNTOF(ephemeralPrivateKey) == EphemeralPrivateKeyLength()</tt> 0203 /// \pre <tt>COUNTOF(staticOtherPublicKey) == StaticPublicKeyLength()</tt> 0204 /// \pre <tt>COUNTOF(ephemeralOtherPublicKey) == EphemeralPublicKeyLength()</tt> 0205 bool Agree(byte *agreedValue, 0206 const byte *staticPrivateKey, const byte *ephemeralPrivateKey, 0207 const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey, 0208 bool validateStaticOtherPublicKey=true) const 0209 { 0210 try 0211 { 0212 const DL_GroupParameters<Element> ¶ms = GetAbstractGroupParameters(); 0213 Element WW = params.DecodeElement(staticOtherPublicKey, validateStaticOtherPublicKey); 0214 Element VV = params.DecodeElement(ephemeralOtherPublicKey, true); 0215 0216 Integer s(staticPrivateKey, StaticPrivateKeyLength()); 0217 Integer u(ephemeralPrivateKey, StaticPrivateKeyLength()); 0218 Element V = params.DecodeElement(ephemeralPrivateKey+StaticPrivateKeyLength(), false); 0219 0220 const Integer &r = params.GetSubgroupOrder(); 0221 Integer h2 = Integer::Power2((r.BitCount()+1)/2); 0222 Integer e = ((h2+params.ConvertElementToInteger(V)%h2)*s+u) % r; 0223 Integer tt = h2 + params.ConvertElementToInteger(VV) % h2; 0224 0225 if (COFACTOR_OPTION::ToEnum() == NO_COFACTOR_MULTIPLICTION) 0226 { 0227 Element P = params.ExponentiateElement(WW, tt); 0228 P = m_groupParameters.MultiplyElements(P, VV); 0229 Element R[2]; 0230 const Integer e2[2] = {r, e}; 0231 params.SimultaneousExponentiate(R, P, e2, 2); 0232 if (!params.IsIdentity(R[0]) || params.IsIdentity(R[1])) 0233 return false; 0234 params.EncodeElement(false, R[1], agreedValue); 0235 } 0236 else 0237 { 0238 const Integer &k = params.GetCofactor(); 0239 if (COFACTOR_OPTION::ToEnum() == COMPATIBLE_COFACTOR_MULTIPLICTION) 0240 e = ModularArithmetic(r).Divide(e, k); 0241 Element P = m_groupParameters.CascadeExponentiate(VV, k*e, WW, k*(e*tt%r)); 0242 if (params.IsIdentity(P)) 0243 return false; 0244 params.EncodeElement(false, P, agreedValue); 0245 } 0246 } 0247 catch (DL_BadElement &) 0248 { 0249 return false; 0250 } 0251 return true; 0252 } 0253 0254 private: 0255 DL_GroupParameters<Element> & AccessAbstractGroupParameters() {return m_groupParameters;} 0256 const DL_GroupParameters<Element> & GetAbstractGroupParameters() const {return m_groupParameters;} 0257 0258 GroupParameters m_groupParameters; 0259 }; 0260 0261 /// Menezes-Qu-Vanstone in GF(p) with key validation, AKA <a href="http://www.weidai.com/scan-mirror/ka.html#MQV">MQV</a> 0262 /// \sa MQV, HMQV_Domain, FHMQV_Domain, AuthenticatedKeyAgreementDomain 0263 /// \since Crypto++ 3.0 0264 typedef MQV_Domain<DL_GroupParameters_GFP_DefaultSafePrime> MQV; 0265 0266 NAMESPACE_END 0267 0268 #endif
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |