Update documentation
parent
2e6ccd7fb1
commit
47a58050c6
154
fhmqv.h
154
fhmqv.h
|
|
@ -30,30 +30,81 @@ public:
|
||||||
|
|
||||||
virtual ~FHMQV_Domain() {}
|
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 <tt>clientRole = true</tt> indicates initiator, and
|
||||||
|
/// <tt>clientRole = false</tt> 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 <tt>clientRole = true</tt> indicates initiator, and
|
||||||
|
/// <tt>clientRole = false</tt> indicates recipient or server.
|
||||||
FHMQV_Domain(const GroupParameters ¶ms, bool clientRole = true)
|
FHMQV_Domain(const GroupParameters ¶ms, bool clientRole = true)
|
||||||
: m_role(clientRole ? RoleClient : RoleServer), m_groupParameters(params) {}
|
: m_role(clientRole ? RoleClient : RoleServer), m_groupParameters(params) {}
|
||||||
|
|
||||||
|
/// \brief Construct a FHMQV domain
|
||||||
|
/// \param bt BufferedTransformation with group parameters and options
|
||||||
|
/// \details <tt>clientRole = true</tt> indicates initiator, and
|
||||||
|
/// <tt>clientRole = false</tt> indicates recipient or server.
|
||||||
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);}
|
||||||
|
|
||||||
|
/// \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 <tt>clientRole = true</tt> indicates initiator, and
|
||||||
|
/// <tt>clientRole = false</tt> indicates recipient or server.
|
||||||
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);}
|
||||||
|
|
||||||
|
/// \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 <tt>clientRole = true</tt> indicates initiator, and
|
||||||
|
/// <tt>clientRole = false</tt> indicates recipient or server.
|
||||||
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);}
|
||||||
|
|
||||||
|
/// \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 <tt>clientRole = true</tt> indicates initiator, and
|
||||||
|
/// <tt>clientRole = false</tt> indicates recipient or server.
|
||||||
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);}
|
||||||
|
|
||||||
|
/// \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 <tt>clientRole = true</tt> indicates initiator, and
|
||||||
|
/// <tt>clientRole = false</tt> indicates recipient or server.
|
||||||
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)
|
||||||
|
|
@ -61,28 +112,62 @@ public:
|
||||||
|
|
||||||
public:
|
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;}
|
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;}
|
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();}
|
CryptoParameters & AccessCryptoParameters() {return AccessAbstractGroupParameters();}
|
||||||
|
|
||||||
/// return length of agreed value produced
|
/// \brief Provides the size of the agreed value
|
||||||
unsigned int AgreedValueLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(false);}
|
/// \return size of agreed value produced in this domain
|
||||||
/// return length of static private keys in this domain
|
/// \details The length is calculated using <tt>GetEncodedElementSize(false)</tt>,
|
||||||
unsigned int StaticPrivateKeyLength() const {return GetAbstractGroupParameters().GetSubgroupOrder().ByteCount();}
|
/// which means the element is encoded in a non-reversible format. A
|
||||||
/// return length of static public keys in this domain
|
/// non-reversible format means its a raw byte array, and it lacks presentation
|
||||||
unsigned int StaticPublicKeyLength() const{return GetAbstractGroupParameters().GetEncodedElementSize(true);}
|
/// format like an ASN.1 BIT_STRING or OCTET_STRING.
|
||||||
|
unsigned int AgreedValueLength() const
|
||||||
|
{return GetAbstractGroupParameters().GetEncodedElementSize(false);}
|
||||||
|
|
||||||
/// generate static private key
|
/// \brief Provides the size of the static private key
|
||||||
/*! \pre size of privateKey == PrivateStaticKeyLength() */
|
/// \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
|
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
|
/// \brief Generate a static public key from a private key in this domain
|
||||||
/*! \pre size of publicKey == PublicStaticKeyLength() */
|
/// \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
|
void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
|
||||||
{
|
{
|
||||||
CRYPTOPP_UNUSED(rng);
|
CRYPTOPP_UNUSED(rng);
|
||||||
|
|
@ -112,15 +197,26 @@ public:
|
||||||
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
|
/// \brief Derive shared secre from your private keys and couterparty's public keys
|
||||||
/*! \note The ephemeral public key will always be validated.
|
/// \param agreedValue the shared secret
|
||||||
If you have previously validated the static public key, use validateStaticOtherPublicKey=false to save time.
|
/// \param staticPrivateKey your long term private key
|
||||||
\pre size of agreedValue == AgreedValueLength()
|
/// \param ephemeralPrivateKey your ephemeral private key
|
||||||
\pre length of staticPrivateKey == StaticPrivateKeyLength()
|
/// \param staticOtherPublicKey couterparty's long term public key
|
||||||
\pre length of ephemeralPrivateKey == EphemeralPrivateKeyLength()
|
/// \param ephemeralOtherPublicKey your ephemeral public key
|
||||||
\pre length of staticOtherPublicKey == StaticPublicKeyLength()
|
/// \param validateStaticOtherPublicKey flag indicating validation
|
||||||
\pre length of ephemeralOtherPublicKey == EphemeralPublicKeyLength()
|
/// \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.
|
||||||
|
/// <tt>validateStaticOtherPublicKey</tt> determines how thoroughly other's
|
||||||
|
/// static public key is validated. If you have previously validated the
|
||||||
|
/// couterparty's static public key, then use
|
||||||
|
/// <tt>validateStaticOtherPublicKey=false</tt> to save time.
|
||||||
|
/// \pre 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,
|
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,
|
||||||
|
|
@ -153,7 +249,7 @@ public:
|
||||||
BB = tt.BytePtr();
|
BB = tt.BytePtr();
|
||||||
bbs = tt.SizeInBytes();
|
bbs = tt.SizeInBytes();
|
||||||
}
|
}
|
||||||
else if(m_role == RoleClient)
|
else
|
||||||
{
|
{
|
||||||
Integer a(staticPrivateKey, StaticPrivateKeyLength());
|
Integer a(staticPrivateKey, StaticPrivateKeyLength());
|
||||||
Element A = params.ExponentiateBase(a);
|
Element A = params.ExponentiateBase(a);
|
||||||
|
|
@ -168,24 +264,25 @@ public:
|
||||||
BB = staticOtherPublicKey;
|
BB = staticOtherPublicKey;
|
||||||
bbs = StaticPublicKeyLength();
|
bbs = StaticPublicKeyLength();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
CRYPTOPP_ASSERT(0);
|
|
||||||
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, NULLPTR))
|
if(!params.ValidateElement(validateStaticOtherPublicKey ? 3 : 1, VV1, NULLPTR))
|
||||||
|
{
|
||||||
|
CRYPTOPP_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*. 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, NULLPTR))
|
if(!params.ValidateElement(3, VV2, NULLPTR))
|
||||||
|
{
|
||||||
|
CRYPTOPP_ASSERT(0);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
|
@ -233,6 +330,7 @@ public:
|
||||||
}
|
}
|
||||||
catch (DL_BadElement &)
|
catch (DL_BadElement &)
|
||||||
{
|
{
|
||||||
|
CRYPTOPP_ASSERT(0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -251,6 +349,8 @@ protected:
|
||||||
|
|
||||||
if(sigma)
|
if(sigma)
|
||||||
{
|
{
|
||||||
|
//SecByteBlock sbb(GetAbstractGroupParameters().GetEncodedElementSize(false));
|
||||||
|
//GetAbstractGroupParameters().EncodeElement(false, *sigma, sbb);
|
||||||
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());
|
||||||
|
|
@ -294,7 +394,7 @@ private:
|
||||||
/// \details This implementation follows Augustin P. Sarr and Philippe Elbaz–Vincent, and Jean–Claude Bajard's
|
/// \details This implementation follows Augustin P. Sarr and Philippe Elbaz–Vincent, and Jean–Claude Bajard's
|
||||||
/// <a href="http://eprint.iacr.org/2009/408">A Secure and Efficient Authenticated Diffie-Hellman Protocol</a>.
|
/// <a href="http://eprint.iacr.org/2009/408">A Secure and Efficient Authenticated Diffie-Hellman 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.
|
||||||
/// \sa FHMQV, MQV_Domain, HMQV_Domain, AuthenticatedKeyAgreementDomain
|
/// \sa FHMQV, MQV_Domain, FHMQV_Domain, AuthenticatedKeyAgreementDomain
|
||||||
/// \since Crypto++ 5.6.4
|
/// \since Crypto++ 5.6.4
|
||||||
typedef FHMQV_Domain<DL_GroupParameters_GFP_DefaultSafePrime> FHMQV;
|
typedef FHMQV_Domain<DL_GroupParameters_GFP_DefaultSafePrime> FHMQV;
|
||||||
|
|
||||||
|
|
|
||||||
156
hmqv.h
156
hmqv.h
|
|
@ -1,5 +1,5 @@
|
||||||
// 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 Wei Dai's MQV source files
|
||||||
|
|
||||||
#ifndef CRYPTOPP_HMQV_H
|
#ifndef CRYPTOPP_HMQV_H
|
||||||
#define CRYPTOPP_HMQV_H
|
#define CRYPTOPP_HMQV_H
|
||||||
|
|
@ -29,30 +29,81 @@ public:
|
||||||
|
|
||||||
virtual ~HMQV_Domain() {}
|
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 <tt>clientRole = true</tt> indicates initiator, and
|
||||||
|
/// <tt>clientRole = false</tt> 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 <tt>clientRole = true</tt> indicates initiator, and
|
||||||
|
/// <tt>clientRole = false</tt> indicates recipient or server.
|
||||||
HMQV_Domain(const GroupParameters ¶ms, bool clientRole = true)
|
HMQV_Domain(const GroupParameters ¶ms, bool clientRole = true)
|
||||||
: m_role(clientRole ? RoleClient : RoleServer), m_groupParameters(params) {}
|
: m_role(clientRole ? RoleClient : RoleServer), m_groupParameters(params) {}
|
||||||
|
|
||||||
|
/// \brief Construct a HMQV domain
|
||||||
|
/// \param bt BufferedTransformation with group parameters and options
|
||||||
|
/// \details <tt>clientRole = true</tt> indicates initiator, and
|
||||||
|
/// <tt>clientRole = false</tt> indicates recipient or server.
|
||||||
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);}
|
||||||
|
|
||||||
|
/// \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 <tt>clientRole = true</tt> indicates initiator, and
|
||||||
|
/// <tt>clientRole = false</tt> indicates recipient or server.
|
||||||
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);}
|
||||||
|
|
||||||
|
/// \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 <tt>clientRole = true</tt> indicates initiator, and
|
||||||
|
/// <tt>clientRole = false</tt> indicates recipient or server.
|
||||||
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);}
|
||||||
|
|
||||||
|
/// \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 <tt>clientRole = true</tt> indicates initiator, and
|
||||||
|
/// <tt>clientRole = false</tt> indicates recipient or server.
|
||||||
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);}
|
||||||
|
|
||||||
|
/// \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 <tt>clientRole = true</tt> indicates initiator, and
|
||||||
|
/// <tt>clientRole = false</tt> indicates recipient or server.
|
||||||
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)
|
||||||
|
|
@ -60,28 +111,62 @@ public:
|
||||||
|
|
||||||
public:
|
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;}
|
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;}
|
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();}
|
CryptoParameters & AccessCryptoParameters() {return AccessAbstractGroupParameters();}
|
||||||
|
|
||||||
/// return length of agreed value produced
|
/// \brief Provides the size of the agreed value
|
||||||
unsigned int AgreedValueLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(false);}
|
/// \return size of agreed value produced in this domain
|
||||||
/// return length of static private keys in this domain
|
/// \details The length is calculated using <tt>GetEncodedElementSize(false)</tt>,
|
||||||
unsigned int StaticPrivateKeyLength() const {return GetAbstractGroupParameters().GetSubgroupOrder().ByteCount();}
|
/// which means the element is encoded in a non-reversible format. A
|
||||||
/// return length of static public keys in this domain
|
/// non-reversible format means its a raw byte array, and it lacks presentation
|
||||||
unsigned int StaticPublicKeyLength() const{return GetAbstractGroupParameters().GetEncodedElementSize(true);}
|
/// format like an ASN.1 BIT_STRING or OCTET_STRING.
|
||||||
|
unsigned int AgreedValueLength() const
|
||||||
|
{return GetAbstractGroupParameters().GetEncodedElementSize(false);}
|
||||||
|
|
||||||
/// generate static private key
|
/// \brief Provides the size of the static private key
|
||||||
/*! \pre size of privateKey == PrivateStaticKeyLength() */
|
/// \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
|
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
|
/// \brief Generate a static public key from a private key in this domain
|
||||||
/*! \pre size of publicKey == PublicStaticKeyLength() */
|
/// \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
|
void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
|
||||||
{
|
{
|
||||||
CRYPTOPP_UNUSED(rng);
|
CRYPTOPP_UNUSED(rng);
|
||||||
|
|
@ -111,15 +196,26 @@ public:
|
||||||
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
|
/// \brief Derive shared secre from your private keys and couterparty's public keys
|
||||||
/*! \note The ephemeral public key will always be validated.
|
/// \param agreedValue the shared secret
|
||||||
If you have previously validated the static public key, use validateStaticOtherPublicKey=false to save time.
|
/// \param staticPrivateKey your long term private key
|
||||||
\pre size of agreedValue == AgreedValueLength()
|
/// \param ephemeralPrivateKey your ephemeral private key
|
||||||
\pre length of staticPrivateKey == StaticPrivateKeyLength()
|
/// \param staticOtherPublicKey couterparty's long term public key
|
||||||
\pre length of ephemeralPrivateKey == EphemeralPrivateKeyLength()
|
/// \param ephemeralOtherPublicKey your ephemeral public key
|
||||||
\pre length of staticOtherPublicKey == StaticPublicKeyLength()
|
/// \param validateStaticOtherPublicKey flag indicating validation
|
||||||
\pre length of ephemeralOtherPublicKey == EphemeralPublicKeyLength()
|
/// \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.
|
||||||
|
/// <tt>validateStaticOtherPublicKey</tt> determines how thoroughly other's
|
||||||
|
/// static public key is validated. If you have previously validated the
|
||||||
|
/// couterparty's static public key, then use
|
||||||
|
/// <tt>validateStaticOtherPublicKey=false</tt> to save time.
|
||||||
|
/// \pre 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,
|
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,
|
||||||
|
|
@ -178,15 +274,20 @@ public:
|
||||||
// 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, NULLPTR))
|
if(!params.ValidateElement(validateStaticOtherPublicKey ? 3 : 1, VV1, NULLPTR))
|
||||||
|
{
|
||||||
|
CRYPTOPP_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*. 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, NULLPTR))
|
if(!params.ValidateElement(3, VV2, NULLPTR))
|
||||||
|
{
|
||||||
|
CRYPTOPP_ASSERT(0);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// 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);
|
||||||
|
|
||||||
|
|
@ -236,6 +337,7 @@ public:
|
||||||
}
|
}
|
||||||
catch (DL_BadElement &)
|
catch (DL_BadElement &)
|
||||||
{
|
{
|
||||||
|
CRYPTOPP_ASSERT(0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -259,6 +361,8 @@ protected:
|
||||||
if (e1len != 0 || s1len != 0) {
|
if (e1len != 0 || s1len != 0) {
|
||||||
CRYPTOPP_ASSERT(0);
|
CRYPTOPP_ASSERT(0);
|
||||||
}
|
}
|
||||||
|
//SecByteBlock sbb(GetAbstractGroupParameters().GetEncodedElementSize(false));
|
||||||
|
//GetAbstractGroupParameters().EncodeElement(false, *sigma, sbb);
|
||||||
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());
|
||||||
|
|
@ -292,8 +396,10 @@ 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()
|
||||||
const DL_GroupParameters<Element> & GetAbstractGroupParameters() const{return m_groupParameters;}
|
{return m_groupParameters;}
|
||||||
|
const DL_GroupParameters<Element> & GetAbstractGroupParameters() const
|
||||||
|
{return m_groupParameters;}
|
||||||
|
|
||||||
GroupParameters m_groupParameters;
|
GroupParameters m_groupParameters;
|
||||||
KeyAgreementRole m_role;
|
KeyAgreementRole m_role;
|
||||||
|
|
@ -302,7 +408,7 @@ private:
|
||||||
/// \brief Hashed Menezes-Qu-Vanstone in GF(p)
|
/// \brief Hashed Menezes-Qu-Vanstone in GF(p)
|
||||||
/// \details This implementation follows Hugo Krawczyk's <a href="http://eprint.iacr.org/2005/176">HMQV: A High-Performance
|
/// \details This implementation follows Hugo Krawczyk's <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 is not provided.
|
/// Secure Diffie-Hellman Protocol</a>. 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
|
/// \since Crypto++ 5.6.4
|
||||||
typedef HMQV_Domain<DL_GroupParameters_GFP_DefaultSafePrime> HMQV;
|
typedef HMQV_Domain<DL_GroupParameters_GFP_DefaultSafePrime> HMQV;
|
||||||
|
|
||||||
|
|
|
||||||
42
mqv.h
42
mqv.h
|
|
@ -95,9 +95,10 @@ public:
|
||||||
|
|
||||||
/// \brief Provides the size of the agreed value
|
/// \brief Provides the size of the agreed value
|
||||||
/// \return size of agreed value produced in this domain
|
/// \return size of agreed value produced in this domain
|
||||||
/// \details The length is calculated using <tt>GetEncodedElementSize(false)</tt>, which means the
|
/// \details The length is calculated using <tt>GetEncodedElementSize(false)</tt>,
|
||||||
/// element is encoded in a non-reversible format. A non-reversible format means its a raw byte array,
|
/// which means the element is encoded in a non-reversible format. A
|
||||||
/// and it lacks presentation format like an ASN.1 BIT_STRING or OCTET_STRING.
|
/// 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);}
|
unsigned int AgreedValueLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(false);}
|
||||||
|
|
||||||
/// \brief Provides the size of the static private key
|
/// \brief Provides the size of the static private key
|
||||||
|
|
@ -107,15 +108,17 @@ public:
|
||||||
|
|
||||||
/// \brief Provides the size of the static public key
|
/// \brief Provides the size of the static public key
|
||||||
/// \return size of static public keys in this domain
|
/// \return size of static public keys in this domain
|
||||||
/// \details The length is calculated using <tt>GetEncodedElementSize(true)</tt>, which means the
|
/// \details The length is calculated using <tt>GetEncodedElementSize(true)</tt>,
|
||||||
/// element is encoded in a reversible format. A reversible format means it has a presentation format,
|
/// which means the element is encoded in a reversible format. A reversible
|
||||||
/// and its an ANS.1 encoded element or point.
|
/// format means it has a presentation format, and its an ANS.1 encoded element
|
||||||
|
/// or point.
|
||||||
unsigned int StaticPublicKeyLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(true);}
|
unsigned int StaticPublicKeyLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(true);}
|
||||||
|
|
||||||
/// \brief Generate static private key in this domain
|
/// \brief Generate static private key in this domain
|
||||||
/// \param rng a RandomNumberGenerator derived class
|
/// \param rng a RandomNumberGenerator derived class
|
||||||
/// \param privateKey a byte buffer for the generated private key in this domain
|
/// \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>.
|
/// \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>
|
/// \pre <tt>COUNTOF(privateKey) == PrivateStaticKeyLength()</tt>
|
||||||
void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
|
void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
|
||||||
{
|
{
|
||||||
|
|
@ -127,8 +130,9 @@ public:
|
||||||
/// \param rng a RandomNumberGenerator derived class
|
/// \param rng a RandomNumberGenerator derived class
|
||||||
/// \param privateKey a byte buffer with the previously generated private key
|
/// \param privateKey a byte buffer with the previously generated private key
|
||||||
/// \param publicKey a byte buffer for the generated public key in this domain
|
/// \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.
|
/// \details The public key is an element or point on the curve, and its stored
|
||||||
/// A reversible format means it has a presentation format, and its an ANS.1 encoded element or point.
|
/// 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>
|
/// \pre <tt>COUNTOF(publicKey) == PublicStaticKeyLength()</tt>
|
||||||
void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
|
void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
|
||||||
{
|
{
|
||||||
|
|
@ -157,6 +161,26 @@ public:
|
||||||
memcpy(publicKey, privateKey+StaticPrivateKeyLength(), EphemeralPublicKeyLength());
|
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.
|
||||||
|
/// <tt>validateStaticOtherPublicKey</tt> determines how thoroughly other's
|
||||||
|
/// static public key is validated. If you have previously validated the
|
||||||
|
/// couterparty's static public key, then use
|
||||||
|
/// <tt>validateStaticOtherPublicKey=false</tt> to save time.
|
||||||
|
/// \pre 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,
|
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,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue