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