1#ifndef CRYPTOPP_MQV_H 2#define CRYPTOPP_MQV_H 3 4/** \file 5*/ 6 7#include "gfpcrypt.h" 8 9NAMESPACE_BEGIN(CryptoPP) 10 11//! _ 12template <class GROUP_PARAMETERS, class COFACTOR_OPTION = CPP_TYPENAME GROUP_PARAMETERS::DefaultCofactorOption> 13class MQV_Domain : public AuthenticatedKeyAgreementDomain 14{ 15public: 16 typedef GROUP_PARAMETERS GroupParameters; 17 typedef typename GroupParameters::Element Element; 18 typedef MQV_Domain<GROUP_PARAMETERS, COFACTOR_OPTION> Domain; 19 20 MQV_Domain() {} 21 22 MQV_Domain(const GroupParameters ¶ms) 23 : m_groupParameters(params) {} 24 25 MQV_Domain(BufferedTransformation &bt) 26 {m_groupParameters.BERDecode(bt);} 27 28 template <class T1, class T2> 29 MQV_Domain(T1 v1, T2 v2) 30 {m_groupParameters.Initialize(v1, v2);} 31 32 template <class T1, class T2, class T3> 33 MQV_Domain(T1 v1, T2 v2, T3 v3) 34 {m_groupParameters.Initialize(v1, v2, v3);} 35 36 template <class T1, class T2, class T3, class T4> 37 MQV_Domain(T1 v1, T2 v2, T3 v3, T4 v4) 38 {m_groupParameters.Initialize(v1, v2, v3, v4);} 39 40 const GroupParameters & GetGroupParameters() const {return m_groupParameters;} 41 GroupParameters & AccessGroupParameters() {return m_groupParameters;} 42 43 CryptoParameters & AccessCryptoParameters() {return AccessAbstractGroupParameters();} 44 45 unsigned int AgreedValueLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(false);} 46 unsigned int StaticPrivateKeyLength() const {return GetAbstractGroupParameters().GetSubgroupOrder().ByteCount();} 47 unsigned int StaticPublicKeyLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(true);} 48 49 void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const 50 { 51 Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent()); 52 x.Encode(privateKey, StaticPrivateKeyLength()); 53 } 54 55 void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const 56 { 57 const DL_GroupParameters<Element> ¶ms = GetAbstractGroupParameters(); 58 Integer x(privateKey, StaticPrivateKeyLength()); 59 Element y = params.ExponentiateBase(x); 60 params.EncodeElement(true, y, publicKey); 61 } 62 63 unsigned int EphemeralPrivateKeyLength() const {return StaticPrivateKeyLength() + StaticPublicKeyLength();} 64 unsigned int EphemeralPublicKeyLength() const {return StaticPublicKeyLength();} 65 66 void GenerateEphemeralPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const 67 { 68 const DL_GroupParameters<Element> ¶ms = GetAbstractGroupParameters(); 69 Integer x(rng, Integer::One(), params.GetMaxExponent()); 70 x.Encode(privateKey, StaticPrivateKeyLength()); 71 Element y = params.ExponentiateBase(x); 72 params.EncodeElement(true, y, privateKey+StaticPrivateKeyLength()); 73 } 74 75 void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const 76 { 77 memcpy(publicKey, privateKey+StaticPrivateKeyLength(), EphemeralPublicKeyLength()); 78 } 79 80 bool Agree(byte *agreedValue, 81 const byte *staticPrivateKey, const byte *ephemeralPrivateKey, 82 const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey, 83 bool validateStaticOtherPublicKey=true) const 84 { 85 try 86 { 87 const DL_GroupParameters<Element> ¶ms = GetAbstractGroupParameters(); 88 Element WW = params.DecodeElement(staticOtherPublicKey, validateStaticOtherPublicKey); 89 Element VV = params.DecodeElement(ephemeralOtherPublicKey, true); 90 91 Integer s(staticPrivateKey, StaticPrivateKeyLength()); 92 Integer u(ephemeralPrivateKey, StaticPrivateKeyLength()); 93 Element V = params.DecodeElement(ephemeralPrivateKey+StaticPrivateKeyLength(), false); 94 95 const Integer &r = params.GetSubgroupOrder(); 96 Integer h2 = Integer::Power2((r.BitCount()+1)/2); 97 Integer e = ((h2+params.ConvertElementToInteger(V)%h2)*s+u) % r; 98 Integer tt = h2 + params.ConvertElementToInteger(VV) % h2; 99 100 if (COFACTOR_OPTION::ToEnum() == NO_COFACTOR_MULTIPLICTION) 101 { 102 Element P = params.ExponentiateElement(WW, tt); 103 P = m_groupParameters.MultiplyElements(P, VV); 104 Element R[2]; 105 const Integer e2[2] = {r, e}; 106 params.SimultaneousExponentiate(R, P, e2, 2); 107 if (!params.IsIdentity(R[0]) || params.IsIdentity(R[1])) 108 return false; 109 params.EncodeElement(false, R[1], agreedValue); 110 } 111 else 112 { 113 const Integer &k = params.GetCofactor(); 114 if (COFACTOR_OPTION::ToEnum() == COMPATIBLE_COFACTOR_MULTIPLICTION) 115 e = ModularArithmetic(r).Divide(e, k); 116 Element P = m_groupParameters.CascadeExponentiate(VV, k*e, WW, k*(e*tt%r)); 117 if (params.IsIdentity(P)) 118 return false; 119 params.EncodeElement(false, P, agreedValue); 120 } 121 } 122 catch (DL_BadElement &) 123 { 124 return false; 125 } 126 return true; 127 } 128 129private: 130 DL_GroupParameters<Element> & AccessAbstractGroupParameters() {return m_groupParameters;} 131 const DL_GroupParameters<Element> & GetAbstractGroupParameters() const {return m_groupParameters;} 132 133 GroupParameters m_groupParameters; 134}; 135 136//! Menezes-Qu-Vanstone in GF(p) with key validation, AKA <a href="http://www.weidai.com/scan-mirror/ka.html#MQV">MQV</a> 137typedef MQV_Domain<DL_GroupParameters_GFP_DefaultSafePrime> MQV; 138 139NAMESPACE_END 140 141#endif 142