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