You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
141 lines
5.0 KiB
141 lines
5.0 KiB
#ifndef CRYPTOPP_MQV_H |
|
#define CRYPTOPP_MQV_H |
|
|
|
/** \file |
|
*/ |
|
|
|
#include "gfpcrypt.h" |
|
|
|
NAMESPACE_BEGIN(CryptoPP) |
|
|
|
//! _ |
|
template <class GROUP_PARAMETERS, class COFACTOR_OPTION = CPP_TYPENAME GROUP_PARAMETERS::DefaultCofactorOption> |
|
class MQV_Domain : public AuthenticatedKeyAgreementDomain |
|
{ |
|
public: |
|
typedef GROUP_PARAMETERS GroupParameters; |
|
typedef typename GroupParameters::Element Element; |
|
typedef MQV_Domain<GROUP_PARAMETERS, COFACTOR_OPTION> Domain; |
|
|
|
MQV_Domain() {} |
|
|
|
MQV_Domain(const GroupParameters ¶ms) |
|
: m_groupParameters(params) {} |
|
|
|
MQV_Domain(BufferedTransformation &bt) |
|
{m_groupParameters.BERDecode(bt);} |
|
|
|
template <class T1, class T2> |
|
MQV_Domain(T1 v1, T2 v2) |
|
{m_groupParameters.Initialize(v1, v2);} |
|
|
|
template <class T1, class T2, class T3> |
|
MQV_Domain(T1 v1, T2 v2, T3 v3) |
|
{m_groupParameters.Initialize(v1, v2, v3);} |
|
|
|
template <class T1, class T2, class T3, class T4> |
|
MQV_Domain(T1 v1, T2 v2, T3 v3, T4 v4) |
|
{m_groupParameters.Initialize(v1, v2, v3, v4);} |
|
|
|
const GroupParameters & GetGroupParameters() const {return m_groupParameters;} |
|
GroupParameters & AccessGroupParameters() {return m_groupParameters;} |
|
|
|
CryptoParameters & AccessCryptoParameters() {return AccessAbstractGroupParameters();} |
|
|
|
unsigned int AgreedValueLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(false);} |
|
unsigned int StaticPrivateKeyLength() const {return GetAbstractGroupParameters().GetSubgroupOrder().ByteCount();} |
|
unsigned int StaticPublicKeyLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(true);} |
|
|
|
void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const |
|
{ |
|
Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent()); |
|
x.Encode(privateKey, StaticPrivateKeyLength()); |
|
} |
|
|
|
void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const |
|
{ |
|
const DL_GroupParameters<Element> ¶ms = GetAbstractGroupParameters(); |
|
Integer x(privateKey, StaticPrivateKeyLength()); |
|
Element y = params.ExponentiateBase(x); |
|
params.EncodeElement(true, y, publicKey); |
|
} |
|
|
|
unsigned int EphemeralPrivateKeyLength() const {return StaticPrivateKeyLength() + StaticPublicKeyLength();} |
|
unsigned int EphemeralPublicKeyLength() const {return StaticPublicKeyLength();} |
|
|
|
void GenerateEphemeralPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const |
|
{ |
|
const DL_GroupParameters<Element> ¶ms = GetAbstractGroupParameters(); |
|
Integer x(rng, Integer::One(), params.GetMaxExponent()); |
|
x.Encode(privateKey, StaticPrivateKeyLength()); |
|
Element y = params.ExponentiateBase(x); |
|
params.EncodeElement(true, y, privateKey+StaticPrivateKeyLength()); |
|
} |
|
|
|
void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const |
|
{ |
|
memcpy(publicKey, privateKey+StaticPrivateKeyLength(), EphemeralPublicKeyLength()); |
|
} |
|
|
|
bool Agree(byte *agreedValue, |
|
const byte *staticPrivateKey, const byte *ephemeralPrivateKey, |
|
const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey, |
|
bool validateStaticOtherPublicKey=true) const |
|
{ |
|
try |
|
{ |
|
const DL_GroupParameters<Element> ¶ms = GetAbstractGroupParameters(); |
|
Element WW = params.DecodeElement(staticOtherPublicKey, validateStaticOtherPublicKey); |
|
Element VV = params.DecodeElement(ephemeralOtherPublicKey, true); |
|
|
|
Integer s(staticPrivateKey, StaticPrivateKeyLength()); |
|
Integer u(ephemeralPrivateKey, StaticPrivateKeyLength()); |
|
Element V = params.DecodeElement(ephemeralPrivateKey+StaticPrivateKeyLength(), false); |
|
|
|
const Integer &r = params.GetSubgroupOrder(); |
|
Integer h2 = Integer::Power2((r.BitCount()+1)/2); |
|
Integer e = ((h2+params.ConvertElementToInteger(V)%h2)*s+u) % r; |
|
Integer tt = h2 + params.ConvertElementToInteger(VV) % h2; |
|
|
|
if (COFACTOR_OPTION::ToEnum() == NO_COFACTOR_MULTIPLICTION) |
|
{ |
|
Element P = params.ExponentiateElement(WW, tt); |
|
P = m_groupParameters.MultiplyElements(P, VV); |
|
Element R[2]; |
|
const Integer e2[2] = {r, e}; |
|
params.SimultaneousExponentiate(R, P, e2, 2); |
|
if (!params.IsIdentity(R[0]) || params.IsIdentity(R[1])) |
|
return false; |
|
params.EncodeElement(false, R[1], agreedValue); |
|
} |
|
else |
|
{ |
|
const Integer &k = params.GetCofactor(); |
|
if (COFACTOR_OPTION::ToEnum() == COMPATIBLE_COFACTOR_MULTIPLICTION) |
|
e = ModularArithmetic(r).Divide(e, k); |
|
Element P = m_groupParameters.CascadeExponentiate(VV, k*e, WW, k*(e*tt%r)); |
|
if (params.IsIdentity(P)) |
|
return false; |
|
params.EncodeElement(false, P, agreedValue); |
|
} |
|
} |
|
catch (DL_BadElement &) |
|
{ |
|
return false; |
|
} |
|
return true; |
|
} |
|
|
|
private: |
|
DL_GroupParameters<Element> & AccessAbstractGroupParameters() {return m_groupParameters;} |
|
const DL_GroupParameters<Element> & GetAbstractGroupParameters() const {return m_groupParameters;} |
|
|
|
GroupParameters m_groupParameters; |
|
}; |
|
|
|
//! Menezes-Qu-Vanstone in GF(p) with key validation, AKA <a href="http://www.weidai.com/scan-mirror/ka.html#MQV">MQV</a> |
|
typedef MQV_Domain<DL_GroupParameters_GFP_DefaultSafePrime> MQV; |
|
|
|
NAMESPACE_END |
|
|
|
#endif
|
|
|