Fabcoin Core  0.16.2
P2P Digital Currency
hmqv.h
Go to the documentation of this file.
1 // hmqv.h - written and placed in the public domain by Uri Blumenthal
2 // Shamelessly based upon Jeffrey Walton's FHMQV and Wei Dai's MQV source files
3 
4 #ifndef CRYPTOPP_HMQV_H
5 #define CRYPTOPP_HMQV_H
6 
10 
11 #include "gfpcrypt.h"
12 #include "algebra.h"
13 #include "sha.h"
14 
16 
17 template <class GROUP_PARAMETERS, class COFACTOR_OPTION = typename GROUP_PARAMETERS::DefaultCofactorOption, class HASH = SHA512>
24 {
25 public:
26  typedef GROUP_PARAMETERS GroupParameters;
27  typedef typename GroupParameters::Element Element;
29 
30  virtual ~HMQV_Domain() {}
31 
32  HMQV_Domain(bool clientRole = true): m_role(clientRole ? RoleClient : RoleServer) {}
33 
34  HMQV_Domain(const GroupParameters &params, bool clientRole = true)
35  : m_role(clientRole ? RoleClient : RoleServer), m_groupParameters(params) {}
36 
37  HMQV_Domain(BufferedTransformation &bt, bool clientRole = true)
38  : m_role(clientRole ? RoleClient : RoleServer)
39  {m_groupParameters.BERDecode(bt);}
40 
41  template <class T1>
42  HMQV_Domain(T1 v1, bool clientRole = true)
43  : m_role(clientRole ? RoleClient : RoleServer)
44  {m_groupParameters.Initialize(v1);}
45 
46  template <class T1, class T2>
47  HMQV_Domain(T1 v1, T2 v2, bool clientRole = true)
48  : m_role(clientRole ? RoleClient : RoleServer)
49  {m_groupParameters.Initialize(v1, v2);}
50 
51  template <class T1, class T2, class T3>
52  HMQV_Domain(T1 v1, T2 v2, T3 v3, bool clientRole = true)
53  : m_role(clientRole ? RoleClient : RoleServer)
54  {m_groupParameters.Initialize(v1, v2, v3);}
55 
56  template <class T1, class T2, class T3, class T4>
57  HMQV_Domain(T1 v1, T2 v2, T3 v3, T4 v4, bool clientRole = true)
58  : m_role(clientRole ? RoleClient : RoleServer)
59  {m_groupParameters.Initialize(v1, v2, v3, v4);}
60 
61 public:
62 
63  const GroupParameters & GetGroupParameters() const {return m_groupParameters;}
64  GroupParameters & AccessGroupParameters(){return m_groupParameters;}
65 
66  CryptoParameters & AccessCryptoParameters(){return AccessAbstractGroupParameters();}
67 
69  unsigned int AgreedValueLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(false);}
71  unsigned int StaticPrivateKeyLength() const {return GetAbstractGroupParameters().GetSubgroupOrder().ByteCount();}
73  unsigned int StaticPublicKeyLength() const{return GetAbstractGroupParameters().GetEncodedElementSize(true);}
74 
76 
77  void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
78  {
79  Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent());
80  x.Encode(privateKey, StaticPrivateKeyLength());
81  }
82 
84 
85  void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
86  {
87  CRYPTOPP_UNUSED(rng);
88  const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
89  Integer x(privateKey, StaticPrivateKeyLength());
90  Element y = params.ExponentiateBase(x);
91  params.EncodeElement(true, y, publicKey);
92  }
93 
94  unsigned int EphemeralPrivateKeyLength() const {return StaticPrivateKeyLength() + StaticPublicKeyLength();}
95  unsigned int EphemeralPublicKeyLength() const{return StaticPublicKeyLength();}
96 
99  {
100  const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
101  Integer x(rng, Integer::One(), params.GetMaxExponent());
102  x.Encode(privateKey, StaticPrivateKeyLength());
103  Element y = params.ExponentiateBase(x);
104  params.EncodeElement(true, y, privateKey+StaticPrivateKeyLength());
105  }
106 
108  void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
109  {
110  CRYPTOPP_UNUSED(rng);
111  memcpy(publicKey, privateKey+StaticPrivateKeyLength(), EphemeralPublicKeyLength());
112  }
113 
115 
123  bool Agree(byte *agreedValue,
124  const byte *staticPrivateKey, const byte *ephemeralPrivateKey,
125  const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey,
126  bool validateStaticOtherPublicKey=true) const
127  {
128  byte *XX = NULL, *YY = NULL, *AA = NULL, *BB = NULL;
129  size_t xxs = 0, yys = 0, aas = 0, bbs = 0;
130 
131  // Depending on the role, this will hold either A's or B's static
132  // (long term) public key. AA or BB will then point into tt.
133  SecByteBlock tt(StaticPublicKeyLength());
134 
135  try
136  {
137  const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
138 
139  if(m_role == RoleServer)
140  {
141  Integer b(staticPrivateKey, StaticPrivateKeyLength());
142  Element B = params.ExponentiateBase(b);
143  params.EncodeElement(true, B, tt);
144 
145  XX = const_cast<byte*>(ephemeralOtherPublicKey);
146  xxs = EphemeralPublicKeyLength();
147  YY = const_cast<byte*>(ephemeralPrivateKey) + StaticPrivateKeyLength();
148  yys = EphemeralPublicKeyLength();
149  AA = const_cast<byte*>(staticOtherPublicKey);
150  aas = StaticPublicKeyLength();
151  BB = tt.BytePtr();
152  bbs = tt.SizeInBytes();
153  }
154  else if(m_role == RoleClient)
155  {
156  Integer a(staticPrivateKey, StaticPrivateKeyLength());
157  Element A = params.ExponentiateBase(a);
158  params.EncodeElement(true, A, tt);
159 
160  XX = const_cast<byte*>(ephemeralPrivateKey) + StaticPrivateKeyLength();
161  xxs = EphemeralPublicKeyLength();
162  YY = const_cast<byte*>(ephemeralOtherPublicKey);
163  yys = EphemeralPublicKeyLength();
164  AA = tt.BytePtr();
165  aas = tt.SizeInBytes();
166  BB = const_cast<byte*>(staticOtherPublicKey);
167  bbs = StaticPublicKeyLength();
168  }
169  else
170  {
171  CRYPTOPP_ASSERT(0);
172  return false;
173  }
174 
175  // DecodeElement calls ValidateElement at level 1. Level 1 only calls
176  // VerifyPoint to ensure the element is in G*. If the other's PublicKey is
177  // requested to be validated, we manually call ValidateElement at level 3.
178  Element VV1 = params.DecodeElement(staticOtherPublicKey, false);
179  if(!params.ValidateElement(validateStaticOtherPublicKey ? 3 : 1, VV1, NULL))
180  return false;
181 
182  // DecodeElement calls ValidateElement at level 1. Level 1 only calls
183  // VerifyPoint to ensure the element is in G*. Crank it up.
184  Element VV2 = params.DecodeElement(ephemeralOtherPublicKey, false);
185  if(!params.ValidateElement(3, VV2, NULL))
186  return false;
187 
188  // const Integer& p = params.GetGroupOrder(); // not used, remove later
189  const Integer& q = params.GetSubgroupOrder();
190  const unsigned int len /*bytes*/ = (((q.BitCount()+1)/2 +7)/8);
191 
192  Integer d, e;
193  SecByteBlock dd(len), ee(len);
194 
195  // Compute $d = \hat{H}(X, \hat{B})$
196  Hash(NULL, XX, xxs, BB, bbs, dd.BytePtr(), dd.SizeInBytes());
197  d.Decode(dd.BytePtr(), dd.SizeInBytes());
198 
199  // Compute $e = \hat{H}(Y, \hat{A})$
200  Hash(NULL, YY, yys, AA, aas, ee.BytePtr(), ee.SizeInBytes());
201  e.Decode(ee.BytePtr(), ee.SizeInBytes());
202 
203  Element sigma;
204  if(m_role == RoleServer)
205  {
206  Integer y(ephemeralPrivateKey, StaticPrivateKeyLength());
207  Integer b(staticPrivateKey, StaticPrivateKeyLength());
208  Integer s_B = (y + e * b) % q;
209 
210  Element A = params.DecodeElement(AA, false);
211  Element X = params.DecodeElement(XX, false);
212 
213  Element t1 = params.ExponentiateElement(A, d);
214  Element t2 = m_groupParameters.MultiplyElements(X, t1);
215 
216  // $\sigma_B}=(X \cdot A^{d})^{s_B}
217  sigma = params.ExponentiateElement(t2, s_B);
218  }
219  else
220  {
221  Integer x(ephemeralPrivateKey, StaticPrivateKeyLength());
222  Integer a(staticPrivateKey, StaticPrivateKeyLength());
223  Integer s_A = (x + d * a) % q;
224 
225  Element B = params.DecodeElement(BB, false);
226  Element Y = params.DecodeElement(YY, false);
227 
228  Element t1 = params.ExponentiateElement(B, e);
229  Element t2 = m_groupParameters.MultiplyElements(Y, t1);
230 
231  // $\sigma_A}=(Y \cdot B^{e})^{s_A}
232  sigma = params.ExponentiateElement(t2, s_A);
233  }
234  Hash(&sigma, NULL, 0, NULL, 0, agreedValue, AgreedValueLength());
235  }
236  catch (DL_BadElement &)
237  {
238  return false;
239  }
240  return true;
241  }
242 
243 protected:
244  // Hash invocation by client and server differ only in what keys
245  // each provides.
246 
247  inline void Hash(const Element* sigma,
248  const byte* e1, size_t e1len, // Ephemeral key and key length
249  const byte* s1, size_t s1len, // Static key and key length
250  byte* digest, size_t dlen) const
251  {
252  HASH hash;
253  size_t idx = 0, req = dlen;
254  size_t blk = STDMIN(dlen, (size_t)HASH::DIGESTSIZE);
255 
256  if(sigma)
257  {
258  if (e1len != 0 || s1len != 0) {
259  CRYPTOPP_ASSERT(0);
260  }
261  Integer x = GetAbstractGroupParameters().ConvertElementToInteger(*sigma);
262  SecByteBlock sbb(x.MinEncodedSize());
263  x.Encode(sbb.BytePtr(), sbb.SizeInBytes());
264  hash.Update(sbb.BytePtr(), sbb.SizeInBytes());
265  } else {
266  if (e1len == 0 || s1len == 0) {
267  CRYPTOPP_ASSERT(0);
268  }
269  hash.Update(e1, e1len);
270  hash.Update(s1, s1len);
271  }
272 
273  hash.TruncatedFinal(digest, blk);
274  req -= blk;
275 
276  // All this to catch tail bytes for large curves and small hashes
277  while(req != 0)
278  {
279  hash.Update(&digest[idx], (size_t)HASH::DIGESTSIZE);
280 
281  idx += (size_t)HASH::DIGESTSIZE;
282  blk = STDMIN(req, (size_t)HASH::DIGESTSIZE);
283  hash.TruncatedFinal(&digest[idx], blk);
284 
285  req -= blk;
286  }
287  }
288 
289 private:
290 
291  // The paper uses Initiator and Recipient - make it classical.
292  enum KeyAgreementRole{ RoleServer = 1, RoleClient };
293 
295  const DL_GroupParameters<Element> & GetAbstractGroupParameters() const{return m_groupParameters;}
296 
297  GroupParameters m_groupParameters;
299 };
300 
307 
309 
310 #endif
#define T1
Definition: integer.cpp:2170
void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
return length of ephemeral public keys in this domain
Definition: hmqv.h:108
bool Agree(byte *agreedValue, const byte *staticPrivateKey, const byte *ephemeralPrivateKey, const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey, bool validateStaticOtherPublicKey=true) const
derive agreed value from your private keys and couterparty&#39;s public keys, return false in case of fai...
Definition: hmqv.h:123
void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
generate static public key
Definition: hmqv.h:85
uint8_t byte
Definition: Common.h:57
virtual ~HMQV_Domain()
Definition: hmqv.h:30
#define T2
Definition: integer.cpp:2171
HMQV_Domain< GROUP_PARAMETERS, COFACTOR_OPTION, HASH > Domain
Definition: hmqv.h:28
void Encode(byte *output, size_t outputLen, Signedness sign=UNSIGNED) const
Encode in big-endian format.
Definition: integer.cpp:3369
GroupParameters::Element Element
Definition: hmqv.h:27
#define NAMESPACE_BEGIN(x)
Definition: config.h:200
Interface for Discrete Log (DL) group parameters.
Definition: pubkey.h:736
unsigned int StaticPrivateKeyLength() const
return length of static private keys in this domain
Definition: hmqv.h:71
HMQV_Domain(T1 v1, T2 v2, T3 v3, bool clientRole=true)
Definition: hmqv.h:52
Hashed Menezes-Qu-Vanstone in GF(p)
Definition: hmqv.h:23
Interface for random number generators.
Definition: cryptlib.h:1188
size_t MinEncodedSize(Signedness sign=UNSIGNED) const
Minimum number of bytes to encode this integer.
Definition: integer.cpp:3354
Classes for performing mathematics over different fields.
Interface for buffered transformations.
Definition: cryptlib.h:1352
GroupParameters & AccessGroupParameters()
Definition: hmqv.h:64
HMQV_Domain(BufferedTransformation &bt, bool clientRole=true)
Definition: hmqv.h:37
static const Integer &CRYPTOPP_API One()
Integer representing 1.
Definition: integer.cpp:3035
DL_GroupParameters< Element > & AccessAbstractGroupParameters()
Definition: hmqv.h:294
void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
generate static private key
Definition: hmqv.h:77
unsigned int BitCount() const
Determines the number of bits required to represent the Integer.
Definition: integer.cpp:3305
#define a(i)
#define x(i)
HMQV_Domain(T1 v1, T2 v2, T3 v3, T4 v4, bool clientRole=true)
Definition: hmqv.h:57
GROUP_PARAMETERS GroupParameters
Definition: hmqv.h:26
const DL_GroupParameters< Element > & GetAbstractGroupParameters() const
Definition: hmqv.h:295
CryptoParameters & AccessCryptoParameters()
Retrieves a reference to Crypto Parameters.
Definition: hmqv.h:66
HMQV_Domain(T1 v1, T2 v2, bool clientRole=true)
Definition: hmqv.h:47
HMQV_Domain(T1 v1, bool clientRole=true)
Definition: hmqv.h:42
unsigned int AgreedValueLength() const
return length of agreed value produced
Definition: hmqv.h:69
SHA-512 message digest.
Definition: sha.h:69
KeyAgreementRole m_role
Definition: hmqv.h:298
HMQV_Domain< DL_GroupParameters_GFP_DefaultSafePrime > HMQV
Hashed Menezes-Qu-Vanstone in GF(p)
Definition: hmqv.h:306
Multiple precision integer with arithmetic operations.
Definition: integer.h:43
const GroupParameters & GetGroupParameters() const
Definition: hmqv.h:63
#define t1
uint256 Hash(const T1 pbegin, const T1 pend)
Compute the 256-bit hash of an object.
Definition: hash.h:70
Classes and functions for schemes based on Discrete Logs (DL) over GF(p)
unsigned int EphemeralPrivateKeyLength() const
Provides the size of ephemeral private key.
Definition: hmqv.h:94
virtual Element DecodeElement(const byte *encoded, bool checkForGroupMembership) const =0
Decodes the element.
unsigned int EphemeralPublicKeyLength() const
Provides the size of ephemeral public key.
Definition: hmqv.h:95
Exception thrown when an invalid group element is encountered.
Definition: pubkey.h:726
#define b(i, j)
const T & STDMIN(const T &a, const T &b)
Replacement function for std::min.
Definition: misc.h:477
#define CRYPTOPP_ASSERT(exp)
Definition: trap.h:92
HMQV_Domain(bool clientRole=true)
Definition: hmqv.h:32
virtual bool ValidateElement(unsigned int level, const Element &element, const DL_FixedBasePrecomputation< Element > *precomp) const =0
Check the element for errors.
#define t2
Classes for SHA-1 and SHA-2 family of message digests.
#define X(name)
Definition: net.cpp:642
KeyAgreementRole
Definition: hmqv.h:292
void * memcpy(void *a, const void *b, size_t c)
#define CRYPTOPP_UNUSED(x)
Definition: config.h:741
virtual void EncodeElement(bool reversible, const Element &element, byte *encoded) const =0
Encodes the element.
void Decode(const byte *input, size_t inputLen, Signedness sign=UNSIGNED)
Decode from big-endian byte array.
Definition: integer.cpp:3314
GroupParameters m_groupParameters
Definition: hmqv.h:297
#define NAMESPACE_END
Definition: config.h:201
Interface for crypto prameters.
Definition: cryptlib.h:2191
virtual Integer GetMaxExponent() const =0
Retrieves the maximum exponent for the group.
#define e(i)
Definition: sha.cpp:733
#define d(i)
Definition: sha.cpp:732
Interface for domains of authenticated key agreement protocols.
Definition: cryptlib.h:2727
void GenerateEphemeralPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
return length of ephemeral private keys in this domain
Definition: hmqv.h:98
size_type SizeInBytes() const
Provides the number of bytes in the SecBlock.
Definition: secblock.h:538
#define s1(x)
Definition: sha256.c:70
#define T3
Definition: integer.cpp:2172
virtual Element ExponentiateBase(const Integer &exponent) const
Retrieves the subgroup generator.
Definition: pubkey.h:803
HMQV_Domain(const GroupParameters &params, bool clientRole=true)
Definition: hmqv.h:34
virtual Element ExponentiateElement(const Element &base, const Integer &exponent) const
Exponentiates an element.
Definition: pubkey.h:813
void Hash(const Element *sigma, const byte *e1, size_t e1len, const byte *s1, size_t s1len, byte *digest, size_t dlen) const
Definition: hmqv.h:247
unsigned int StaticPublicKeyLength() const
return length of static public keys in this domain
Definition: hmqv.h:73
byte * BytePtr()
Provides a byte pointer to the first element in the memory block.
Definition: secblock.h:531
virtual const Integer & GetSubgroupOrder() const =0
Retrieves the subgroup order.