Whitespace

pull/263/head
Jeffrey Walton 2016-07-13 15:47:58 -04:00
parent 19763c33a8
commit e9b11b8e08
5 changed files with 629 additions and 629 deletions

View File

@ -1,14 +1,14 @@
// fhmqv.cpp - written and placed in the public domain by Jeffrey Walton // fhmqv.cpp - written and placed in the public domain by Jeffrey Walton
// Shamelessly based upon Wei Dai's MQV source files // Shamelessly based upon Wei Dai's MQV source files
#include "pch.h" #include "pch.h"
#include "fhmqv.h" #include "fhmqv.h"
NAMESPACE_BEGIN(CryptoPP) NAMESPACE_BEGIN(CryptoPP)
void TestInstantiations_FHMQV() void TestInstantiations_FHMQV()
{ {
FullyHashedMQV fhmqv; FullyHashedMQV fhmqv;
} }
NAMESPACE_END NAMESPACE_END

588
fhmqv.h
View File

@ -1,294 +1,294 @@
// fhmqv.h - written and placed in the public domain by Jeffrey Walton // fhmqv.h - written and placed in the public domain by Jeffrey Walton
// Shamelessly based upon Wei Dai's MQV source files // Shamelessly based upon Wei Dai's MQV source files
#ifndef CRYPTOPP_FHMQV_H #ifndef CRYPTOPP_FHMQV_H
#define CRYPTOPP_FHMQV_H #define CRYPTOPP_FHMQV_H
/** \file /** \file
*/ */
#include "gfpcrypt.h" #include "gfpcrypt.h"
#include "algebra.h" #include "algebra.h"
#include "sha.h" #include "sha.h"
NAMESPACE_BEGIN(CryptoPP) NAMESPACE_BEGIN(CryptoPP)
//! Fully Hashed Menezes-Qu-Vanstone in GF(p) with key validation, //! Fully Hashed Menezes-Qu-Vanstone in GF(p) with key validation,
/*! <a href="http://eprint.iacr.org/2009/408">A Secure and Efficient Authenticated DiffieHellman Protocol</a> /*! <a href="http://eprint.iacr.org/2009/408">A Secure and Efficient Authenticated DiffieHellman Protocol</a>
Note: this is FHMQV, Protocol 5, from page 11; and not FHMQV-C. Note: this is FHMQV, Protocol 5, from page 11; and not FHMQV-C.
*/ */
template <class GROUP_PARAMETERS, class COFACTOR_OPTION = CPP_TYPENAME GROUP_PARAMETERS::DefaultCofactorOption, class HASH = SHA512> template <class GROUP_PARAMETERS, class COFACTOR_OPTION = CPP_TYPENAME GROUP_PARAMETERS::DefaultCofactorOption, class HASH = SHA512>
class FHMQV_Domain: public AuthenticatedKeyAgreementDomain class FHMQV_Domain: public AuthenticatedKeyAgreementDomain
{ {
public: public:
typedef GROUP_PARAMETERS GroupParameters; typedef GROUP_PARAMETERS GroupParameters;
typedef typename GroupParameters::Element Element; typedef typename GroupParameters::Element Element;
typedef FHMQV_Domain<GROUP_PARAMETERS, COFACTOR_OPTION, HASH> Domain; typedef FHMQV_Domain<GROUP_PARAMETERS, COFACTOR_OPTION, HASH> Domain;
FHMQV_Domain(bool clientRole = true): m_role(clientRole ? RoleClient : RoleServer) {} FHMQV_Domain(bool clientRole = true): m_role(clientRole ? RoleClient : RoleServer) {}
FHMQV_Domain(const GroupParameters &params, bool clientRole = true) FHMQV_Domain(const GroupParameters &params, bool clientRole = true)
: m_role(clientRole ? RoleClient : RoleServer), m_groupParameters(params) {} : m_role(clientRole ? RoleClient : RoleServer), m_groupParameters(params) {}
FHMQV_Domain(BufferedTransformation &bt, bool clientRole = true) FHMQV_Domain(BufferedTransformation &bt, bool clientRole = true)
: m_role(clientRole ? RoleClient : RoleServer) : m_role(clientRole ? RoleClient : RoleServer)
{m_groupParameters.BERDecode(bt);} {m_groupParameters.BERDecode(bt);}
template <class T1> template <class T1>
FHMQV_Domain(T1 v1, bool clientRole = true) FHMQV_Domain(T1 v1, bool clientRole = true)
: m_role(clientRole ? RoleClient : RoleServer) : m_role(clientRole ? RoleClient : RoleServer)
{m_groupParameters.Initialize(v1);} {m_groupParameters.Initialize(v1);}
template <class T1, class T2> template <class T1, class T2>
FHMQV_Domain(T1 v1, T2 v2, bool clientRole = true) FHMQV_Domain(T1 v1, T2 v2, bool clientRole = true)
: m_role(clientRole ? RoleClient : RoleServer) : m_role(clientRole ? RoleClient : RoleServer)
{m_groupParameters.Initialize(v1, v2);} {m_groupParameters.Initialize(v1, v2);}
template <class T1, class T2, class T3> template <class T1, class T2, class T3>
FHMQV_Domain(T1 v1, T2 v2, T3 v3, bool clientRole = true) FHMQV_Domain(T1 v1, T2 v2, T3 v3, bool clientRole = true)
: m_role(clientRole ? RoleClient : RoleServer) : m_role(clientRole ? RoleClient : RoleServer)
{m_groupParameters.Initialize(v1, v2, v3);} {m_groupParameters.Initialize(v1, v2, v3);}
template <class T1, class T2, class T3, class T4> template <class T1, class T2, class T3, class T4>
FHMQV_Domain(T1 v1, T2 v2, T3 v3, T4 v4, bool clientRole = true) FHMQV_Domain(T1 v1, T2 v2, T3 v3, T4 v4, bool clientRole = true)
: m_role(clientRole ? RoleClient : RoleServer) : m_role(clientRole ? RoleClient : RoleServer)
{m_groupParameters.Initialize(v1, v2, v3, v4);} {m_groupParameters.Initialize(v1, v2, v3, v4);}
protected: protected:
inline void Hash(const Element* sigma, inline void Hash(const Element* sigma,
const byte* e1, size_t e1len, const byte* e2, size_t e2len, const byte* e1, size_t e1len, const byte* e2, size_t e2len,
const byte* s1, size_t s1len, const byte* s2, size_t s2len, const byte* s1, size_t s1len, const byte* s2, size_t s2len,
byte* digest, size_t dlen) const byte* digest, size_t dlen) const
{ {
HASH hash; HASH hash;
size_t idx = 0, req = dlen; size_t idx = 0, req = dlen;
size_t blk = std::min(dlen, (size_t)HASH::DIGESTSIZE); size_t blk = std::min(dlen, (size_t)HASH::DIGESTSIZE);
if(sigma) if(sigma)
{ {
Integer x = GetAbstractGroupParameters().ConvertElementToInteger(*sigma); Integer x = GetAbstractGroupParameters().ConvertElementToInteger(*sigma);
SecByteBlock sbb(x.MinEncodedSize()); SecByteBlock sbb(x.MinEncodedSize());
x.Encode(sbb.BytePtr(), sbb.SizeInBytes()); x.Encode(sbb.BytePtr(), sbb.SizeInBytes());
hash.Update(sbb.BytePtr(), sbb.SizeInBytes()); hash.Update(sbb.BytePtr(), sbb.SizeInBytes());
} }
hash.Update(e1, e1len); hash.Update(e1, e1len);
hash.Update(e2, e2len); hash.Update(e2, e2len);
hash.Update(s1, s1len); hash.Update(s1, s1len);
hash.Update(s2, s2len); hash.Update(s2, s2len);
hash.TruncatedFinal(digest, blk); hash.TruncatedFinal(digest, blk);
req -= blk; req -= blk;
// All this to catch tail bytes for large curves and small hashes // All this to catch tail bytes for large curves and small hashes
while(req != 0) while(req != 0)
{ {
hash.Update(&digest[idx], (size_t)HASH::DIGESTSIZE); hash.Update(&digest[idx], (size_t)HASH::DIGESTSIZE);
idx += (size_t)HASH::DIGESTSIZE; idx += (size_t)HASH::DIGESTSIZE;
blk = std::min(req, (size_t)HASH::DIGESTSIZE); blk = std::min(req, (size_t)HASH::DIGESTSIZE);
hash.TruncatedFinal(&digest[idx], blk); hash.TruncatedFinal(&digest[idx], blk);
req -= blk; req -= blk;
} }
} }
public: public:
const GroupParameters & GetGroupParameters() const {return m_groupParameters;} const GroupParameters & GetGroupParameters() const {return m_groupParameters;}
GroupParameters & AccessGroupParameters(){return m_groupParameters;} GroupParameters & AccessGroupParameters(){return m_groupParameters;}
CryptoParameters & AccessCryptoParameters(){return AccessAbstractGroupParameters();} CryptoParameters & AccessCryptoParameters(){return AccessAbstractGroupParameters();}
//! return length of agreed value produced //! return length of agreed value produced
unsigned int AgreedValueLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(false);} unsigned int AgreedValueLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(false);}
//! return length of static private keys in this domain //! return length of static private keys in this domain
unsigned int StaticPrivateKeyLength() const {return GetAbstractGroupParameters().GetSubgroupOrder().ByteCount();} unsigned int StaticPrivateKeyLength() const {return GetAbstractGroupParameters().GetSubgroupOrder().ByteCount();}
//! return length of static public keys in this domain //! return length of static public keys in this domain
unsigned int StaticPublicKeyLength() const{return GetAbstractGroupParameters().GetEncodedElementSize(true);} unsigned int StaticPublicKeyLength() const{return GetAbstractGroupParameters().GetEncodedElementSize(true);}
//! generate static private key //! generate static private key
/*! \pre size of privateKey == PrivateStaticKeyLength() */ /*! \pre size of privateKey == PrivateStaticKeyLength() */
void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
{ {
Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent()); Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent());
x.Encode(privateKey, StaticPrivateKeyLength()); x.Encode(privateKey, StaticPrivateKeyLength());
} }
//! generate static public key //! generate static public key
/*! \pre size of publicKey == PublicStaticKeyLength() */ /*! \pre size of publicKey == PublicStaticKeyLength() */
void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
{ {
const DL_GroupParameters<Element> &params = GetAbstractGroupParameters(); const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
Integer x(privateKey, StaticPrivateKeyLength()); Integer x(privateKey, StaticPrivateKeyLength());
Element y = params.ExponentiateBase(x); Element y = params.ExponentiateBase(x);
params.EncodeElement(true, y, publicKey); params.EncodeElement(true, y, publicKey);
} }
unsigned int EphemeralPrivateKeyLength() const {return StaticPrivateKeyLength() + StaticPublicKeyLength();} unsigned int EphemeralPrivateKeyLength() const {return StaticPrivateKeyLength() + StaticPublicKeyLength();}
unsigned int EphemeralPublicKeyLength() const{return StaticPublicKeyLength();} unsigned int EphemeralPublicKeyLength() const{return StaticPublicKeyLength();}
//! return length of ephemeral private keys in this domain //! return length of ephemeral private keys in this domain
void GenerateEphemeralPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const void GenerateEphemeralPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
{ {
const DL_GroupParameters<Element> &params = GetAbstractGroupParameters(); const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
Integer x(rng, Integer::One(), params.GetMaxExponent()); Integer x(rng, Integer::One(), params.GetMaxExponent());
x.Encode(privateKey, StaticPrivateKeyLength()); x.Encode(privateKey, StaticPrivateKeyLength());
Element y = params.ExponentiateBase(x); Element y = params.ExponentiateBase(x);
params.EncodeElement(true, y, privateKey+StaticPrivateKeyLength()); params.EncodeElement(true, y, privateKey+StaticPrivateKeyLength());
} }
//! return length of ephemeral public keys in this domain //! return length of ephemeral public keys in this domain
void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
{ {
memcpy(publicKey, privateKey+StaticPrivateKeyLength(), EphemeralPublicKeyLength()); memcpy(publicKey, privateKey+StaticPrivateKeyLength(), EphemeralPublicKeyLength());
} }
//! derive agreed value from your private keys and couterparty's public keys, return false in case of failure //! derive agreed value from your private keys and couterparty's public keys, return false in case of failure
/*! \note The ephemeral public key will always be validated. /*! \note The ephemeral public key will always be validated.
If you have previously validated the static public key, use validateStaticOtherPublicKey=false to save time. If you have previously validated the static public key, use validateStaticOtherPublicKey=false to save time.
\pre size of agreedValue == AgreedValueLength() \pre size of agreedValue == AgreedValueLength()
\pre length of staticPrivateKey == StaticPrivateKeyLength() \pre length of staticPrivateKey == StaticPrivateKeyLength()
\pre length of ephemeralPrivateKey == EphemeralPrivateKeyLength() \pre length of ephemeralPrivateKey == EphemeralPrivateKeyLength()
\pre length of staticOtherPublicKey == StaticPublicKeyLength() \pre length of staticOtherPublicKey == StaticPublicKeyLength()
\pre length of ephemeralOtherPublicKey == EphemeralPublicKeyLength() \pre length of ephemeralOtherPublicKey == EphemeralPublicKeyLength()
*/ */
bool Agree(byte *agreedValue, bool Agree(byte *agreedValue,
const byte *staticPrivateKey, const byte *ephemeralPrivateKey, const byte *staticPrivateKey, const byte *ephemeralPrivateKey,
const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey, const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey,
bool validateStaticOtherPublicKey=true) const bool validateStaticOtherPublicKey=true) const
{ {
byte *XX = NULL, *YY = NULL, *AA = NULL, *BB = NULL; byte *XX = NULL, *YY = NULL, *AA = NULL, *BB = NULL;
size_t xxs = 0, yys = 0, aas = 0, bbs = 0; size_t xxs = 0, yys = 0, aas = 0, bbs = 0;
// Depending on the role, this will hold either A's or B's static // Depending on the role, this will hold either A's or B's static
// (long term) public key. AA or BB will then point into tt. // (long term) public key. AA or BB will then point into tt.
SecByteBlock tt(StaticPublicKeyLength()); SecByteBlock tt(StaticPublicKeyLength());
try try
{ {
const DL_GroupParameters<Element> &params = GetAbstractGroupParameters(); const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
if(m_role == RoleServer) if(m_role == RoleServer)
{ {
Integer b(staticPrivateKey, StaticPrivateKeyLength()); Integer b(staticPrivateKey, StaticPrivateKeyLength());
Element B = params.ExponentiateBase(b); Element B = params.ExponentiateBase(b);
params.EncodeElement(true, B, tt); params.EncodeElement(true, B, tt);
XX = const_cast<byte*>(ephemeralOtherPublicKey); XX = const_cast<byte*>(ephemeralOtherPublicKey);
xxs = EphemeralPublicKeyLength(); xxs = EphemeralPublicKeyLength();
YY = const_cast<byte*>(ephemeralPrivateKey) + StaticPrivateKeyLength(); YY = const_cast<byte*>(ephemeralPrivateKey) + StaticPrivateKeyLength();
yys = EphemeralPublicKeyLength(); yys = EphemeralPublicKeyLength();
AA = const_cast<byte*>(staticOtherPublicKey); AA = const_cast<byte*>(staticOtherPublicKey);
aas = StaticPublicKeyLength(); aas = StaticPublicKeyLength();
BB = tt.BytePtr(); BB = tt.BytePtr();
bbs = tt.SizeInBytes(); bbs = tt.SizeInBytes();
} }
else if(m_role == RoleClient) else if(m_role == RoleClient)
{ {
Integer a(staticPrivateKey, StaticPrivateKeyLength()); Integer a(staticPrivateKey, StaticPrivateKeyLength());
Element A = params.ExponentiateBase(a); Element A = params.ExponentiateBase(a);
params.EncodeElement(true, A, tt); params.EncodeElement(true, A, tt);
XX = const_cast<byte*>(ephemeralPrivateKey) + StaticPrivateKeyLength(); XX = const_cast<byte*>(ephemeralPrivateKey) + StaticPrivateKeyLength();
xxs = EphemeralPublicKeyLength(); xxs = EphemeralPublicKeyLength();
YY = const_cast<byte*>(ephemeralOtherPublicKey); YY = const_cast<byte*>(ephemeralOtherPublicKey);
yys = EphemeralPublicKeyLength(); yys = EphemeralPublicKeyLength();
AA = tt.BytePtr(); AA = tt.BytePtr();
aas = tt.SizeInBytes(); aas = tt.SizeInBytes();
BB = const_cast<byte*>(staticOtherPublicKey); BB = const_cast<byte*>(staticOtherPublicKey);
bbs = StaticPublicKeyLength(); bbs = StaticPublicKeyLength();
} }
else else
{ {
assert(0); assert(0);
return false; return false;
} }
// DecodeElement calls ValidateElement at level 1. Level 1 only calls // DecodeElement calls ValidateElement at level 1. Level 1 only calls
// VerifyPoint to ensure the element is in G*. If the other's PublicKey is // VerifyPoint to ensure the element is in G*. If the other's PublicKey is
// requested to be validated, we manually call ValidateElement at level 3. // requested to be validated, we manually call ValidateElement at level 3.
Element VV1 = params.DecodeElement(staticOtherPublicKey, false); Element VV1 = params.DecodeElement(staticOtherPublicKey, false);
if(!params.ValidateElement(validateStaticOtherPublicKey ? 3 : 1, VV1, NULL)) if(!params.ValidateElement(validateStaticOtherPublicKey ? 3 : 1, VV1, NULL))
return false; return false;
// DecodeElement calls ValidateElement at level 1. Level 1 only calls // DecodeElement calls ValidateElement at level 1. Level 1 only calls
// VerifyPoint to ensure the element is in G*. Crank it up. // VerifyPoint to ensure the element is in G*. Crank it up.
Element VV2 = params.DecodeElement(ephemeralOtherPublicKey, false); Element VV2 = params.DecodeElement(ephemeralOtherPublicKey, false);
if(!params.ValidateElement(3, VV2, NULL)) if(!params.ValidateElement(3, VV2, NULL))
return false; return false;
const Integer& p = params.GetGroupOrder(); const Integer& p = params.GetGroupOrder();
const Integer& q = params.GetSubgroupOrder(); const Integer& q = params.GetSubgroupOrder();
const unsigned int len /*bytes*/ = (((q.BitCount()+1)/2 +7)/8); const unsigned int len /*bytes*/ = (((q.BitCount()+1)/2 +7)/8);
Integer d, e; Integer d, e;
SecByteBlock dd(len), ee(len); SecByteBlock dd(len), ee(len);
Hash(NULL, XX, xxs, YY, yys, AA, aas, BB, bbs, dd.BytePtr(), dd.SizeInBytes()); Hash(NULL, XX, xxs, YY, yys, AA, aas, BB, bbs, dd.BytePtr(), dd.SizeInBytes());
d.Decode(dd.BytePtr(), dd.SizeInBytes()); d.Decode(dd.BytePtr(), dd.SizeInBytes());
Hash(NULL, YY, yys, XX, xxs, AA, aas, BB, bbs, ee.BytePtr(), ee.SizeInBytes()); Hash(NULL, YY, yys, XX, xxs, AA, aas, BB, bbs, ee.BytePtr(), ee.SizeInBytes());
e.Decode(ee.BytePtr(), ee.SizeInBytes()); e.Decode(ee.BytePtr(), ee.SizeInBytes());
Element sigma; Element sigma;
if(m_role == RoleServer) if(m_role == RoleServer)
{ {
Integer y(ephemeralPrivateKey, StaticPrivateKeyLength()); Integer y(ephemeralPrivateKey, StaticPrivateKeyLength());
Integer b(staticPrivateKey, StaticPrivateKeyLength()); Integer b(staticPrivateKey, StaticPrivateKeyLength());
Integer s_B = (y + e * b) % q; Integer s_B = (y + e * b) % q;
Element A = params.DecodeElement(AA, false); Element A = params.DecodeElement(AA, false);
Element X = params.DecodeElement(XX, false); Element X = params.DecodeElement(XX, false);
Element t1 = params.ExponentiateElement(A, d); Element t1 = params.ExponentiateElement(A, d);
Element t2 = m_groupParameters.MultiplyElements(X, t1); Element t2 = m_groupParameters.MultiplyElements(X, t1);
sigma = params.ExponentiateElement(t2, s_B); sigma = params.ExponentiateElement(t2, s_B);
} }
else else
{ {
Integer x(ephemeralPrivateKey, StaticPrivateKeyLength()); Integer x(ephemeralPrivateKey, StaticPrivateKeyLength());
Integer a(staticPrivateKey, StaticPrivateKeyLength()); Integer a(staticPrivateKey, StaticPrivateKeyLength());
Integer s_A = (x + d * a) % q; Integer s_A = (x + d * a) % q;
Element B = params.DecodeElement(BB, false); Element B = params.DecodeElement(BB, false);
Element Y = params.DecodeElement(YY, false); Element Y = params.DecodeElement(YY, false);
Element t1 = params.ExponentiateElement(B, e); Element t1 = params.ExponentiateElement(B, e);
Element t2 = m_groupParameters.MultiplyElements(Y, t1); Element t2 = m_groupParameters.MultiplyElements(Y, t1);
sigma = params.ExponentiateElement(t2, s_A); sigma = params.ExponentiateElement(t2, s_A);
} }
Hash(&sigma, XX, xxs, YY, yys, AA, aas, BB, bbs, agreedValue, AgreedValueLength()); Hash(&sigma, XX, xxs, YY, yys, AA, aas, BB, bbs, agreedValue, AgreedValueLength());
} }
catch (DL_BadElement &) catch (DL_BadElement &)
{ {
return false; return false;
} }
return true; return true;
} }
private: private:
// The paper uses Initiator and Recipient - make it classical. // The paper uses Initiator and Recipient - make it classical.
enum KeyAgreementRole{ RoleServer = 1, RoleClient }; enum KeyAgreementRole{ RoleServer = 1, RoleClient };
DL_GroupParameters<Element> & AccessAbstractGroupParameters() {return m_groupParameters;} DL_GroupParameters<Element> & AccessAbstractGroupParameters() {return m_groupParameters;}
const DL_GroupParameters<Element> & GetAbstractGroupParameters() const{return m_groupParameters;} const DL_GroupParameters<Element> & GetAbstractGroupParameters() const{return m_groupParameters;}
KeyAgreementRole m_role; KeyAgreementRole m_role;
GroupParameters m_groupParameters; GroupParameters m_groupParameters;
}; };
//! Fully Hashed Menezes-Qu-Vanstone in GF(p) with key validation, //! Fully Hashed Menezes-Qu-Vanstone in GF(p) with key validation,
/*! <a href="http://eprint.iacr.org/2009/408">A Secure and Efficient Authenticated DiffieHellman Protocol</a> /*! <a href="http://eprint.iacr.org/2009/408">A Secure and Efficient Authenticated DiffieHellman Protocol</a>
Note: this is FHMQV, Protocol 5, from page 11; and not FHMQV-C. Note: this is FHMQV, Protocol 5, from page 11; and not FHMQV-C.
*/ */
typedef FHMQV_Domain<DL_GroupParameters_GFP_DefaultSafePrime> FullyHashedMQV; typedef FHMQV_Domain<DL_GroupParameters_GFP_DefaultSafePrime> FullyHashedMQV;
NAMESPACE_END NAMESPACE_END
#endif #endif

View File

@ -1,14 +1,14 @@
// hmqv.cpp - written and placed in the public domain by Uri Blumenthal // hmqv.cpp - written and placed in the public domain by Uri Blumenthal
// Shamelessly based upon Jeffrey Walton's FHMQV and Wei Dai's MQV source files // Shamelessly based upon Jeffrey Walton's FHMQV and Wei Dai's MQV source files
#include "pch.h" #include "pch.h"
#include "hmqv.h" #include "hmqv.h"
NAMESPACE_BEGIN(CryptoPP) NAMESPACE_BEGIN(CryptoPP)
void TestInstantiations_HMQV() void TestInstantiations_HMQV()
{ {
HashedMQV hmqv; HashedMQV hmqv;
} }
NAMESPACE_END NAMESPACE_END

606
hmqv.h
View File

@ -1,303 +1,303 @@
// hmqv.h - written and placed in the public domain by Uri Blumenthal // hmqv.h - written and placed in the public domain by Uri Blumenthal
// Shamelessly based upon Jeffrey Walton's FHMQV and Wei Dai's MQV source files // Shamelessly based upon Jeffrey Walton's FHMQV and Wei Dai's MQV source files
#ifndef CRYPTOPP_HMQV_H #ifndef CRYPTOPP_HMQV_H
#define CRYPTOPP_HMQV_H #define CRYPTOPP_HMQV_H
/** \file /** \file
*/ */
#include "gfpcrypt.h" #include "gfpcrypt.h"
#include "algebra.h" #include "algebra.h"
#include "sha.h" #include "sha.h"
NAMESPACE_BEGIN(CryptoPP) NAMESPACE_BEGIN(CryptoPP)
//! Hashed Menezes-Qu-Vanstone in GF(p) with key validation, //! Hashed Menezes-Qu-Vanstone in GF(p) with key validation,
/*! <a href="http://eprint.iacr.org/2005/176">HMQV: A High-Performance Secure Diffie-Hellman Protocol</a> /*! <a href="http://eprint.iacr.org/2005/176">HMQV: A High-Performance Secure Diffie-Hellman Protocol</a>
Note: this implements HMQV only. HMQV-C (with Key Confirmation) will be provided separately. Note: this implements HMQV only. HMQV-C (with Key Confirmation) will be provided separately.
*/ */
template <class GROUP_PARAMETERS, class COFACTOR_OPTION = CPP_TYPENAME GROUP_PARAMETERS::DefaultCofactorOption, class HASH = SHA512> template <class GROUP_PARAMETERS, class COFACTOR_OPTION = CPP_TYPENAME GROUP_PARAMETERS::DefaultCofactorOption, class HASH = SHA512>
class HMQV_Domain: public AuthenticatedKeyAgreementDomain class HMQV_Domain: public AuthenticatedKeyAgreementDomain
{ {
public: public:
typedef GROUP_PARAMETERS GroupParameters; typedef GROUP_PARAMETERS GroupParameters;
typedef typename GroupParameters::Element Element; typedef typename GroupParameters::Element Element;
typedef HMQV_Domain<GROUP_PARAMETERS, COFACTOR_OPTION, HASH> Domain; typedef HMQV_Domain<GROUP_PARAMETERS, COFACTOR_OPTION, HASH> Domain;
HMQV_Domain(bool clientRole = true): m_role(clientRole ? RoleClient : RoleServer) {} HMQV_Domain(bool clientRole = true): m_role(clientRole ? RoleClient : RoleServer) {}
HMQV_Domain(const GroupParameters &params, bool clientRole = true) HMQV_Domain(const GroupParameters &params, bool clientRole = true)
: m_role(clientRole ? RoleClient : RoleServer), m_groupParameters(params) {} : m_role(clientRole ? RoleClient : RoleServer), m_groupParameters(params) {}
HMQV_Domain(BufferedTransformation &bt, bool clientRole = true) HMQV_Domain(BufferedTransformation &bt, bool clientRole = true)
: m_role(clientRole ? RoleClient : RoleServer) : m_role(clientRole ? RoleClient : RoleServer)
{m_groupParameters.BERDecode(bt);} {m_groupParameters.BERDecode(bt);}
template <class T1> template <class T1>
HMQV_Domain(T1 v1, bool clientRole = true) HMQV_Domain(T1 v1, bool clientRole = true)
: m_role(clientRole ? RoleClient : RoleServer) : m_role(clientRole ? RoleClient : RoleServer)
{m_groupParameters.Initialize(v1);} {m_groupParameters.Initialize(v1);}
template <class T1, class T2> template <class T1, class T2>
HMQV_Domain(T1 v1, T2 v2, bool clientRole = true) HMQV_Domain(T1 v1, T2 v2, bool clientRole = true)
: m_role(clientRole ? RoleClient : RoleServer) : m_role(clientRole ? RoleClient : RoleServer)
{m_groupParameters.Initialize(v1, v2);} {m_groupParameters.Initialize(v1, v2);}
template <class T1, class T2, class T3> template <class T1, class T2, class T3>
HMQV_Domain(T1 v1, T2 v2, T3 v3, bool clientRole = true) HMQV_Domain(T1 v1, T2 v2, T3 v3, bool clientRole = true)
: m_role(clientRole ? RoleClient : RoleServer) : m_role(clientRole ? RoleClient : RoleServer)
{m_groupParameters.Initialize(v1, v2, v3);} {m_groupParameters.Initialize(v1, v2, v3);}
template <class T1, class T2, class T3, class T4> template <class T1, class T2, class T3, class T4>
HMQV_Domain(T1 v1, T2 v2, T3 v3, T4 v4, bool clientRole = true) HMQV_Domain(T1 v1, T2 v2, T3 v3, T4 v4, bool clientRole = true)
: m_role(clientRole ? RoleClient : RoleServer) : m_role(clientRole ? RoleClient : RoleServer)
{m_groupParameters.Initialize(v1, v2, v3, v4);} {m_groupParameters.Initialize(v1, v2, v3, v4);}
protected: protected:
// Hash invocation by client and server differ only in what keys // Hash invocation by client and server differ only in what keys
// each provides. // each provides.
inline void Hash(const Element* sigma, inline void Hash(const Element* sigma,
const byte* e1, size_t e1len, // Ephemeral key and key length const byte* e1, size_t e1len, // Ephemeral key and key length
const byte* s1, size_t s1len, // Static key and key length const byte* s1, size_t s1len, // Static key and key length
byte* digest, size_t dlen) const byte* digest, size_t dlen) const
{ {
HASH hash; HASH hash;
size_t idx = 0, req = dlen; size_t idx = 0, req = dlen;
size_t blk = std::min(dlen, (size_t)HASH::DIGESTSIZE); size_t blk = std::min(dlen, (size_t)HASH::DIGESTSIZE);
if(sigma) if(sigma)
{ {
if (e1len != 0 || s1len != 0) { if (e1len != 0 || s1len != 0) {
assert(0); assert(0);
} }
Integer x = GetAbstractGroupParameters().ConvertElementToInteger(*sigma); Integer x = GetAbstractGroupParameters().ConvertElementToInteger(*sigma);
SecByteBlock sbb(x.MinEncodedSize()); SecByteBlock sbb(x.MinEncodedSize());
x.Encode(sbb.BytePtr(), sbb.SizeInBytes()); x.Encode(sbb.BytePtr(), sbb.SizeInBytes());
hash.Update(sbb.BytePtr(), sbb.SizeInBytes()); hash.Update(sbb.BytePtr(), sbb.SizeInBytes());
} else { } else {
if (e1len == 0 || s1len == 0) { if (e1len == 0 || s1len == 0) {
assert(0); assert(0);
} }
hash.Update(e1, e1len); hash.Update(e1, e1len);
hash.Update(s1, s1len); hash.Update(s1, s1len);
} }
hash.TruncatedFinal(digest, blk); hash.TruncatedFinal(digest, blk);
req -= blk; req -= blk;
// All this to catch tail bytes for large curves and small hashes // All this to catch tail bytes for large curves and small hashes
while(req != 0) while(req != 0)
{ {
hash.Update(&digest[idx], (size_t)HASH::DIGESTSIZE); hash.Update(&digest[idx], (size_t)HASH::DIGESTSIZE);
idx += (size_t)HASH::DIGESTSIZE; idx += (size_t)HASH::DIGESTSIZE;
blk = std::min(req, (size_t)HASH::DIGESTSIZE); blk = std::min(req, (size_t)HASH::DIGESTSIZE);
hash.TruncatedFinal(&digest[idx], blk); hash.TruncatedFinal(&digest[idx], blk);
req -= blk; req -= blk;
} }
} }
public: public:
const GroupParameters & GetGroupParameters() const {return m_groupParameters;} const GroupParameters & GetGroupParameters() const {return m_groupParameters;}
GroupParameters & AccessGroupParameters(){return m_groupParameters;} GroupParameters & AccessGroupParameters(){return m_groupParameters;}
CryptoParameters & AccessCryptoParameters(){return AccessAbstractGroupParameters();} CryptoParameters & AccessCryptoParameters(){return AccessAbstractGroupParameters();}
//! return length of agreed value produced //! return length of agreed value produced
unsigned int AgreedValueLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(false);} unsigned int AgreedValueLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(false);}
//! return length of static private keys in this domain //! return length of static private keys in this domain
unsigned int StaticPrivateKeyLength() const {return GetAbstractGroupParameters().GetSubgroupOrder().ByteCount();} unsigned int StaticPrivateKeyLength() const {return GetAbstractGroupParameters().GetSubgroupOrder().ByteCount();}
//! return length of static public keys in this domain //! return length of static public keys in this domain
unsigned int StaticPublicKeyLength() const{return GetAbstractGroupParameters().GetEncodedElementSize(true);} unsigned int StaticPublicKeyLength() const{return GetAbstractGroupParameters().GetEncodedElementSize(true);}
//! generate static private key //! generate static private key
/*! \pre size of privateKey == PrivateStaticKeyLength() */ /*! \pre size of privateKey == PrivateStaticKeyLength() */
void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
{ {
Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent()); Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent());
x.Encode(privateKey, StaticPrivateKeyLength()); x.Encode(privateKey, StaticPrivateKeyLength());
} }
//! generate static public key //! generate static public key
/*! \pre size of publicKey == PublicStaticKeyLength() */ /*! \pre size of publicKey == PublicStaticKeyLength() */
void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
{ {
const DL_GroupParameters<Element> &params = GetAbstractGroupParameters(); const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
Integer x(privateKey, StaticPrivateKeyLength()); Integer x(privateKey, StaticPrivateKeyLength());
Element y = params.ExponentiateBase(x); Element y = params.ExponentiateBase(x);
params.EncodeElement(true, y, publicKey); params.EncodeElement(true, y, publicKey);
} }
unsigned int EphemeralPrivateKeyLength() const {return StaticPrivateKeyLength() + StaticPublicKeyLength();} unsigned int EphemeralPrivateKeyLength() const {return StaticPrivateKeyLength() + StaticPublicKeyLength();}
unsigned int EphemeralPublicKeyLength() const{return StaticPublicKeyLength();} unsigned int EphemeralPublicKeyLength() const{return StaticPublicKeyLength();}
//! return length of ephemeral private keys in this domain //! return length of ephemeral private keys in this domain
void GenerateEphemeralPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const void GenerateEphemeralPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
{ {
const DL_GroupParameters<Element> &params = GetAbstractGroupParameters(); const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
Integer x(rng, Integer::One(), params.GetMaxExponent()); Integer x(rng, Integer::One(), params.GetMaxExponent());
x.Encode(privateKey, StaticPrivateKeyLength()); x.Encode(privateKey, StaticPrivateKeyLength());
Element y = params.ExponentiateBase(x); Element y = params.ExponentiateBase(x);
params.EncodeElement(true, y, privateKey+StaticPrivateKeyLength()); params.EncodeElement(true, y, privateKey+StaticPrivateKeyLength());
} }
//! return length of ephemeral public keys in this domain //! return length of ephemeral public keys in this domain
void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
{ {
memcpy(publicKey, privateKey+StaticPrivateKeyLength(), EphemeralPublicKeyLength()); memcpy(publicKey, privateKey+StaticPrivateKeyLength(), EphemeralPublicKeyLength());
} }
//! derive agreed value from your private keys and couterparty's public keys, return false in case of failure //! derive agreed value from your private keys and couterparty's public keys, return false in case of failure
/*! \note The ephemeral public key will always be validated. /*! \note The ephemeral public key will always be validated.
If you have previously validated the static public key, use validateStaticOtherPublicKey=false to save time. If you have previously validated the static public key, use validateStaticOtherPublicKey=false to save time.
\pre size of agreedValue == AgreedValueLength() \pre size of agreedValue == AgreedValueLength()
\pre length of staticPrivateKey == StaticPrivateKeyLength() \pre length of staticPrivateKey == StaticPrivateKeyLength()
\pre length of ephemeralPrivateKey == EphemeralPrivateKeyLength() \pre length of ephemeralPrivateKey == EphemeralPrivateKeyLength()
\pre length of staticOtherPublicKey == StaticPublicKeyLength() \pre length of staticOtherPublicKey == StaticPublicKeyLength()
\pre length of ephemeralOtherPublicKey == EphemeralPublicKeyLength() \pre length of ephemeralOtherPublicKey == EphemeralPublicKeyLength()
*/ */
bool Agree(byte *agreedValue, bool Agree(byte *agreedValue,
const byte *staticPrivateKey, const byte *ephemeralPrivateKey, const byte *staticPrivateKey, const byte *ephemeralPrivateKey,
const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey, const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey,
bool validateStaticOtherPublicKey=true) const bool validateStaticOtherPublicKey=true) const
{ {
byte *XX = NULL, *YY = NULL, *AA = NULL, *BB = NULL; byte *XX = NULL, *YY = NULL, *AA = NULL, *BB = NULL;
size_t xxs = 0, yys = 0, aas = 0, bbs = 0; size_t xxs = 0, yys = 0, aas = 0, bbs = 0;
// Depending on the role, this will hold either A's or B's static // Depending on the role, this will hold either A's or B's static
// (long term) public key. AA or BB will then point into tt. // (long term) public key. AA or BB will then point into tt.
SecByteBlock tt(StaticPublicKeyLength()); SecByteBlock tt(StaticPublicKeyLength());
try try
{ {
const DL_GroupParameters<Element> &params = GetAbstractGroupParameters(); const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
if(m_role == RoleServer) if(m_role == RoleServer)
{ {
Integer b(staticPrivateKey, StaticPrivateKeyLength()); Integer b(staticPrivateKey, StaticPrivateKeyLength());
Element B = params.ExponentiateBase(b); Element B = params.ExponentiateBase(b);
params.EncodeElement(true, B, tt); params.EncodeElement(true, B, tt);
XX = const_cast<byte*>(ephemeralOtherPublicKey); XX = const_cast<byte*>(ephemeralOtherPublicKey);
xxs = EphemeralPublicKeyLength(); xxs = EphemeralPublicKeyLength();
YY = const_cast<byte*>(ephemeralPrivateKey) + StaticPrivateKeyLength(); YY = const_cast<byte*>(ephemeralPrivateKey) + StaticPrivateKeyLength();
yys = EphemeralPublicKeyLength(); yys = EphemeralPublicKeyLength();
AA = const_cast<byte*>(staticOtherPublicKey); AA = const_cast<byte*>(staticOtherPublicKey);
aas = StaticPublicKeyLength(); aas = StaticPublicKeyLength();
BB = tt.BytePtr(); BB = tt.BytePtr();
bbs = tt.SizeInBytes(); bbs = tt.SizeInBytes();
} }
else if(m_role == RoleClient) else if(m_role == RoleClient)
{ {
Integer a(staticPrivateKey, StaticPrivateKeyLength()); Integer a(staticPrivateKey, StaticPrivateKeyLength());
Element A = params.ExponentiateBase(a); Element A = params.ExponentiateBase(a);
params.EncodeElement(true, A, tt); params.EncodeElement(true, A, tt);
XX = const_cast<byte*>(ephemeralPrivateKey) + StaticPrivateKeyLength(); XX = const_cast<byte*>(ephemeralPrivateKey) + StaticPrivateKeyLength();
xxs = EphemeralPublicKeyLength(); xxs = EphemeralPublicKeyLength();
YY = const_cast<byte*>(ephemeralOtherPublicKey); YY = const_cast<byte*>(ephemeralOtherPublicKey);
yys = EphemeralPublicKeyLength(); yys = EphemeralPublicKeyLength();
AA = tt.BytePtr(); AA = tt.BytePtr();
aas = tt.SizeInBytes(); aas = tt.SizeInBytes();
BB = const_cast<byte*>(staticOtherPublicKey); BB = const_cast<byte*>(staticOtherPublicKey);
bbs = StaticPublicKeyLength(); bbs = StaticPublicKeyLength();
} }
else else
{ {
assert(0); assert(0);
return false; return false;
} }
// DecodeElement calls ValidateElement at level 1. Level 1 only calls // DecodeElement calls ValidateElement at level 1. Level 1 only calls
// VerifyPoint to ensure the element is in G*. If the other's PublicKey is // VerifyPoint to ensure the element is in G*. If the other's PublicKey is
// requested to be validated, we manually call ValidateElement at level 3. // requested to be validated, we manually call ValidateElement at level 3.
Element VV1 = params.DecodeElement(staticOtherPublicKey, false); Element VV1 = params.DecodeElement(staticOtherPublicKey, false);
if(!params.ValidateElement(validateStaticOtherPublicKey ? 3 : 1, VV1, NULL)) if(!params.ValidateElement(validateStaticOtherPublicKey ? 3 : 1, VV1, NULL))
return false; return false;
// DecodeElement calls ValidateElement at level 1. Level 1 only calls // DecodeElement calls ValidateElement at level 1. Level 1 only calls
// VerifyPoint to ensure the element is in G*. Crank it up. // VerifyPoint to ensure the element is in G*. Crank it up.
Element VV2 = params.DecodeElement(ephemeralOtherPublicKey, false); Element VV2 = params.DecodeElement(ephemeralOtherPublicKey, false);
if(!params.ValidateElement(3, VV2, NULL)) if(!params.ValidateElement(3, VV2, NULL))
return false; return false;
// const Integer& p = params.GetGroupOrder(); // not used, remove later // const Integer& p = params.GetGroupOrder(); // not used, remove later
const Integer& q = params.GetSubgroupOrder(); const Integer& q = params.GetSubgroupOrder();
const unsigned int len /*bytes*/ = (((q.BitCount()+1)/2 +7)/8); const unsigned int len /*bytes*/ = (((q.BitCount()+1)/2 +7)/8);
Integer d, e; Integer d, e;
SecByteBlock dd(len), ee(len); SecByteBlock dd(len), ee(len);
// Compute $d = \hat{H}(X, \hat{B})$ // Compute $d = \hat{H}(X, \hat{B})$
Hash(NULL, XX, xxs, BB, bbs, dd.BytePtr(), dd.SizeInBytes()); Hash(NULL, XX, xxs, BB, bbs, dd.BytePtr(), dd.SizeInBytes());
d.Decode(dd.BytePtr(), dd.SizeInBytes()); d.Decode(dd.BytePtr(), dd.SizeInBytes());
// Compute $e = \hat{H}(Y, \hat{A})$ // Compute $e = \hat{H}(Y, \hat{A})$
Hash(NULL, YY, yys, AA, aas, ee.BytePtr(), ee.SizeInBytes()); Hash(NULL, YY, yys, AA, aas, ee.BytePtr(), ee.SizeInBytes());
e.Decode(ee.BytePtr(), ee.SizeInBytes()); e.Decode(ee.BytePtr(), ee.SizeInBytes());
Element sigma; Element sigma;
if(m_role == RoleServer) if(m_role == RoleServer)
{ {
Integer y(ephemeralPrivateKey, StaticPrivateKeyLength()); Integer y(ephemeralPrivateKey, StaticPrivateKeyLength());
Integer b(staticPrivateKey, StaticPrivateKeyLength()); Integer b(staticPrivateKey, StaticPrivateKeyLength());
Integer s_B = (y + e * b) % q; Integer s_B = (y + e * b) % q;
Element A = params.DecodeElement(AA, false); Element A = params.DecodeElement(AA, false);
Element X = params.DecodeElement(XX, false); Element X = params.DecodeElement(XX, false);
Element t1 = params.ExponentiateElement(A, d); Element t1 = params.ExponentiateElement(A, d);
Element t2 = m_groupParameters.MultiplyElements(X, t1); Element t2 = m_groupParameters.MultiplyElements(X, t1);
// $\sigma_B}=(X \cdot A^{d})^{s_B} // $\sigma_B}=(X \cdot A^{d})^{s_B}
sigma = params.ExponentiateElement(t2, s_B); sigma = params.ExponentiateElement(t2, s_B);
} }
else else
{ {
Integer x(ephemeralPrivateKey, StaticPrivateKeyLength()); Integer x(ephemeralPrivateKey, StaticPrivateKeyLength());
Integer a(staticPrivateKey, StaticPrivateKeyLength()); Integer a(staticPrivateKey, StaticPrivateKeyLength());
Integer s_A = (x + d * a) % q; Integer s_A = (x + d * a) % q;
Element B = params.DecodeElement(BB, false); Element B = params.DecodeElement(BB, false);
Element Y = params.DecodeElement(YY, false); Element Y = params.DecodeElement(YY, false);
Element t1 = params.ExponentiateElement(B, e); Element t1 = params.ExponentiateElement(B, e);
Element t2 = m_groupParameters.MultiplyElements(Y, t1); Element t2 = m_groupParameters.MultiplyElements(Y, t1);
// $\sigma_A}=(Y \cdot B^{e})^{s_A} // $\sigma_A}=(Y \cdot B^{e})^{s_A}
sigma = params.ExponentiateElement(t2, s_A); sigma = params.ExponentiateElement(t2, s_A);
} }
Hash(&sigma, NULL, 0, NULL, 0, agreedValue, AgreedValueLength()); Hash(&sigma, NULL, 0, NULL, 0, agreedValue, AgreedValueLength());
} }
catch (DL_BadElement &) catch (DL_BadElement &)
{ {
return false; return false;
} }
return true; return true;
} }
private: private:
// The paper uses Initiator and Recipient - make it classical. // The paper uses Initiator and Recipient - make it classical.
enum KeyAgreementRole{ RoleServer = 1, RoleClient }; enum KeyAgreementRole{ RoleServer = 1, RoleClient };
DL_GroupParameters<Element> & AccessAbstractGroupParameters() {return m_groupParameters;} DL_GroupParameters<Element> & AccessAbstractGroupParameters() {return m_groupParameters;}
const DL_GroupParameters<Element> & GetAbstractGroupParameters() const{return m_groupParameters;} const DL_GroupParameters<Element> & GetAbstractGroupParameters() const{return m_groupParameters;}
KeyAgreementRole m_role; KeyAgreementRole m_role;
GroupParameters m_groupParameters; GroupParameters m_groupParameters;
}; };
//! Hashed Menezes-Qu-Vanstone in GF(p) with key validation, //! Hashed Menezes-Qu-Vanstone in GF(p) with key validation,
/*! <a href="http://eprint.iacr.org/2005/176">HMQV: A High-Performance Secure Diffie-Hellman Protocol</a> /*! <a href="http://eprint.iacr.org/2005/176">HMQV: A High-Performance Secure Diffie-Hellman Protocol</a>
Note: this implements HMQV only. HMQV-C (with Key Confirmation) will be provided separately. Note: this implements HMQV only. HMQV-C (with Key Confirmation) will be provided separately.
*/ */
typedef HMQV_Domain<DL_GroupParameters_GFP_DefaultSafePrime> HashedMQV; typedef HMQV_Domain<DL_GroupParameters_GFP_DefaultSafePrime> HashedMQV;
NAMESPACE_END NAMESPACE_END
#endif #endif

8
mqv.h
View File

@ -46,7 +46,7 @@ public:
//! \brief Construct a MQV domain //! \brief Construct a MQV domain
//! \tparam T1 template parameter used as a constructor parameter //! \tparam T1 template parameter used as a constructor parameter
//! \tparam T2 template parameter used as a constructor parameter //! \tparam T2 template parameter used as a constructor parameter
//! \param v1 first parameter //! \param v1 first parameter
//! \param v2 second parameter //! \param v2 second parameter
//! \details v1 and v2 are passed directly to the GROUP_PARAMETERS object. //! \details v1 and v2 are passed directly to the GROUP_PARAMETERS object.
template <class T1, class T2> template <class T1, class T2>
@ -57,7 +57,7 @@ public:
//! \tparam T1 template parameter used as a constructor parameter //! \tparam T1 template parameter used as a constructor parameter
//! \tparam T2 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 T3 template parameter used as a constructor parameter
//! \param v1 first parameter //! \param v1 first parameter
//! \param v2 second parameter //! \param v2 second parameter
//! \param v3 third parameter //! \param v3 third parameter
//! \details v1, v2 and v3 are passed directly to the GROUP_PARAMETERS object. //! \details v1, v2 and v3 are passed directly to the GROUP_PARAMETERS object.
@ -70,7 +70,7 @@ public:
//! \tparam T2 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 T3 template parameter used as a constructor parameter
//! \tparam T4 template parameter used as a constructor parameter //! \tparam T4 template parameter used as a constructor parameter
//! \param v1 first parameter //! \param v1 first parameter
//! \param v2 second parameter //! \param v2 second parameter
//! \param v3 third parameter //! \param v3 third parameter
//! \param v4 third parameter //! \param v4 third parameter
@ -156,7 +156,7 @@ public:
} }
bool Agree(byte *agreedValue, bool Agree(byte *agreedValue,
const byte *staticPrivateKey, const byte *ephemeralPrivateKey, const byte *staticPrivateKey, const byte *ephemeralPrivateKey,
const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey, const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey,
bool validateStaticOtherPublicKey=true) const bool validateStaticOtherPublicKey=true) const
{ {