mqv.h
Go to the documentation of this file.
// mqv.h - written and placed in the public domain by Wei Dai
//! \file mqv.h
//! \brief Classes for Menezes–Qu–Vanstone (MQV) key agreement
#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)
//! \class MQV_Domain
//! \brief MQV domain for performing authenticated key agreement
//! \tparam GROUP_PARAMETERS doamin parameters
//! \tparam COFACTOR_OPTION cofactor option
//! \details GROUP_PARAMETERS paramters 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
template <class GROUP_PARAMETERS, class COFACTOR_OPTION = CPP_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);
}
unsigned int EphemeralPrivateKeyLength() const {return StaticPrivateKeyLength() + StaticPublicKeyLength();}
unsigned int EphemeralPublicKeyLength() const {return StaticPublicKeyLength();}
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());
}
void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
{
CRYPTOPP_UNUSED(rng);
memcpy(publicKey, privateKey+StaticPrivateKeyLength(), EphemeralPublicKeyLength());
}
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
typedef MQV_Domain<DL_GroupParameters_GFP_DefaultSafePrime> MQV;
NAMESPACE_END
#endif
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:132
MQV_Domain::MQV_Domain
MQV_Domain(T1 v1, T2 v2)
Construct a MQV domain.
Definition: mqv.h:54
DL_GroupParameters::GetCofactor
virtual Integer GetCofactor() const
Retrieves the cofactor.
Definition: pubkey.h:866
ModularArithmetic::Divide
const Integer & Divide(const Integer &a, const Integer &b) const
Divides elements in the ring.
Definition: modarith.h:200
misc.h
Utility functions for the Crypto++ library.
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.
Definition: mqv.h:159
DL_GroupParameters
Interface for Discrete Log (DL) group parameters.
Definition: pubkey.h:752
MQV_Domain::MQV_Domain
MQV_Domain(T1 v1, T2 v2, T3 v3, T4 v4)
Construct a MQV domain.
Definition: mqv.h:80
cryptlib.h
Abstract base classes that provide a uniform interface to this library.
DL_GroupParameters::ConvertElementToInteger
virtual Integer ConvertElementToInteger(const Element &element) const =0
Converts an element to an Integer.
ModularArithmetic
Ring of congruence classes modulo n.
Definition: modarith.h:34
RandomNumberGenerator
Interface for random number generators.
Definition: cryptlib.h:1186
MQV_Domain::MQV_Domain
MQV_Domain(BufferedTransformation &bt)
Construct a MQV domain.
Definition: mqv.h:44
algebra.h
Classes for performing mathematics over different fields.
BufferedTransformation
Interface for buffered transformations.
Definition: cryptlib.h:1352
DL_GroupParameters::ExponentiateBase
virtual Element ExponentiateBase(const Integer &exponent) const
Retrieves the subgroup generator.
Definition: pubkey.h:821
Integer::One
static const Integer & One()
Integer representing 1.
Definition: integer.cpp:3016
MQV
MQV_Domain< DL_GroupParameters_GFP_DefaultSafePrime > MQV
Menezes-Qu-Vanstone in GF(p) with key validation, AKA MQV
Definition: mqv.h:217
COMPATIBLE_COFACTOR_MULTIPLICTION
Cofactor multiplication compatible with ordinary Diffie-Hellman.
Definition: pubkey.h:1960
MQV_Domain
MQV domain for performing authenticated key agreement.
Definition: mqv.h:27
NO_COFACTOR_MULTIPLICTION
No cofactor multiplication applied.
Definition: pubkey.h:1956
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.
Integer::Power2
static Integer Power2(size_t e)
Exponentiates to a power of 2.
Definition: integer.cpp:2995
Integer
Multiple precision integer with arithmetic operations.
Definition: integer.h:45
MQV_Domain::EphemeralPublicKeyLength
unsigned int EphemeralPublicKeyLength() const
Provides the size of ephemeral public key.
Definition: mqv.h:142
MQV_Domain::StaticPrivateKeyLength
unsigned int StaticPrivateKeyLength() const
Provides the size of the static private key.
Definition: mqv.h:105
gfpcrypt.h
Implementation of schemes based on DL over GF(p)
DL_GroupParameters::DecodeElement
virtual Element DecodeElement(const byte *encoded, bool checkForGroupMembership) const =0
Decodes the element.
MQV_Domain::GenerateEphemeralPrivateKey
void GenerateEphemeralPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
Generate ephemeral private key.
Definition: mqv.h:144
DL_BadElement
Exception thrown when an invalid group element is encountered.
Definition: pubkey.h:742
MQV_Domain::GenerateEphemeralPublicKey
void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
Generate ephemeral public key.
Definition: mqv.h:153
Integer::BitCount
unsigned int BitCount() const
Determines the number of bits required to represent the Integer.
Definition: integer.cpp:3289
MQV_Domain::GenerateStaticPrivateKey
void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
Generate static private key in this domain.
Definition: mqv.h:119
Integer::Encode
void Encode(byte *output, size_t outputLen, Signedness sign=UNSIGNED) const
Encode in big-endian format.
Definition: integer.cpp:3350
MQV_Domain::StaticPublicKeyLength
unsigned int StaticPublicKeyLength() const
Provides the size of the static public key.
Definition: mqv.h:112
MQV_Domain::MQV_Domain
MQV_Domain(const GroupParameters &params)
Construct a MQV domain.
Definition: mqv.h:39
DL_GroupParameters::EncodeElement
virtual void EncodeElement(bool reversible, const Element &element, byte *encoded) const =0
Encodes the element.
integer.h
Multiple precision integer with arithmetic operations.
MQV_Domain::MQV_Domain
MQV_Domain(T1 v1, T2 v2, T3 v3)
Construct a MQV domain.
Definition: mqv.h:66
MQV_Domain::MQV_Domain
MQV_Domain()
Construct a MQV domain.
Definition: mqv.h:35
CryptoParameters
Interface for crypto prameters.
Definition: cryptlib.h:2196
DL_GroupParameters::GetMaxExponent
virtual Integer GetMaxExponent() const =0
Retrieves the maximum exponent for the group.
MQV_Domain::AccessCryptoParameters
CryptoParameters & AccessCryptoParameters()
Retrieves the crypto parameters for this domain.
Definition: mqv.h:93
MQV_Domain::EphemeralPrivateKeyLength
unsigned int EphemeralPrivateKeyLength() const
Provides the size of ephemeral private key.
Definition: mqv.h:141
modarith.h
Class file for performing modular arithmetic.
CryptoPP
Crypto++ library namespace.
MQV_Domain::AgreedValueLength
unsigned int AgreedValueLength() const
Provides the size of the agreed value.
Definition: mqv.h:100
AuthenticatedKeyAgreementDomain
Interface for domains of authenticated key agreement protocols.
Definition: cryptlib.h:2747
MQV_Domain::AccessGroupParameters
GroupParameters & AccessGroupParameters()
Retrieves the group parameters for this domain.
Definition: mqv.h:89
MQV_Domain::GetGroupParameters
const GroupParameters & GetGroupParameters() const
Retrieves the group parameters for this domain.
Definition: mqv.h:85
DL_GroupParameters::ExponentiateElement
virtual Element ExponentiateElement(const Element &base, const Integer &exponent) const
Exponentiates an element.
Definition: pubkey.h:831
DL_GroupParameters::IsIdentity
virtual bool IsIdentity(const Element &element) const =0
Determines if an element is an identity.
DL_GroupParameters::GetSubgroupOrder
virtual const Integer & GetSubgroupOrder() const =0
Retrieves the subgroup order.