diff --git a/fhmqv.h b/fhmqv.h
index d777c342..5d2f5135 100644
--- a/fhmqv.h
+++ b/fhmqv.h
@@ -1,11 +1,11 @@
-// fhmqv.h - written and placed in the public domain by Jeffrey Walton
-// Shamelessly based upon Wei Dai's MQV source files
+// fhmqv.h - written and placed in the public domain by Jeffrey Walton, Ray Clayton and Uri Blumenthal
+// Shamelessly based upon Wei Dai's MQV source files
#ifndef CRYPTOPP_FHMQV_H
#define CRYPTOPP_FHMQV_H
-/** \file
-*/
+//! \file fhmqv.h
+//! \brief Classes for Fully Hashed Menezes-Qu-Vanstone key agreement in GF(p)
#include "gfpcrypt.h"
#include "algebra.h"
@@ -13,12 +13,12 @@
NAMESPACE_BEGIN(CryptoPP)
-//! Fully Hashed Menezes-Qu-Vanstone in GF(p) with key validation,
-/*! A Secure and Efficient Authenticated Diffie–Hellman Protocol
- Note: this is FHMQV, Protocol 5, from page 11; and not FHMQV-C.
-*/
+//! \brief Fully Hashed Menezes-Qu-Vanstone in GF(p)
+//! \details This implementation follows Augustin P. Sarr and Philippe Elbaz–Vincent, and Jean–Claude Bajard's
+//! A Secure and Efficient Authenticated Diffie-Hellman Protocol.
+//! Note: this is FHMQV, Protocol 5, from page 11; and not FHMQV-C.
template
-class FHMQV_Domain: public AuthenticatedKeyAgreementDomain
+class FHMQV_Domain : public AuthenticatedKeyAgreementDomain
{
public:
typedef GROUP_PARAMETERS GroupParameters;
@@ -54,46 +54,6 @@ public:
: m_role(clientRole ? RoleClient : RoleServer)
{m_groupParameters.Initialize(v1, v2, v3, v4);}
-protected:
-
- inline void Hash(const Element* sigma,
- const byte* e1, size_t e1len, const byte* e2, size_t e2len,
- const byte* s1, size_t s1len, const byte* s2, size_t s2len,
- byte* digest, size_t dlen) const
- {
- HASH hash;
- size_t idx = 0, req = dlen;
- size_t blk = std::min(dlen, (size_t)HASH::DIGESTSIZE);
-
- if(sigma)
- {
- Integer x = GetAbstractGroupParameters().ConvertElementToInteger(*sigma);
- SecByteBlock sbb(x.MinEncodedSize());
- x.Encode(sbb.BytePtr(), sbb.SizeInBytes());
- hash.Update(sbb.BytePtr(), sbb.SizeInBytes());
- }
-
- hash.Update(e1, e1len);
- hash.Update(e2, e2len);
- hash.Update(s1, s1len);
- hash.Update(s2, s2len);
-
- hash.TruncatedFinal(digest, blk);
- req -= blk;
-
- // All this to catch tail bytes for large curves and small hashes
- while(req != 0)
- {
- hash.Update(&digest[idx], (size_t)HASH::DIGESTSIZE);
-
- idx += (size_t)HASH::DIGESTSIZE;
- blk = std::min(req, (size_t)HASH::DIGESTSIZE);
- hash.TruncatedFinal(&digest[idx], blk);
-
- req -= blk;
- }
- }
-
public:
const GroupParameters & GetGroupParameters() const {return m_groupParameters;}
@@ -271,6 +231,46 @@ public:
return true;
}
+protected:
+
+ inline void Hash(const Element* sigma,
+ const byte* e1, size_t e1len, const byte* e2, size_t e2len,
+ const byte* s1, size_t s1len, const byte* s2, size_t s2len,
+ byte* digest, size_t dlen) const
+ {
+ HASH hash;
+ size_t idx = 0, req = dlen;
+ size_t blk = std::min(dlen, (size_t)HASH::DIGESTSIZE);
+
+ if(sigma)
+ {
+ Integer x = GetAbstractGroupParameters().ConvertElementToInteger(*sigma);
+ SecByteBlock sbb(x.MinEncodedSize());
+ x.Encode(sbb.BytePtr(), sbb.SizeInBytes());
+ hash.Update(sbb.BytePtr(), sbb.SizeInBytes());
+ }
+
+ hash.Update(e1, e1len);
+ hash.Update(e2, e2len);
+ hash.Update(s1, s1len);
+ hash.Update(s2, s2len);
+
+ hash.TruncatedFinal(digest, blk);
+ req -= blk;
+
+ // All this to catch tail bytes for large curves and small hashes
+ while(req != 0)
+ {
+ hash.Update(&digest[idx], (size_t)HASH::DIGESTSIZE);
+
+ idx += (size_t)HASH::DIGESTSIZE;
+ blk = std::min(req, (size_t)HASH::DIGESTSIZE);
+ hash.TruncatedFinal(&digest[idx], blk);
+
+ req -= blk;
+ }
+ }
+
private:
// The paper uses Initiator and Recipient - make it classical.
@@ -279,14 +279,14 @@ private:
DL_GroupParameters & AccessAbstractGroupParameters() {return m_groupParameters;}
const DL_GroupParameters & GetAbstractGroupParameters() const{return m_groupParameters;}
- KeyAgreementRole m_role;
GroupParameters m_groupParameters;
+ KeyAgreementRole m_role;
};
-//! Fully Hashed Menezes-Qu-Vanstone in GF(p) with key validation,
-/*! A Secure and Efficient Authenticated Diffie–Hellman Protocol
- Note: this is FHMQV, Protocol 5, from page 11; and not FHMQV-C.
-*/
+//! \brief Fully Hashed Menezes-Qu-Vanstone in GF(p)
+//! \details This implementation follows Augustin P. Sarr and Philippe Elbaz–Vincent, and Jean–Claude Bajard's
+//! A Secure and Efficient Authenticated Diffie-Hellman Protocol.
+//! Note: this is FHMQV, Protocol 5, from page 11; and not FHMQV-C.
typedef FHMQV_Domain FullyHashedMQV;
NAMESPACE_END
diff --git a/hmqv.h b/hmqv.h
index d2c692a8..e44e0a24 100644
--- a/hmqv.h
+++ b/hmqv.h
@@ -1,11 +1,11 @@
// 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
#define CRYPTOPP_HMQV_H
-/** \file
-*/
+//! \file hmqv.h
+//! \brief Classes for Hashed Menezes-Qu-Vanstone key agreement in GF(p)
#include "gfpcrypt.h"
#include "algebra.h"
@@ -13,10 +13,9 @@
NAMESPACE_BEGIN(CryptoPP)
-//! Hashed Menezes-Qu-Vanstone in GF(p) with key validation,
-/*! HMQV: A High-Performance Secure Diffie-Hellman Protocol
- Note: this implements HMQV only. HMQV-C (with Key Confirmation) will be provided separately.
-*/
+//! \brief Hashed Menezes-Qu-Vanstone in GF(p)
+//! \details This implementation follows Hugo Krawczyk's HMQV: A High-Performance
+//! Secure Diffie-Hellman Protocol. Note: this implements HMQV only. HMQV-C with Key Confirmation is not provided.
template
class HMQV_Domain: public AuthenticatedKeyAgreementDomain
{
@@ -54,52 +53,6 @@ public:
: m_role(clientRole ? RoleClient : RoleServer)
{m_groupParameters.Initialize(v1, v2, v3, v4);}
-protected:
- // Hash invocation by client and server differ only in what keys
- // each provides.
-
- inline void Hash(const Element* sigma,
- const byte* e1, size_t e1len, // Ephemeral key and key length
- const byte* s1, size_t s1len, // Static key and key length
- byte* digest, size_t dlen) const
- {
- HASH hash;
- size_t idx = 0, req = dlen;
- size_t blk = std::min(dlen, (size_t)HASH::DIGESTSIZE);
-
- if(sigma)
- {
- if (e1len != 0 || s1len != 0) {
- assert(0);
- }
- Integer x = GetAbstractGroupParameters().ConvertElementToInteger(*sigma);
- SecByteBlock sbb(x.MinEncodedSize());
- x.Encode(sbb.BytePtr(), sbb.SizeInBytes());
- hash.Update(sbb.BytePtr(), sbb.SizeInBytes());
- } else {
- if (e1len == 0 || s1len == 0) {
- assert(0);
- }
- hash.Update(e1, e1len);
- hash.Update(s1, s1len);
- }
-
- hash.TruncatedFinal(digest, blk);
- req -= blk;
-
- // All this to catch tail bytes for large curves and small hashes
- while(req != 0)
- {
- hash.Update(&digest[idx], (size_t)HASH::DIGESTSIZE);
-
- idx += (size_t)HASH::DIGESTSIZE;
- blk = std::min(req, (size_t)HASH::DIGESTSIZE);
- hash.TruncatedFinal(&digest[idx], blk);
-
- req -= blk;
- }
- }
-
public:
const GroupParameters & GetGroupParameters() const {return m_groupParameters;}
@@ -225,7 +178,7 @@ public:
if(!params.ValidateElement(3, VV2, NULL))
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 unsigned int len /*bytes*/ = (((q.BitCount()+1)/2 +7)/8);
@@ -253,7 +206,7 @@ public:
Element t1 = params.ExponentiateElement(A, d);
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);
}
else
@@ -268,7 +221,7 @@ public:
Element t1 = params.ExponentiateElement(B, e);
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);
}
Hash(&sigma, NULL, 0, NULL, 0, agreedValue, AgreedValueLength());
@@ -280,6 +233,52 @@ public:
return true;
}
+protected:
+ // Hash invocation by client and server differ only in what keys
+ // each provides.
+
+ inline void Hash(const Element* sigma,
+ const byte* e1, size_t e1len, // Ephemeral key and key length
+ const byte* s1, size_t s1len, // Static key and key length
+ byte* digest, size_t dlen) const
+ {
+ HASH hash;
+ size_t idx = 0, req = dlen;
+ size_t blk = std::min(dlen, (size_t)HASH::DIGESTSIZE);
+
+ if(sigma)
+ {
+ if (e1len != 0 || s1len != 0) {
+ assert(0);
+ }
+ Integer x = GetAbstractGroupParameters().ConvertElementToInteger(*sigma);
+ SecByteBlock sbb(x.MinEncodedSize());
+ x.Encode(sbb.BytePtr(), sbb.SizeInBytes());
+ hash.Update(sbb.BytePtr(), sbb.SizeInBytes());
+ } else {
+ if (e1len == 0 || s1len == 0) {
+ assert(0);
+ }
+ hash.Update(e1, e1len);
+ hash.Update(s1, s1len);
+ }
+
+ hash.TruncatedFinal(digest, blk);
+ req -= blk;
+
+ // All this to catch tail bytes for large curves and small hashes
+ while(req != 0)
+ {
+ hash.Update(&digest[idx], (size_t)HASH::DIGESTSIZE);
+
+ idx += (size_t)HASH::DIGESTSIZE;
+ blk = std::min(req, (size_t)HASH::DIGESTSIZE);
+ hash.TruncatedFinal(&digest[idx], blk);
+
+ req -= blk;
+ }
+ }
+
private:
// The paper uses Initiator and Recipient - make it classical.
@@ -288,14 +287,13 @@ private:
DL_GroupParameters & AccessAbstractGroupParameters() {return m_groupParameters;}
const DL_GroupParameters & GetAbstractGroupParameters() const{return m_groupParameters;}
- KeyAgreementRole m_role;
GroupParameters m_groupParameters;
+ KeyAgreementRole m_role;
};
-//! Hashed Menezes-Qu-Vanstone in GF(p) with key validation,
-/*! HMQV: A High-Performance Secure Diffie-Hellman Protocol
- Note: this implements HMQV only. HMQV-C (with Key Confirmation) will be provided separately.
-*/
+//! \brief Hashed Menezes-Qu-Vanstone in GF(p)
+//! \details This implementation follows Hugo Krawczyk's HMQV: A High-Performance
+//! Secure Diffie-Hellman Protocol. Note: this implements HMQV only. HMQV-C with Key Confirmation is not provided.
typedef HMQV_Domain HashedMQV;
NAMESPACE_END