Back to home page

EIC code displayed by LXR

 
 

    


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 &params)
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> &params = 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> &params = 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> &params = 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