mqv.h
Go to the documentation of this file.
// mqv.h - originally written and placed in the public domain by Wei Dai
/// \file mqv.h
/// \brief Classes for Menezes–Qu–Vanstone (MQV) key agreement
/// \since Crypto++ 3.0
#ifndef CRYPTOPP_MQV_H
#define CRYPTOPP_MQV_H
#include "cryptlib.h"
#include "gfpcrypt.h"
#include "modarith.h"
#include "integer.h"
#include "algebra.h"
#include "misc.h"
NAMESPACE_BEGIN(CryptoPP)
/// \brief MQV domain for performing authenticated key agreement
/// \tparam GROUP_PARAMETERS doamin parameters
/// \tparam COFACTOR_OPTION cofactor option
/// \details GROUP_PARAMETERS parameters include the curve coefcients and the base point.
/// Binary curves use a polynomial to represent its characteristic, while prime curves
/// use a prime number.
/// \sa MQV, HMQV, FHMQV, and AuthenticatedKeyAgreementDomain
/// \since Crypto++ 3.0
template <class GROUP_PARAMETERS, class COFACTOR_OPTION = typename GROUP_PARAMETERS::DefaultCofactorOption>
class MQV_Domain : public AuthenticatedKeyAgreementDomain
{
public:
typedef GROUP_PARAMETERS GroupParameters;
typedef typename GroupParameters::Element Element;
typedef MQV_Domain<GROUP_PARAMETERS, COFACTOR_OPTION> Domain;
/// \brief Construct a MQV domain
MQV_Domain() {}
/// \brief Construct a MQV domain
/// \param params group parameters and options
MQV_Domain(const GroupParameters &params)
: m_groupParameters(params) {}
/// \brief Construct a MQV domain
/// \param bt BufferedTransformation with group parameters and options
MQV_Domain(BufferedTransformation &bt)
{m_groupParameters.BERDecode(bt);}
/// \brief Construct a MQV domain
/// \tparam T1 template parameter used as a constructor parameter
/// \tparam T2 template parameter used as a constructor parameter
/// \param v1 first parameter
/// \param v2 second parameter
/// \details v1 and v2 are passed directly to the GROUP_PARAMETERS object.
template <class T1, class T2>
MQV_Domain(T1 v1, T2 v2)
{m_groupParameters.Initialize(v1, v2);}
/// \brief Construct a MQV domain
/// \tparam T1 template parameter used as a constructor parameter
/// \tparam T2 template parameter used as a constructor parameter
/// \tparam T3 template parameter used as a constructor parameter
/// \param v1 first parameter
/// \param v2 second parameter
/// \param v3 third parameter
/// \details v1, v2 and v3 are passed directly to the GROUP_PARAMETERS object.
template <class T1, class T2, class T3>
MQV_Domain(T1 v1, T2 v2, T3 v3)
{m_groupParameters.Initialize(v1, v2, v3);}
/// \brief Construct a MQV domain
/// \tparam T1 template parameter used as a constructor parameter
/// \tparam T2 template parameter used as a constructor parameter
/// \tparam T3 template parameter used as a constructor parameter
/// \tparam T4 template parameter used as a constructor parameter
/// \param v1 first parameter
/// \param v2 second parameter
/// \param v3 third parameter
/// \param v4 third parameter
/// \details v1, v2, v3 and v4 are passed directly to the GROUP_PARAMETERS object.
template <class T1, class T2, class T3, class T4>
MQV_Domain(T1 v1, T2 v2, T3 v3, T4 v4)
{m_groupParameters.Initialize(v1, v2, v3, v4);}
/// \brief Retrieves the group parameters for this domain
/// \return the group parameters for this domain as a const reference
const GroupParameters & GetGroupParameters() const {return m_groupParameters;}
/// \brief Retrieves the group parameters for this domain
/// \return the group parameters for this domain as a non-const reference
GroupParameters & AccessGroupParameters() {return m_groupParameters;}
/// \brief Retrieves the crypto parameters for this domain
/// \return the crypto parameters for this domain as a non-const reference
CryptoParameters & AccessCryptoParameters() {return AccessAbstractGroupParameters();}
/// \brief Provides the size of the agreed value
/// \return size of agreed value produced in this domain
/// \details The length is calculated using <tt>GetEncodedElementSize(false)</tt>,
/// which means the element is encoded in a non-reversible format. A
/// non-reversible format means its a raw byte array, and it lacks presentation
/// format like an ASN.1 BIT_STRING or OCTET_STRING.
unsigned int AgreedValueLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(false);}
/// \brief Provides the size of the static private key
/// \return size of static private keys in this domain
/// \details The length is calculated using the byte count of the subgroup order.
unsigned int StaticPrivateKeyLength() const {return GetAbstractGroupParameters().GetSubgroupOrder().ByteCount();}
/// \brief Provides the size of the static public key
/// \return size of static public keys in this domain
/// \details The length is calculated using <tt>GetEncodedElementSize(true)</tt>,
/// which means the element is encoded in a reversible format. A reversible
/// format means it has a presentation format, and its an ANS.1 encoded element
/// or point.
unsigned int StaticPublicKeyLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(true);}
/// \brief Generate static private key in this domain
/// \param rng a RandomNumberGenerator derived class
/// \param privateKey a byte buffer for the generated private key in this domain
/// \details The private key is a random scalar used as an exponent in the range
/// <tt>[1,MaxExponent()]</tt>.
/// \pre <tt>COUNTOF(privateKey) == PrivateStaticKeyLength()</tt>
void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
{
Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent());
x.Encode(privateKey, StaticPrivateKeyLength());
}
/// \brief Generate a static public key from a private key in this domain
/// \param rng a RandomNumberGenerator derived class
/// \param privateKey a byte buffer with the previously generated private key
/// \param publicKey a byte buffer for the generated public key in this domain
/// \details The public key is an element or point on the curve, and its stored
/// in a revrsible format. A reversible format means it has a presentation
/// format, and its an ANS.1 encoded element or point.
/// \pre <tt>COUNTOF(publicKey) == PublicStaticKeyLength()</tt>
void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
{
CRYPTOPP_UNUSED(rng);
const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
Integer x(privateKey, StaticPrivateKeyLength());
Element y = params.ExponentiateBase(x);
params.EncodeElement(true, y, publicKey);
}
/// \brief Provides the size of the ephemeral private key
/// \return size of ephemeral private keys in this domain
/// \details An ephemeral private key is a private key and public key.
/// The serialized size is different than a static private key.
unsigned int EphemeralPrivateKeyLength() const {return StaticPrivateKeyLength() + StaticPublicKeyLength();}
/// \brief Provides the size of the ephemeral public key
/// \return size of ephemeral public keys in this domain
/// \details An ephemeral public key is a public key.
/// The serialized size is the same as a static public key.
unsigned int EphemeralPublicKeyLength() const {return StaticPublicKeyLength();}
/// \brief Generate ephemeral private key in this domain
/// \param rng a RandomNumberGenerator derived class
/// \param privateKey a byte buffer for the generated private key in this domain
/// \pre <tt>COUNTOF(privateKey) == EphemeralPrivateKeyLength()</tt>
void GenerateEphemeralPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
{
const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
Integer x(rng, Integer::One(), params.GetMaxExponent());
x.Encode(privateKey, StaticPrivateKeyLength());
Element y = params.ExponentiateBase(x);
params.EncodeElement(true, y, privateKey+StaticPrivateKeyLength());
}
/// \brief Generate ephemeral public key from a private key in this domain
/// \param rng a RandomNumberGenerator derived class
/// \param privateKey a byte buffer with the previously generated private key
/// \param publicKey a byte buffer for the generated public key in this domain
/// \pre <tt>COUNTOF(publicKey) == EphemeralPublicKeyLength()</tt>
void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
{
CRYPTOPP_UNUSED(rng);
std::memcpy(publicKey, privateKey+StaticPrivateKeyLength(), EphemeralPublicKeyLength());
}
/// \brief Derive agreed value or shared secret
/// \param agreedValue the shared secret
/// \param staticPrivateKey your long term private key
/// \param ephemeralPrivateKey your ephemeral private key
/// \param staticOtherPublicKey couterparty's long term public key
/// \param ephemeralOtherPublicKey couterparty's ephemeral public key
/// \param validateStaticOtherPublicKey flag indicating validation
/// \return true upon success, false in case of failure
/// \details Agree() performs the authenticated key agreement. Agree()
/// derives a shared secret from your private keys and couterparty's
/// public keys. Each instance or run of the protocol should use a new
/// ephemeral key pair.
/// \details The other's ephemeral public key will always be validated at
/// Level 1 to ensure it is a point on the curve.
/// <tt>validateStaticOtherPublicKey</tt> determines how thoroughly other's
/// static public key is validated. If you have previously validated the
/// couterparty's static public key, then use
/// <tt>validateStaticOtherPublicKey=false</tt> to save time.
/// \pre <tt>COUNTOF(agreedValue) == AgreedValueLength()</tt>
/// \pre <tt>COUNTOF(staticPrivateKey) == StaticPrivateKeyLength()</tt>
/// \pre <tt>COUNTOF(ephemeralPrivateKey) == EphemeralPrivateKeyLength()</tt>
/// \pre <tt>COUNTOF(staticOtherPublicKey) == StaticPublicKeyLength()</tt>
/// \pre <tt>COUNTOF(ephemeralOtherPublicKey) == EphemeralPublicKeyLength()</tt>
bool Agree(byte *agreedValue,
const byte *staticPrivateKey, const byte *ephemeralPrivateKey,
const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey,
bool validateStaticOtherPublicKey=true) const
{
try
{
const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
Element WW = params.DecodeElement(staticOtherPublicKey, validateStaticOtherPublicKey);
Element VV = params.DecodeElement(ephemeralOtherPublicKey, true);
Integer s(staticPrivateKey, StaticPrivateKeyLength());
Integer u(ephemeralPrivateKey, StaticPrivateKeyLength());
Element V = params.DecodeElement(ephemeralPrivateKey+StaticPrivateKeyLength(), false);
const Integer &r = params.GetSubgroupOrder();
Integer h2 = Integer::Power2((r.BitCount()+1)/2);
Integer e = ((h2+params.ConvertElementToInteger(V)%h2)*s+u) % r;
Integer tt = h2 + params.ConvertElementToInteger(VV) % h2;
if (COFACTOR_OPTION::ToEnum() == NO_COFACTOR_MULTIPLICTION)
{
Element P = params.ExponentiateElement(WW, tt);
P = m_groupParameters.MultiplyElements(P, VV);
Element R[2];
const Integer e2[2] = {r, e};
params.SimultaneousExponentiate(R, P, e2, 2);
if (!params.IsIdentity(R[0]) || params.IsIdentity(R[1]))
return false;
params.EncodeElement(false, R[1], agreedValue);
}
else
{
const Integer &k = params.GetCofactor();
if (COFACTOR_OPTION::ToEnum() == COMPATIBLE_COFACTOR_MULTIPLICTION)
e = ModularArithmetic(r).Divide(e, k);
Element P = m_groupParameters.CascadeExponentiate(VV, k*e, WW, k*(e*tt%r));
if (params.IsIdentity(P))
return false;
params.EncodeElement(false, P, agreedValue);
}
}
catch (DL_BadElement &)
{
return false;
}
return true;
}
private:
DL_GroupParameters<Element> & AccessAbstractGroupParameters() {return m_groupParameters;}
const DL_GroupParameters<Element> & GetAbstractGroupParameters() const {return m_groupParameters;}
GroupParameters m_groupParameters;
};
/// Menezes-Qu-Vanstone in GF(p) with key validation, AKA <a href="http://www.weidai.com/scan-mirror/ka.html#MQV">MQV</a>
/// \sa MQV, HMQV_Domain, FHMQV_Domain, AuthenticatedKeyAgreementDomain
/// \since Crypto++ 3.0
typedef MQV_Domain<DL_GroupParameters_GFP_DefaultSafePrime> MQV;
NAMESPACE_END
#endif
algebra.h
Classes for performing mathematics over different fields.
AuthenticatedKeyAgreementDomain
Interface for domains of authenticated key agreement protocols.
Definition cryptlib.h:3077
BufferedTransformation
Interface for buffered transformations.
Definition cryptlib.h:1657
CryptoParameters
Interface for crypto parameters.
Definition cryptlib.h:2551
DL_BadElement
Exception thrown when an invalid group element is encountered.
Definition pubkey.h:772
DL_GroupParameters
Interface for Discrete Log (DL) group parameters.
Definition pubkey.h:782
DL_GroupParameters::ExponentiateElement
virtual Element ExponentiateElement(const Element &base, const Integer &exponent) const
Exponentiates an element.
Definition pubkey.h:879
DL_GroupParameters::GetCofactor
virtual Integer GetCofactor() const
Retrieves the cofactor.
Definition pubkey.h:914
DL_GroupParameters::EncodeElement
virtual void EncodeElement(bool reversible, const Element &element, byte *encoded) const =0
Encodes the element.
DL_GroupParameters::GetMaxExponent
virtual Integer GetMaxExponent() const =0
Retrieves the maximum exponent for the group.
DL_GroupParameters::SimultaneousExponentiate
virtual void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const =0
Exponentiates a base to multiple exponents.
DL_GroupParameters::GetSubgroupOrder
virtual const Integer & GetSubgroupOrder() const =0
Retrieves the subgroup order.
DL_GroupParameters::ExponentiateBase
virtual Element ExponentiateBase(const Integer &exponent) const
Exponentiates the base.
Definition pubkey.h:869
DL_GroupParameters::DecodeElement
virtual Element DecodeElement(const byte *encoded, bool checkForGroupMembership) const =0
Decodes the element.
DL_GroupParameters::ConvertElementToInteger
virtual Integer ConvertElementToInteger(const Element &element) const =0
Converts an element to an Integer.
DL_GroupParameters::IsIdentity
virtual bool IsIdentity(const Element &element) const =0
Determines if an element is an identity.
Integer
Multiple precision integer with arithmetic operations.
Definition integer.h:50
Integer::Power2
static Integer Power2(size_t e)
Exponentiates to a power of 2.
Integer::BitCount
unsigned int BitCount() const
Determines the number of bits required to represent the Integer.
Integer::One
static const Integer & One()
Integer representing 1.
MQV_Domain
MQV domain for performing authenticated key agreement.
Definition mqv.h:29
MQV_Domain::EphemeralPublicKeyLength
unsigned int EphemeralPublicKeyLength() const
Provides the size of the ephemeral public key.
Definition mqv.h:156
MQV_Domain::MQV_Domain
MQV_Domain(T1 v1, T2 v2)
Construct a MQV domain.
Definition mqv.h:55
MQV_Domain::GetGroupParameters
const GroupParameters & GetGroupParameters() const
Retrieves the group parameters for this domain.
Definition mqv.h:86
MQV_Domain::MQV_Domain
MQV_Domain(BufferedTransformation &bt)
Construct a MQV domain.
Definition mqv.h:45
MQV_Domain::GenerateEphemeralPublicKey
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
MQV_Domain::EphemeralPrivateKeyLength
unsigned int EphemeralPrivateKeyLength() const
Provides the size of the ephemeral private key.
Definition mqv.h:150
MQV_Domain::GenerateStaticPrivateKey
void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
Generate static private key in this domain.
Definition mqv.h:123
MQV_Domain::AccessCryptoParameters
CryptoParameters & AccessCryptoParameters()
Retrieves the crypto parameters for this domain.
Definition mqv.h:94
MQV_Domain::GenerateStaticPublicKey
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
MQV_Domain::AgreedValueLength
unsigned int AgreedValueLength() const
Provides the size of the agreed value.
Definition mqv.h:102
MQV_Domain::GenerateEphemeralPrivateKey
void GenerateEphemeralPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
Generate ephemeral private key in this domain.
Definition mqv.h:162
MQV_Domain::MQV_Domain
MQV_Domain(T1 v1, T2 v2, T3 v3, T4 v4)
Construct a MQV domain.
Definition mqv.h:81
MQV_Domain::Agree
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::MQV_Domain
MQV_Domain(const GroupParameters &params)
Construct a MQV domain.
Definition mqv.h:40
MQV_Domain::StaticPrivateKeyLength
unsigned int StaticPrivateKeyLength() const
Provides the size of the static private key.
Definition mqv.h:107
MQV_Domain::MQV_Domain
MQV_Domain(T1 v1, T2 v2, T3 v3)
Construct a MQV domain.
Definition mqv.h:67
MQV_Domain::AccessGroupParameters
GroupParameters & AccessGroupParameters()
Retrieves the group parameters for this domain.
Definition mqv.h:90
MQV_Domain::StaticPublicKeyLength
unsigned int StaticPublicKeyLength() const
Provides the size of the static public key.
Definition mqv.h:115
MQV_Domain::MQV_Domain
MQV_Domain()
Construct a MQV domain.
Definition mqv.h:36
ModularArithmetic
Ring of congruence classes modulo n.
Definition modarith.h:44
ModularArithmetic::Divide
const Integer & Divide(const Integer &a, const Integer &b) const
Divides elements in the ring.
Definition modarith.h:218
RandomNumberGenerator
Interface for random number generators.
Definition cryptlib.h:1440
cryptlib.h
Abstract base classes that provide a uniform interface to this library.
gfpcrypt.h
Classes and functions for schemes based on Discrete Logs (DL) over GF(p)
integer.h
Multiple precision integer with arithmetic operations.
misc.h
Utility functions for the Crypto++ library.
modarith.h
Class file for performing modular arithmetic.
MQV
MQV_Domain< DL_GroupParameters_GFP_DefaultSafePrime > MQV
Menezes-Qu-Vanstone in GF(p) with key validation, AKA MQV
Definition mqv.h:264
CryptoPP
Crypto++ library namespace.
NO_COFACTOR_MULTIPLICTION
@ NO_COFACTOR_MULTIPLICTION
No cofactor multiplication applied.
Definition pubkey.h:2125
COMPATIBLE_COFACTOR_MULTIPLICTION
@ COMPATIBLE_COFACTOR_MULTIPLICTION
Cofactor multiplication compatible with ordinary Diffie-Hellman.
Definition pubkey.h:2129