diff --git a/fhmqv.h b/fhmqv.h
index eaf6193b..7d2fc1ca 100644
--- a/fhmqv.h
+++ b/fhmqv.h
@@ -30,59 +30,144 @@ public:
virtual ~FHMQV_Domain() {}
- FHMQV_Domain(bool clientRole = true): m_role(clientRole ? RoleClient : RoleServer) {}
+ /// \brief Construct a FHMQV domain
+ /// \params clientRole flag indicating initiator or recipient
+ /// \details clientRole = true indicates initiator, and
+ /// clientRole = false indicates recipient or server.
+ FHMQV_Domain(bool clientRole = true)
+ : m_role(clientRole ? RoleClient : RoleServer) {}
+ /// \brief Construct a FHMQV domain
+ /// \param params group parameters and options
+ /// \details clientRole = true indicates initiator, and
+ /// clientRole = false indicates recipient or server.
FHMQV_Domain(const GroupParameters ¶ms, bool clientRole = true)
: m_role(clientRole ? RoleClient : RoleServer), m_groupParameters(params) {}
+ /// \brief Construct a FHMQV domain
+ /// \param bt BufferedTransformation with group parameters and options
+ /// \details clientRole = true indicates initiator, and
+ /// clientRole = false indicates recipient or server.
FHMQV_Domain(BufferedTransformation &bt, bool clientRole = true)
: m_role(clientRole ? RoleClient : RoleServer)
- {m_groupParameters.BERDecode(bt);}
+ {m_groupParameters.BERDecode(bt);}
+ /// \brief Construct a FHMQV 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.
+ /// \details clientRole = true indicates initiator, and
+ /// clientRole = false indicates recipient or server.
template
FHMQV_Domain(T1 v1, bool clientRole = true)
: m_role(clientRole ? RoleClient : RoleServer)
- {m_groupParameters.Initialize(v1);}
+ {m_groupParameters.Initialize(v1);}
+ /// \brief Construct a FHMQV 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.
+ /// \details clientRole = true indicates initiator, and
+ /// clientRole = false indicates recipient or server.
template
FHMQV_Domain(T1 v1, T2 v2, bool clientRole = true)
: m_role(clientRole ? RoleClient : RoleServer)
- {m_groupParameters.Initialize(v1, v2);}
+ {m_groupParameters.Initialize(v1, v2);}
+ /// \brief Construct a FHMQV 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.
+ /// \details clientRole = true indicates initiator, and
+ /// clientRole = false indicates recipient or server.
template
FHMQV_Domain(T1 v1, T2 v2, T3 v3, bool clientRole = true)
: m_role(clientRole ? RoleClient : RoleServer)
- {m_groupParameters.Initialize(v1, v2, v3);}
+ {m_groupParameters.Initialize(v1, v2, v3);}
+ /// \brief Construct a FHMQV 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.
+ /// \details clientRole = true indicates initiator, and
+ /// clientRole = false indicates recipient or server.
template
FHMQV_Domain(T1 v1, T2 v2, T3 v3, T4 v4, bool clientRole = true)
: m_role(clientRole ? RoleClient : RoleServer)
- {m_groupParameters.Initialize(v1, v2, v3, v4);}
+ {m_groupParameters.Initialize(v1, v2, v3, v4);}
public:
+ /// \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;}
- GroupParameters & AccessGroupParameters(){return m_groupParameters;}
- CryptoParameters & AccessCryptoParameters(){return AccessAbstractGroupParameters();}
+ /// \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;}
- /// return length of agreed value produced
- unsigned int AgreedValueLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(false);}
- /// return length of static private keys in this domain
- unsigned int StaticPrivateKeyLength() const {return GetAbstractGroupParameters().GetSubgroupOrder().ByteCount();}
- /// return length of static public keys in this domain
- unsigned int StaticPublicKeyLength() const{return GetAbstractGroupParameters().GetEncodedElementSize(true);}
+ /// \brief Retrieves the crypto parameters for this domain
+ /// \return the crypto parameters for this domain as a non-const reference
+ CryptoParameters & AccessCryptoParameters() {return AccessAbstractGroupParameters();}
- /// generate static private key
- /*! \pre size of privateKey == PrivateStaticKeyLength() */
+ /// \brief Provides the size of the agreed value
+ /// \return size of agreed value produced in this domain
+ /// \details The length is calculated using GetEncodedElementSize(false),
+ /// 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 GetEncodedElementSize(true),
+ /// 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
+ /// [1,MaxExponent()].
+ /// \pre COUNTOF(privateKey) == PrivateStaticKeyLength()
void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
{
Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent());
x.Encode(privateKey, StaticPrivateKeyLength());
}
- /// generate static public key
- /*! \pre size of publicKey == PublicStaticKeyLength() */
+ /// \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 COUNTOF(publicKey) == PublicStaticKeyLength()
void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
{
CRYPTOPP_UNUSED(rng);
@@ -112,15 +197,26 @@ public:
memcpy(publicKey, privateKey+StaticPrivateKeyLength(), EphemeralPublicKeyLength());
}
- /// 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.
- If you have previously validated the static public key, use validateStaticOtherPublicKey=false to save time.
- \pre size of agreedValue == AgreedValueLength()
- \pre length of staticPrivateKey == StaticPrivateKeyLength()
- \pre length of ephemeralPrivateKey == EphemeralPrivateKeyLength()
- \pre length of staticOtherPublicKey == StaticPublicKeyLength()
- \pre length of ephemeralOtherPublicKey == EphemeralPublicKeyLength()
- */
+ /// \brief Derive shared secre from your private keys and couterparty's public keys
+ /// \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 your ephemeral public key
+ /// \param validateStaticOtherPublicKey flag indicating validation
+ /// \details Agree() performs the authenticated key agreement. 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.
+ /// validateStaticOtherPublicKey determines how thoroughly other's
+ /// static public key is validated. If you have previously validated the
+ /// couterparty's static public key, then use
+ /// validateStaticOtherPublicKey=false to save time.
+ /// \pre size of agreedValue == AgreedValueLength()
+ /// \pre length of staticPrivateKey == StaticPrivateKeyLength()
+ /// \pre length of ephemeralPrivateKey == EphemeralPrivateKeyLength()
+ /// \pre length of staticOtherPublicKey == StaticPublicKeyLength()
+ /// \pre length of ephemeralOtherPublicKey == EphemeralPublicKeyLength()
bool Agree(byte *agreedValue,
const byte *staticPrivateKey, const byte *ephemeralPrivateKey,
const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey,
@@ -153,7 +249,7 @@ public:
BB = tt.BytePtr();
bbs = tt.SizeInBytes();
}
- else if(m_role == RoleClient)
+ else
{
Integer a(staticPrivateKey, StaticPrivateKeyLength());
Element A = params.ExponentiateBase(a);
@@ -168,24 +264,25 @@ public:
BB = staticOtherPublicKey;
bbs = StaticPublicKeyLength();
}
- else
- {
- CRYPTOPP_ASSERT(0);
- return false;
- }
// DecodeElement calls ValidateElement at level 1. Level 1 only calls
// 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.
Element VV1 = params.DecodeElement(staticOtherPublicKey, false);
if(!params.ValidateElement(validateStaticOtherPublicKey ? 3 : 1, VV1, NULLPTR))
+ {
+ CRYPTOPP_ASSERT(0);
return false;
+ }
// DecodeElement calls ValidateElement at level 1. Level 1 only calls
// VerifyPoint to ensure the element is in G*. Crank it up.
Element VV2 = params.DecodeElement(ephemeralOtherPublicKey, false);
if(!params.ValidateElement(3, VV2, NULLPTR))
+ {
+ CRYPTOPP_ASSERT(0);
return false;
+ }
const Integer& q = params.GetSubgroupOrder();
const unsigned int len /*bytes*/ = (((q.BitCount()+1)/2 +7)/8);
@@ -233,6 +330,7 @@ public:
}
catch (DL_BadElement &)
{
+ CRYPTOPP_ASSERT(0);
return false;
}
return true;
@@ -251,6 +349,8 @@ protected:
if(sigma)
{
+ //SecByteBlock sbb(GetAbstractGroupParameters().GetEncodedElementSize(false));
+ //GetAbstractGroupParameters().EncodeElement(false, *sigma, sbb);
Integer x = GetAbstractGroupParameters().ConvertElementToInteger(*sigma);
SecByteBlock sbb(x.MinEncodedSize());
x.Encode(sbb.BytePtr(), sbb.SizeInBytes());
@@ -294,7 +394,7 @@ private:
/// \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.
-/// \sa FHMQV, MQV_Domain, HMQV_Domain, AuthenticatedKeyAgreementDomain
+/// \sa FHMQV, MQV_Domain, FHMQV_Domain, AuthenticatedKeyAgreementDomain
/// \since Crypto++ 5.6.4
typedef FHMQV_Domain FHMQV;
diff --git a/hmqv.h b/hmqv.h
index f3c99731..f678e30f 100644
--- a/hmqv.h
+++ b/hmqv.h
@@ -1,5 +1,5 @@
// 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 Wei Dai's MQV source files
#ifndef CRYPTOPP_HMQV_H
#define CRYPTOPP_HMQV_H
@@ -29,59 +29,144 @@ public:
virtual ~HMQV_Domain() {}
- HMQV_Domain(bool clientRole = true): m_role(clientRole ? RoleClient : RoleServer) {}
+ /// \brief Construct a HMQV domain
+ /// \params clientRole flag indicating initiator or recipient
+ /// \details clientRole = true indicates initiator, and
+ /// clientRole = false indicates recipient or server.
+ HMQV_Domain(bool clientRole = true)
+ : m_role(clientRole ? RoleClient : RoleServer) {}
+ /// \brief Construct a HMQV domain
+ /// \param params group parameters and options
+ /// \details clientRole = true indicates initiator, and
+ /// clientRole = false indicates recipient or server.
HMQV_Domain(const GroupParameters ¶ms, bool clientRole = true)
: m_role(clientRole ? RoleClient : RoleServer), m_groupParameters(params) {}
+ /// \brief Construct a HMQV domain
+ /// \param bt BufferedTransformation with group parameters and options
+ /// \details clientRole = true indicates initiator, and
+ /// clientRole = false indicates recipient or server.
HMQV_Domain(BufferedTransformation &bt, bool clientRole = true)
: m_role(clientRole ? RoleClient : RoleServer)
- {m_groupParameters.BERDecode(bt);}
+ {m_groupParameters.BERDecode(bt);}
+ /// \brief Construct a HMQV 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.
+ /// \details clientRole = true indicates initiator, and
+ /// clientRole = false indicates recipient or server.
template
HMQV_Domain(T1 v1, bool clientRole = true)
: m_role(clientRole ? RoleClient : RoleServer)
- {m_groupParameters.Initialize(v1);}
+ {m_groupParameters.Initialize(v1);}
+ /// \brief Construct a HMQV 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.
+ /// \details clientRole = true indicates initiator, and
+ /// clientRole = false indicates recipient or server.
template
HMQV_Domain(T1 v1, T2 v2, bool clientRole = true)
: m_role(clientRole ? RoleClient : RoleServer)
- {m_groupParameters.Initialize(v1, v2);}
+ {m_groupParameters.Initialize(v1, v2);}
+ /// \brief Construct a HMQV 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.
+ /// \details clientRole = true indicates initiator, and
+ /// clientRole = false indicates recipient or server.
template
HMQV_Domain(T1 v1, T2 v2, T3 v3, bool clientRole = true)
: m_role(clientRole ? RoleClient : RoleServer)
- {m_groupParameters.Initialize(v1, v2, v3);}
+ {m_groupParameters.Initialize(v1, v2, v3);}
+ /// \brief Construct a HMQV 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.
+ /// \details clientRole = true indicates initiator, and
+ /// clientRole = false indicates recipient or server.
template
HMQV_Domain(T1 v1, T2 v2, T3 v3, T4 v4, bool clientRole = true)
: m_role(clientRole ? RoleClient : RoleServer)
- {m_groupParameters.Initialize(v1, v2, v3, v4);}
+ {m_groupParameters.Initialize(v1, v2, v3, v4);}
public:
+ /// \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;}
- GroupParameters & AccessGroupParameters(){return m_groupParameters;}
- CryptoParameters & AccessCryptoParameters(){return AccessAbstractGroupParameters();}
+ /// \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;}
- /// return length of agreed value produced
- unsigned int AgreedValueLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(false);}
- /// return length of static private keys in this domain
- unsigned int StaticPrivateKeyLength() const {return GetAbstractGroupParameters().GetSubgroupOrder().ByteCount();}
- /// return length of static public keys in this domain
- unsigned int StaticPublicKeyLength() const{return GetAbstractGroupParameters().GetEncodedElementSize(true);}
+ /// \brief Retrieves the crypto parameters for this domain
+ /// \return the crypto parameters for this domain as a non-const reference
+ CryptoParameters & AccessCryptoParameters() {return AccessAbstractGroupParameters();}
- /// generate static private key
- /*! \pre size of privateKey == PrivateStaticKeyLength() */
+ /// \brief Provides the size of the agreed value
+ /// \return size of agreed value produced in this domain
+ /// \details The length is calculated using GetEncodedElementSize(false),
+ /// 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 GetEncodedElementSize(true),
+ /// 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
+ /// [1,MaxExponent()].
+ /// \pre COUNTOF(privateKey) == PrivateStaticKeyLength()
void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
{
Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent());
x.Encode(privateKey, StaticPrivateKeyLength());
}
- /// generate static public key
- /*! \pre size of publicKey == PublicStaticKeyLength() */
+ /// \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 COUNTOF(publicKey) == PublicStaticKeyLength()
void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
{
CRYPTOPP_UNUSED(rng);
@@ -111,15 +196,26 @@ public:
memcpy(publicKey, privateKey+StaticPrivateKeyLength(), EphemeralPublicKeyLength());
}
- /// 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.
- If you have previously validated the static public key, use validateStaticOtherPublicKey=false to save time.
- \pre size of agreedValue == AgreedValueLength()
- \pre length of staticPrivateKey == StaticPrivateKeyLength()
- \pre length of ephemeralPrivateKey == EphemeralPrivateKeyLength()
- \pre length of staticOtherPublicKey == StaticPublicKeyLength()
- \pre length of ephemeralOtherPublicKey == EphemeralPublicKeyLength()
- */
+ /// \brief Derive shared secre from your private keys and couterparty's public keys
+ /// \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 your ephemeral public key
+ /// \param validateStaticOtherPublicKey flag indicating validation
+ /// \details Agree() performs the authenticated key agreement. 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.
+ /// validateStaticOtherPublicKey determines how thoroughly other's
+ /// static public key is validated. If you have previously validated the
+ /// couterparty's static public key, then use
+ /// validateStaticOtherPublicKey=false to save time.
+ /// \pre size of agreedValue == AgreedValueLength()
+ /// \pre length of staticPrivateKey == StaticPrivateKeyLength()
+ /// \pre length of ephemeralPrivateKey == EphemeralPrivateKeyLength()
+ /// \pre length of staticOtherPublicKey == StaticPublicKeyLength()
+ /// \pre length of ephemeralOtherPublicKey == EphemeralPublicKeyLength()
bool Agree(byte *agreedValue,
const byte *staticPrivateKey, const byte *ephemeralPrivateKey,
const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey,
@@ -178,15 +274,20 @@ public:
// requested to be validated, we manually call ValidateElement at level 3.
Element VV1 = params.DecodeElement(staticOtherPublicKey, false);
if(!params.ValidateElement(validateStaticOtherPublicKey ? 3 : 1, VV1, NULLPTR))
+ {
+ CRYPTOPP_ASSERT(0);
return false;
+ }
// DecodeElement calls ValidateElement at level 1. Level 1 only calls
// VerifyPoint to ensure the element is in G*. Crank it up.
Element VV2 = params.DecodeElement(ephemeralOtherPublicKey, false);
if(!params.ValidateElement(3, VV2, NULLPTR))
+ {
+ CRYPTOPP_ASSERT(0);
return false;
+ }
- // 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);
@@ -236,6 +337,7 @@ public:
}
catch (DL_BadElement &)
{
+ CRYPTOPP_ASSERT(0);
return false;
}
return true;
@@ -259,6 +361,8 @@ protected:
if (e1len != 0 || s1len != 0) {
CRYPTOPP_ASSERT(0);
}
+ //SecByteBlock sbb(GetAbstractGroupParameters().GetEncodedElementSize(false));
+ //GetAbstractGroupParameters().EncodeElement(false, *sigma, sbb);
Integer x = GetAbstractGroupParameters().ConvertElementToInteger(*sigma);
SecByteBlock sbb(x.MinEncodedSize());
x.Encode(sbb.BytePtr(), sbb.SizeInBytes());
@@ -292,8 +396,10 @@ private:
// The paper uses Initiator and Recipient - make it classical.
enum KeyAgreementRole{ RoleServer = 1, RoleClient };
- DL_GroupParameters & AccessAbstractGroupParameters() {return m_groupParameters;}
- const DL_GroupParameters & GetAbstractGroupParameters() const{return m_groupParameters;}
+ DL_GroupParameters & AccessAbstractGroupParameters()
+ {return m_groupParameters;}
+ const DL_GroupParameters & GetAbstractGroupParameters() const
+ {return m_groupParameters;}
GroupParameters m_groupParameters;
KeyAgreementRole m_role;
@@ -302,7 +408,7 @@ private:
/// \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.
-/// \sa HMQV, MQV_Domain, FHMQV_Domain, AuthenticatedKeyAgreementDomain
+/// \sa HMQV, HMQV_Domain, FHMQV_Domain, AuthenticatedKeyAgreementDomain
/// \since Crypto++ 5.6.4
typedef HMQV_Domain HMQV;
diff --git a/mqv.h b/mqv.h
index 14f4d592..eec96722 100644
--- a/mqv.h
+++ b/mqv.h
@@ -94,10 +94,11 @@ public:
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 GetEncodedElementSize(false), 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.
+ /// \return size of agreed value produced in this domain
+ /// \details The length is calculated using GetEncodedElementSize(false),
+ /// 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
@@ -107,15 +108,17 @@ public:
/// \brief Provides the size of the static public key
/// \return size of static public keys in this domain
- /// \details The length is calculated using GetEncodedElementSize(true), 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.
+ /// \details The length is calculated using GetEncodedElementSize(true),
+ /// 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 [1,MaxExponent()].
+ /// \details The private key is a random scalar used as an exponent in the range
+ /// [1,MaxExponent()].
/// \pre COUNTOF(privateKey) == PrivateStaticKeyLength()
void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
{
@@ -127,8 +130,9 @@ public:
/// \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.
+ /// \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 COUNTOF(publicKey) == PublicStaticKeyLength()
void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
{
@@ -157,6 +161,26 @@ public:
memcpy(publicKey, privateKey+StaticPrivateKeyLength(), EphemeralPublicKeyLength());
}
+ /// \brief Derive shared secre from your private keys and couterparty's public keys
+ /// \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 your ephemeral public key
+ /// \param validateStaticOtherPublicKey flag indicating validation
+ /// \details Agree() performs the authenticated key agreement. 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.
+ /// validateStaticOtherPublicKey determines how thoroughly other's
+ /// static public key is validated. If you have previously validated the
+ /// couterparty's static public key, then use
+ /// validateStaticOtherPublicKey=false to save time.
+ /// \pre size of agreedValue == AgreedValueLength()
+ /// \pre length of staticPrivateKey == StaticPrivateKeyLength()
+ /// \pre length of ephemeralPrivateKey == EphemeralPrivateKeyLength()
+ /// \pre length of staticOtherPublicKey == StaticPublicKeyLength()
+ /// \pre length of ephemeralOtherPublicKey == EphemeralPublicKeyLength()
bool Agree(byte *agreedValue,
const byte *staticPrivateKey, const byte *ephemeralPrivateKey,
const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey,