00001 #ifndef CRYPTOPP_MQV_H
00002 #define CRYPTOPP_MQV_H
00003
00004
00005
00006
00007 #include "gfpcrypt.h"
00008
00009 NAMESPACE_BEGIN(CryptoPP)
00010
00011
00012 template <class GROUP_PARAMETERS, class COFACTOR_OPTION = CPP_TYPENAME GROUP_PARAMETERS::DefaultCofactorOption>
00013 class MQV_Domain : public AuthenticatedKeyAgreementDomain
00014 {
00015 public:
00016 typedef GROUP_PARAMETERS GroupParameters;
00017 typedef typename GroupParameters::Element Element;
00018 typedef MQV_Domain<GROUP_PARAMETERS, COFACTOR_OPTION> Domain;
00019
00020 MQV_Domain() {}
00021
00022 MQV_Domain(const GroupParameters ¶ms)
00023 : m_groupParameters(params) {}
00024
00025 MQV_Domain(BufferedTransformation &bt)
00026 {m_groupParameters.BERDecode(bt);}
00027
00028 template <class T1, class T2>
00029 MQV_Domain(T1 v1, T2 v2)
00030 {m_groupParameters.Initialize(v1, v2);}
00031
00032 template <class T1, class T2, class T3>
00033 MQV_Domain(T1 v1, T2 v2, T3 v3)
00034 {m_groupParameters.Initialize(v1, v2, v3);}
00035
00036 template <class T1, class T2, class T3, class T4>
00037 MQV_Domain(T1 v1, T2 v2, T3 v3, T4 v4)
00038 {m_groupParameters.Initialize(v1, v2, v3, v4);}
00039
00040 const GroupParameters & GetGroupParameters() const {return m_groupParameters;}
00041 GroupParameters & AccessGroupParameters() {return m_groupParameters;}
00042
00043 CryptoParameters & AccessCryptoParameters() {return AccessAbstractGroupParameters();}
00044
00045 unsigned int AgreedValueLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(false);}
00046 unsigned int StaticPrivateKeyLength() const {return GetAbstractGroupParameters().GetSubgroupOrder().ByteCount();}
00047 unsigned int StaticPublicKeyLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(true);}
00048
00049 void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
00050 {
00051 Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent());
00052 x.Encode(privateKey, StaticPrivateKeyLength());
00053 }
00054
00055 void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
00056 {
00057 const DL_GroupParameters<Element> ¶ms = GetAbstractGroupParameters();
00058 Integer x(privateKey, StaticPrivateKeyLength());
00059 Element y = params.ExponentiateBase(x);
00060 params.EncodeElement(true, y, publicKey);
00061 }
00062
00063 unsigned int EphemeralPrivateKeyLength() const {return StaticPrivateKeyLength() + StaticPublicKeyLength();}
00064 unsigned int EphemeralPublicKeyLength() const {return StaticPublicKeyLength();}
00065
00066 void GenerateEphemeralPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
00067 {
00068 const DL_GroupParameters<Element> ¶ms = GetAbstractGroupParameters();
00069 Integer x(rng, Integer::One(), params.GetMaxExponent());
00070 x.Encode(privateKey, StaticPrivateKeyLength());
00071 Element y = params.ExponentiateBase(x);
00072 params.EncodeElement(true, y, privateKey+StaticPrivateKeyLength());
00073 }
00074
00075 void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
00076 {
00077 memcpy(publicKey, privateKey+StaticPrivateKeyLength(), EphemeralPublicKeyLength());
00078 }
00079
00080 bool Agree(byte *agreedValue,
00081 const byte *staticPrivateKey, const byte *ephemeralPrivateKey,
00082 const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey,
00083 bool validateStaticOtherPublicKey=true) const
00084 {
00085 try
00086 {
00087 const DL_GroupParameters<Element> ¶ms = GetAbstractGroupParameters();
00088 Element WW = params.DecodeElement(staticOtherPublicKey, validateStaticOtherPublicKey);
00089 Element VV = params.DecodeElement(ephemeralOtherPublicKey, true);
00090
00091 Integer s(staticPrivateKey, StaticPrivateKeyLength());
00092 Integer u(ephemeralPrivateKey, StaticPrivateKeyLength());
00093 Element V = params.DecodeElement(ephemeralPrivateKey+StaticPrivateKeyLength(), false);
00094
00095 const Integer &r = params.GetSubgroupOrder();
00096 Integer h2 = Integer::Power2((r.BitCount()+1)/2);
00097 Integer e = ((h2+params.ConvertElementToInteger(V)%h2)*s+u) % r;
00098 Integer tt = h2 + params.ConvertElementToInteger(VV) % h2;
00099
00100 if (COFACTOR_OPTION::ToEnum() == NO_COFACTOR_MULTIPLICTION)
00101 {
00102 Element P = params.ExponentiateElement(WW, tt);
00103 P = m_groupParameters.MultiplyElements(P, VV);
00104 Element R[2];
00105 const Integer e2[2] = {r, e};
00106 params.SimultaneousExponentiate(R, P, e2, 2);
00107 if (!params.IsIdentity(R[0]) || params.IsIdentity(R[1]))
00108 return false;
00109 params.EncodeElement(false, R[1], agreedValue);
00110 }
00111 else
00112 {
00113 const Integer &k = params.GetCofactor();
00114 if (COFACTOR_OPTION::ToEnum() == COMPATIBLE_COFACTOR_MULTIPLICTION)
00115 e = ModularArithmetic(r).Divide(e, k);
00116 Element P = m_groupParameters.CascadeExponentiate(VV, k*e, WW, k*(e*tt%r));
00117 if (params.IsIdentity(P))
00118 return false;
00119 params.EncodeElement(false, P, agreedValue);
00120 }
00121 }
00122 catch (DL_BadElement &)
00123 {
00124 return false;
00125 }
00126 return true;
00127 }
00128
00129 private:
00130 DL_GroupParameters<Element> & AccessAbstractGroupParameters() {return m_groupParameters;}
00131 const DL_GroupParameters<Element> & GetAbstractGroupParameters() const {return m_groupParameters;}
00132
00133 GroupParameters m_groupParameters;
00134 };
00135
00136
00137 typedef MQV_Domain<DL_GroupParameters_GFP_DefaultSafePrime> MQV;
00138
00139 NAMESPACE_END
00140
00141 #endif