Crypto++  5.6.5
Free C++ class library of cryptographic schemes
gfpcrypt.h
1 // gfpcrypt.h - written and placed in the public domain by Wei Dai
2 
3 //! \file eccrypto.h
4 //! \brief Classes and functions for schemes based on Discrete Logs (DL) over GF(p)
5 
6 #ifndef CRYPTOPP_GFPCRYPT_H
7 #define CRYPTOPP_GFPCRYPT_H
8 
9 #include "config.h"
10 
11 #if CRYPTOPP_MSC_VERSION
12 # pragma warning(push)
13 # pragma warning(disable: 4189)
14 #endif
15 
16 #include "cryptlib.h"
17 #include "pubkey.h"
18 #include "integer.h"
19 #include "modexppc.h"
20 #include "algparam.h"
21 #include "smartptr.h"
22 #include "sha.h"
23 #include "asn.h"
24 #include "hmac.h"
25 #include "misc.h"
26 
27 NAMESPACE_BEGIN(CryptoPP)
28 
29 CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters<Integer>;
30 
31 //! \class DL_GroupParameters_IntegerBased
32 //! \brief Integer-based GroupParameters specialization
33 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE DL_GroupParameters_IntegerBased : public ASN1CryptoMaterial<DL_GroupParameters<Integer> >
34 {
36 
37 public:
39 
40  //! \brief Initialize a group parameters over integers
41  //! \param params the group parameters
43  {Initialize(params.GetModulus(), params.GetSubgroupOrder(), params.GetSubgroupGenerator());}
44 
45  //! \brief Create a group parameters over integers
46  //! \param rng a RandomNumberGenerator derived class
47  //! \param pbits the size of p, in bits
48  //! \details This function overload of Initialize() creates a new private key because it
49  //! takes a RandomNumberGenerator() as a parameter. If you have an existing keypair,
50  //! then use one of the other Initialize() overloads.
51  void Initialize(RandomNumberGenerator &rng, unsigned int pbits)
52  {GenerateRandom(rng, MakeParameters("ModulusSize", (int)pbits));}
53 
54  //! \brief Initialize a group parameters over integers
55  //! \param p the modulus
56  //! \param g the generator
57  void Initialize(const Integer &p, const Integer &g)
58  {SetModulusAndSubgroupGenerator(p, g); SetSubgroupOrder(ComputeGroupOrder(p)/2);}
59 
60  //! \brief Initialize a group parameters over integers
61  //! \param p the modulus
62  //! \param q the subgroup order
63  //! \param g the generator
64  void Initialize(const Integer &p, const Integer &q, const Integer &g)
65  {SetModulusAndSubgroupGenerator(p, g); SetSubgroupOrder(q);}
66 
67  // ASN1Object interface
68  void BERDecode(BufferedTransformation &bt);
69  void DEREncode(BufferedTransformation &bt) const;
70 
71  // GeneratibleCryptoMaterial interface
72  /*! parameters: (ModulusSize, SubgroupOrderSize (optional)) */
73  void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg);
74  bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
75  void AssignFrom(const NameValuePairs &source);
76 
77  // DL_GroupParameters
78  const Integer & GetSubgroupOrder() const {return m_q;}
79  Integer GetGroupOrder() const {return GetFieldType() == 1 ? GetModulus()-Integer::One() : GetModulus()+Integer::One();}
80  bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const;
81  bool ValidateElement(unsigned int level, const Integer &element, const DL_FixedBasePrecomputation<Integer> *precomp) const;
82  bool FastSubgroupCheckAvailable() const {return GetCofactor() == 2;}
83 
84  // Cygwin i386 crash at -O3; see http://github.com/weidai11/cryptopp/issues/40.
85  void EncodeElement(bool reversible, const Element &element, byte *encoded) const;
86  unsigned int GetEncodedElementSize(bool reversible) const;
87 
88  Integer DecodeElement(const byte *encoded, bool checkForGroupMembership) const;
89  Integer ConvertElementToInteger(const Element &element) const
90  {return element;}
91  Integer GetMaxExponent() const;
92  static std::string CRYPTOPP_API StaticAlgorithmNamePrefix() {return "";}
93 
94  OID GetAlgorithmID() const;
95 
96  virtual const Integer & GetModulus() const =0;
97  virtual void SetModulusAndSubgroupGenerator(const Integer &p, const Integer &g) =0;
98 
99  void SetSubgroupOrder(const Integer &q)
100  {m_q = q; ParametersChanged();}
101 
102 protected:
103  Integer ComputeGroupOrder(const Integer &modulus) const
104  {return modulus-(GetFieldType() == 1 ? 1 : -1);}
105 
106  // GF(p) = 1, GF(p^2) = 2
107  virtual int GetFieldType() const =0;
108  virtual unsigned int GetDefaultSubgroupOrderSize(unsigned int modulusSize) const;
109 
110 private:
111  Integer m_q;
112 };
113 
114 //! \class DL_GroupParameters_IntegerBasedImpl
115 //! \brief Integer-based GroupParameters default implementation
116 //! \tparam GROUP_PRECOMP group parameters precomputation specialization
117 //! \tparam BASE_PRECOMP base class precomputation specialization
118 template <class GROUP_PRECOMP, class BASE_PRECOMP = DL_FixedBasePrecomputationImpl<typename GROUP_PRECOMP::Element> >
119 class CRYPTOPP_NO_VTABLE DL_GroupParameters_IntegerBasedImpl : public DL_GroupParametersImpl<GROUP_PRECOMP, BASE_PRECOMP, DL_GroupParameters_IntegerBased>
120 {
122 
123 public:
124  typedef typename GROUP_PRECOMP::Element Element;
125 
127 
128  // GeneratibleCryptoMaterial interface
129  bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
130  {return GetValueHelper<DL_GroupParameters_IntegerBased>(this, name, valueType, pValue).Assignable();}
131 
132  void AssignFrom(const NameValuePairs &source)
133  {AssignFromHelper<DL_GroupParameters_IntegerBased>(this, source);}
134 
135  // DL_GroupParameters
136  const DL_FixedBasePrecomputation<Element> & GetBasePrecomputation() const {return this->m_gpc;}
138 
139  // IntegerGroupParameters
140  const Integer & GetModulus() const {return this->m_groupPrecomputation.GetModulus();}
141  const Integer & GetGenerator() const {return this->m_gpc.GetBase(this->GetGroupPrecomputation());}
142 
143  void SetModulusAndSubgroupGenerator(const Integer &p, const Integer &g) // these have to be set together
144  {this->m_groupPrecomputation.SetModulus(p); this->m_gpc.SetBase(this->GetGroupPrecomputation(), g); this->ParametersChanged();}
145 
146  // non-inherited
148  {return GetModulus() == rhs.GetModulus() && GetGenerator() == rhs.GetGenerator() && this->GetSubgroupOrder() == rhs.GetSubgroupOrder();}
150  {return !operator==(rhs);}
151 };
152 
154 
155 //! \class DL_GroupParameters_GFP
156 //! \brief GF(p) group parameters
157 class CRYPTOPP_DLL DL_GroupParameters_GFP : public DL_GroupParameters_IntegerBasedImpl<ModExpPrecomputation>
158 {
159 public:
160  virtual ~DL_GroupParameters_GFP() {}
161 
162  // DL_GroupParameters
163  bool IsIdentity(const Integer &element) const {return element == Integer::One();}
164  void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
165 
166  // NameValuePairs interface
167  bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
168  {
169  return GetValueHelper<DL_GroupParameters_IntegerBased>(this, name, valueType, pValue).Assignable();
170  }
171 
172  // used by MQV
173  Element MultiplyElements(const Element &a, const Element &b) const;
174  Element CascadeExponentiate(const Element &element1, const Integer &exponent1, const Element &element2, const Integer &exponent2) const;
175 
176 protected:
177  int GetFieldType() const {return 1;}
178 };
179 
180 //! \class DL_GroupParameters_GFP
181 //! \brief GF(p) group parameters that default to safe primes
183 {
184 public:
186 
188 
189 protected:
190  unsigned int GetDefaultSubgroupOrderSize(unsigned int modulusSize) const {return modulusSize-1;}
191 };
192 
193 //! \class DL_Algorithm_GDSA
194 //! \brief GDSA algorithm
195 //! \tparam T FieldElement type or class
196 template <class T>
198 {
199 public:
200  CRYPTOPP_STATIC_CONSTEXPR const char* CRYPTOPP_API StaticAlgorithmName() {return "DSA-1363";}
201 
202  virtual ~DL_Algorithm_GDSA() {}
203 
204  void Sign(const DL_GroupParameters<T> &params, const Integer &x, const Integer &k, const Integer &e, Integer &r, Integer &s) const
205  {
206  const Integer &q = params.GetSubgroupOrder();
207  r %= q;
208  Integer kInv = k.InverseMod(q);
209  s = (kInv * (x*r + e)) % q;
210  CRYPTOPP_ASSERT(!!r && !!s);
211  }
212 
213  bool Verify(const DL_GroupParameters<T> &params, const DL_PublicKey<T> &publicKey, const Integer &e, const Integer &r, const Integer &s) const
214  {
215  const Integer &q = params.GetSubgroupOrder();
216  if (r>=q || r<1 || s>=q || s<1)
217  return false;
218 
219  Integer w = s.InverseMod(q);
220  Integer u1 = (e * w) % q;
221  Integer u2 = (r * w) % q;
222  // verify r == (g^u1 * y^u2 mod p) mod q
223  return r == params.ConvertElementToInteger(publicKey.CascadeExponentiateBaseAndPublicElement(u1, u2)) % q;
224  }
225 };
226 
227 CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_GDSA<Integer>;
228 
229 //! \class DL_Algorithm_NR
230 //! \brief NR algorithm
231 //! \tparam T FieldElement type or class
232 template <class T>
234 {
235 public:
236  CRYPTOPP_STATIC_CONSTEXPR const char* CRYPTOPP_API StaticAlgorithmName() {return "NR";}
237 
238  virtual ~DL_Algorithm_NR() {}
239 
240  void Sign(const DL_GroupParameters<T> &params, const Integer &x, const Integer &k, const Integer &e, Integer &r, Integer &s) const
241  {
242  const Integer &q = params.GetSubgroupOrder();
243  r = (r + e) % q;
244  s = (k - x*r) % q;
245  CRYPTOPP_ASSERT(!!r);
246  }
247 
248  bool Verify(const DL_GroupParameters<T> &params, const DL_PublicKey<T> &publicKey, const Integer &e, const Integer &r, const Integer &s) const
249  {
250  const Integer &q = params.GetSubgroupOrder();
251  if (r>=q || r<1 || s>=q)
252  return false;
253 
254  // check r == (m_g^s * m_y^r + m) mod m_q
255  return r == (params.ConvertElementToInteger(publicKey.CascadeExponentiateBaseAndPublicElement(s, r)) + e) % q;
256  }
257 };
258 
259 //! \class DL_PublicKey_GFP
260 //! \brief Discrete Log (DL) public key in GF(p) groups
261 //! \tparam GP GroupParameters derived class
262 //! \details DSA public key format is defined in 7.3.3 of RFC 2459. The private key format is defined in 12.9 of PKCS #11 v2.10.
263 template <class GP>
265 {
266 public:
267  virtual ~DL_PublicKey_GFP() {}
268 
269  //! \brief Initialize a public key over GF(p)
270  //! \param params the group parameters
271  //! \param y the public element
272  void Initialize(const DL_GroupParameters_IntegerBased &params, const Integer &y)
273  {this->AccessGroupParameters().Initialize(params); this->SetPublicElement(y);}
274 
275  //! \brief Initialize a public key over GF(p)
276  //! \param p the modulus
277  //! \param g the generator
278  //! \param y the public element
279  void Initialize(const Integer &p, const Integer &g, const Integer &y)
280  {this->AccessGroupParameters().Initialize(p, g); this->SetPublicElement(y);}
281 
282  //! \brief Initialize a public key over GF(p)
283  //! \param p the modulus
284  //! \param q the subgroup order
285  //! \param g the generator
286  //! \param y the public element
287  void Initialize(const Integer &p, const Integer &q, const Integer &g, const Integer &y)
288  {this->AccessGroupParameters().Initialize(p, q, g); this->SetPublicElement(y);}
289 
290  // X509PublicKey
292  {this->SetPublicElement(Integer(bt));}
294  {this->GetPublicElement().DEREncode(bt);}
295 };
296 
297 //! \class DL_PrivateKey_GFP
298 //! \brief Discrete Log (DL) private key in GF(p) groups
299 //! \tparam GP GroupParameters derived class
300 template <class GP>
302 {
303 public:
304  virtual ~DL_PrivateKey_GFP() {}
305 
306  //! \brief Create a private key
307  //! \param rng a RandomNumberGenerator derived class
308  //! \param modulusBits the size of the modulus, in bits
309  //! \details This function overload of Initialize() creates a new private key because it
310  //! takes a RandomNumberGenerator() as a parameter. If you have an existing keypair,
311  //! then use one of the other Initialize() overloads.
312  void Initialize(RandomNumberGenerator &rng, unsigned int modulusBits)
313  {this->GenerateRandomWithKeySize(rng, modulusBits);}
314 
315  //! \brief Create a private key
316  //! \param rng a RandomNumberGenerator derived class
317  //! \param p the modulus
318  //! \param g the generator
319  //! \details This function overload of Initialize() creates a new private key because it
320  //! takes a RandomNumberGenerator() as a parameter. If you have an existing keypair,
321  //! then use one of the other Initialize() overloads.
322  void Initialize(RandomNumberGenerator &rng, const Integer &p, const Integer &g)
323  {this->GenerateRandom(rng, MakeParameters("Modulus", p)("SubgroupGenerator", g));}
324 
325  //! \brief Create a private key
326  //! \param rng a RandomNumberGenerator derived class
327  //! \param p the modulus
328  //! \param q the subgroup order
329  //! \param g the generator
330  //! \details This function overload of Initialize() creates a new private key because it
331  //! takes a RandomNumberGenerator() as a parameter. If you have an existing keypair,
332  //! then use one of the other Initialize() overloads.
333  void Initialize(RandomNumberGenerator &rng, const Integer &p, const Integer &q, const Integer &g)
334  {this->GenerateRandom(rng, MakeParameters("Modulus", p)("SubgroupOrder", q)("SubgroupGenerator", g));}
335 
336  //! \brief Initialize a private key over GF(p)
337  //! \param params the group parameters
338  //! \param x the private exponent
339  void Initialize(const DL_GroupParameters_IntegerBased &params, const Integer &x)
340  {this->AccessGroupParameters().Initialize(params); this->SetPrivateExponent(x);}
341 
342  //! \brief Initialize a private key over GF(p)
343  //! \param p the modulus
344  //! \param g the generator
345  //! \param x the private exponent
346  void Initialize(const Integer &p, const Integer &g, const Integer &x)
347  {this->AccessGroupParameters().Initialize(p, g); this->SetPrivateExponent(x);}
348 
349  //! \brief Initialize a private key over GF(p)
350  //! \param p the modulus
351  //! \param q the subgroup order
352  //! \param g the generator
353  //! \param x the private exponent
354  void Initialize(const Integer &p, const Integer &q, const Integer &g, const Integer &x)
355  {this->AccessGroupParameters().Initialize(p, q, g); this->SetPrivateExponent(x);}
356 };
357 
358 //! \class DL_SignatureKeys_GFP
359 //! \brief Discrete Log (DL) signing/verification keys in GF(p) groups
361 {
365 };
366 
367 //! \class DL_CryptoKeys_GFP
368 //! \brief Discrete Log (DL) encryption/decryption keys in GF(p) groups
370 {
374 };
375 
376 //! \class DL_PublicKey_GFP_OldFormat
377 //! \brief Discrete Log (DL) public key in GF(p) groups
378 //! \tparam BASE GroupParameters derived class
379 //! \deprecated This implementation uses a non-standard Crypto++ key format. New implementations
380 //! should use DL_PublicKey_GFP and DL_PrivateKey_GFP
381 template <class BASE>
382 class DL_PublicKey_GFP_OldFormat : public BASE
383 {
384 public:
385  virtual ~DL_PublicKey_GFP_OldFormat() {}
386 
387  void BERDecode(BufferedTransformation &bt)
388  {
389  BERSequenceDecoder seq(bt);
390  Integer v1(seq);
391  Integer v2(seq);
392  Integer v3(seq);
393 
394  if (seq.EndReached())
395  {
396  this->AccessGroupParameters().Initialize(v1, v1/2, v2);
397  this->SetPublicElement(v3);
398  }
399  else
400  {
401  Integer v4(seq);
402  this->AccessGroupParameters().Initialize(v1, v2, v3);
403  this->SetPublicElement(v4);
404  }
405 
406  seq.MessageEnd();
407  }
408 
409  void DEREncode(BufferedTransformation &bt) const
410  {
411  DERSequenceEncoder seq(bt);
412  this->GetGroupParameters().GetModulus().DEREncode(seq);
413  if (this->GetGroupParameters().GetCofactor() != 2)
414  this->GetGroupParameters().GetSubgroupOrder().DEREncode(seq);
415  this->GetGroupParameters().GetGenerator().DEREncode(seq);
416  this->GetPublicElement().DEREncode(seq);
417  seq.MessageEnd();
418  }
419 };
420 
421 //! \class DL_PrivateKey_GFP_OldFormat
422 //! \brief Discrete Log (DL) private key in GF(p) groups
423 //! \tparam BASE GroupParameters derived class
424 //! \deprecated This implementation uses a non-standard Crypto++ key format. New implementations
425 //! should use DL_PublicKey_GFP and DL_PrivateKey_GFP
426 template <class BASE>
427 class DL_PrivateKey_GFP_OldFormat : public BASE
428 {
429 public:
430  virtual ~DL_PrivateKey_GFP_OldFormat() {}
431 
432  void BERDecode(BufferedTransformation &bt)
433  {
434  BERSequenceDecoder seq(bt);
435  Integer v1(seq);
436  Integer v2(seq);
437  Integer v3(seq);
438  Integer v4(seq);
439 
440  if (seq.EndReached())
441  {
442  this->AccessGroupParameters().Initialize(v1, v1/2, v2);
443  this->SetPrivateExponent(v4 % (v1/2)); // some old keys may have x >= q
444  }
445  else
446  {
447  Integer v5(seq);
448  this->AccessGroupParameters().Initialize(v1, v2, v3);
449  this->SetPrivateExponent(v5);
450  }
451 
452  seq.MessageEnd();
453  }
454 
455  void DEREncode(BufferedTransformation &bt) const
456  {
457  DERSequenceEncoder seq(bt);
458  this->GetGroupParameters().GetModulus().DEREncode(seq);
459  if (this->GetGroupParameters().GetCofactor() != 2)
460  this->GetGroupParameters().GetSubgroupOrder().DEREncode(seq);
461  this->GetGroupParameters().GetGenerator().DEREncode(seq);
462  this->GetGroupParameters().ExponentiateBase(this->GetPrivateExponent()).DEREncode(seq);
463  this->GetPrivateExponent().DEREncode(seq);
464  seq.MessageEnd();
465  }
466 };
467 
468 //! \class GDSA
469 //! \brief DSA signature scheme
470 //! \tparam H HashTransformation derived class
471 //! \sa <a href="http://www.weidai.com/scan-mirror/sig.html#DSA-1363">DSA-1363</a>
472 //! \since Crypto++ 1.0 for DSA, Crypto++ 5.6.2 for DSA2
473 template <class H>
474 struct GDSA : public DL_SS<
475  DL_SignatureKeys_GFP,
476  DL_Algorithm_GDSA<Integer>,
477  DL_SignatureMessageEncodingMethod_DSA,
478  H>
479 {
480 };
481 
482 //! \class NR
483 //! \brief NR signature scheme
484 //! \tparam H HashTransformation derived class
485 //! \sa <a href="http://www.weidai.com/scan-mirror/sig.html#NR">NR</a>
486 template <class H>
487 struct NR : public DL_SS<
488  DL_SignatureKeys_GFP,
489  DL_Algorithm_NR<Integer>,
490  DL_SignatureMessageEncodingMethod_NR,
491  H>
492 {
493 };
494 
495 //! \class DL_GroupParameters_DSA
496 //! \brief DSA group parameters
497 //! \details These are GF(p) group parameters that are allowed by the DSA standard
498 //! \sa DL_Keys_DSA
500 {
501 public:
502  virtual ~DL_GroupParameters_DSA() {}
503 
504  /*! also checks that the lengths of p and q are allowed by the DSA standard */
505  bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const;
506  /*! parameters: (ModulusSize), or (Modulus, SubgroupOrder, SubgroupGenerator) */
507  /*! ModulusSize must be between DSA::MIN_PRIME_LENGTH and DSA::MAX_PRIME_LENGTH, and divisible by DSA::PRIME_LENGTH_MULTIPLE */
508  void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg);
509 
510  static bool CRYPTOPP_API IsValidPrimeLength(unsigned int pbits)
511  {return pbits >= MIN_PRIME_LENGTH && pbits <= MAX_PRIME_LENGTH && pbits % PRIME_LENGTH_MULTIPLE == 0;}
512 
513  enum {MIN_PRIME_LENGTH = 1024, MAX_PRIME_LENGTH = 3072, PRIME_LENGTH_MULTIPLE = 1024};
514 };
515 
516 template <class H>
517 class DSA2;
518 
519 //! \class DL_Keys_DSA
520 //! \brief DSA keys
521 //! \sa DL_GroupParameters_DSA
523 {
526 };
527 
528 //! \class DSA2
529 //! \brief DSA signature scheme
530 //! \tparam H HashTransformation derived class
531 //! \details The class is named DSA2 instead of DSA for backwards compatibility because DSA was a non-template class.
532 //! \sa <a href="http://en.wikipedia.org/wiki/Digital_Signature_Algorithm">DSA</a>, as specified in FIPS 186-3
533 //! \since Crypto++ 1.0 for DSA, Crypto++ 5.6.2 for DSA2
534 template <class H>
535 class DSA2 : public DL_SS<
536  DL_Keys_DSA,
537  DL_Algorithm_GDSA<Integer>,
538  DL_SignatureMessageEncodingMethod_DSA,
539  H,
540  DSA2<H> >
541 {
542 public:
543  static std::string CRYPTOPP_API StaticAlgorithmName() {return "DSA/" + (std::string)H::StaticAlgorithmName();}
544 
545  //#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
546  //enum {MIN_PRIME_LENGTH = 1024, MAX_PRIME_LENGTH = 3072, PRIME_LENGTH_MULTIPLE = 1024};
547  //#endif
548 };
549 
550 //! DSA with SHA-1, typedef'd for backwards compatibility
551 typedef DSA2<SHA1> DSA;
552 
553 CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_GFP<DL_GroupParameters_DSA>;
554 CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_GFP<DL_GroupParameters_DSA>;
556 
557 //! \class DL_EncryptionAlgorithm_Xor
558 //! \brief P1363 based XOR Encryption Method
559 //! \tparam MAC MessageAuthenticationCode derived class used for MAC computation
560 //! \tparam DHAES_MODE flag indicating DHAES mode
561 //! \tparam LABEL_OCTETS flag indicating the label is octet count
562 //! \details DL_EncryptionAlgorithm_Xor is based on an early P1363 draft, which itself appears to be based on an
563 //! early Certicom SEC-1 draft (or an early SEC-1 draft was based on a P1363 draft). Crypto++ 4.2 used it in its Integrated
564 //! Ecryption Schemes with <tt>NoCofactorMultiplication</tt>, <tt>DHAES_MODE=false</tt> and <tt>LABEL_OCTETS=true</tt>.
565 //! \details If you need this method for Crypto++ 4.2 compatibility, then use the ECIES template class with
566 //! <tt>NoCofactorMultiplication</tt>, <tt>DHAES_MODE=false</tt> and <tt>LABEL_OCTETS=true</tt>.
567 //! \details If you need this method for Bouncy Castle 1.54 and Botan 1.11 compatibility, then use the ECIES template class with
568 //! <tt>NoCofactorMultiplication</tt>, <tt>DHAES_MODE=ture</tt> and <tt>LABEL_OCTETS=false</tt>.
569 //! \details Bouncy Castle 1.54 and Botan 1.11 compatibility are the default template parameters.
570 //! \since Crypto++ 4.0
571 template <class MAC, bool DHAES_MODE, bool LABEL_OCTETS=false>
573 {
574 public:
575  virtual ~DL_EncryptionAlgorithm_Xor() {}
576 
577  bool ParameterSupported(const char *name) const {return strcmp(name, Name::EncodingParameters()) == 0;}
578  size_t GetSymmetricKeyLength(size_t plaintextLength) const
579  {return plaintextLength + static_cast<size_t>(MAC::DIGESTSIZE);}
580  size_t GetSymmetricCiphertextLength(size_t plaintextLength) const
581  {return plaintextLength + static_cast<size_t>(MAC::DIGESTSIZE);}
582  size_t GetMaxSymmetricPlaintextLength(size_t ciphertextLength) const
583  {return SaturatingSubtract(ciphertextLength, static_cast<size_t>(MAC::DIGESTSIZE));}
584  void SymmetricEncrypt(RandomNumberGenerator &rng, const byte *key, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs &parameters) const
585  {
586  CRYPTOPP_UNUSED(rng);
587  const byte *cipherKey = NULL, *macKey = NULL;
588  if (DHAES_MODE)
589  {
590  macKey = key;
591  cipherKey = key + MAC::DEFAULT_KEYLENGTH;
592  }
593  else
594  {
595  cipherKey = key;
596  macKey = key + plaintextLength;
597  }
598 
599  ConstByteArrayParameter encodingParameters;
600  parameters.GetValue(Name::EncodingParameters(), encodingParameters);
601 
602  if (plaintextLength) // Coverity finding
603  xorbuf(ciphertext, plaintext, cipherKey, plaintextLength);
604 
605  MAC mac(macKey);
606  mac.Update(ciphertext, plaintextLength);
607  mac.Update(encodingParameters.begin(), encodingParameters.size());
608  if (DHAES_MODE)
609  {
610  byte L[8];
611  PutWord(false, BIG_ENDIAN_ORDER, L, (LABEL_OCTETS ? word64(encodingParameters.size()) : 8 * word64(encodingParameters.size())));
612  mac.Update(L, 8);
613  }
614  mac.Final(ciphertext + plaintextLength);
615  }
616  DecodingResult SymmetricDecrypt(const byte *key, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs &parameters) const
617  {
618  size_t plaintextLength = GetMaxSymmetricPlaintextLength(ciphertextLength);
619  const byte *cipherKey, *macKey;
620  if (DHAES_MODE)
621  {
622  macKey = key;
623  cipherKey = key + MAC::DEFAULT_KEYLENGTH;
624  }
625  else
626  {
627  cipherKey = key;
628  macKey = key + plaintextLength;
629  }
630 
631  ConstByteArrayParameter encodingParameters;
632  parameters.GetValue(Name::EncodingParameters(), encodingParameters);
633 
634  MAC mac(macKey);
635  mac.Update(ciphertext, plaintextLength);
636  mac.Update(encodingParameters.begin(), encodingParameters.size());
637  if (DHAES_MODE)
638  {
639  byte L[8];
640  PutWord(false, BIG_ENDIAN_ORDER, L, (LABEL_OCTETS ? word64(encodingParameters.size()) : 8 * word64(encodingParameters.size())));
641  mac.Update(L, 8);
642  }
643  if (!mac.Verify(ciphertext + plaintextLength))
644  return DecodingResult();
645 
646  if (plaintextLength) // Coverity finding
647  xorbuf(plaintext, ciphertext, cipherKey, plaintextLength);
648 
649  return DecodingResult(plaintextLength);
650  }
651 };
652 
653 //! _
654 template <class T, bool DHAES_MODE, class KDF>
656 {
657 public:
658  virtual ~DL_KeyDerivationAlgorithm_P1363() {}
659 
660  bool ParameterSupported(const char *name) const {return strcmp(name, Name::KeyDerivationParameters()) == 0;}
661  void Derive(const DL_GroupParameters<T> &params, byte *derivedKey, size_t derivedLength, const T &agreedElement, const T &ephemeralPublicKey, const NameValuePairs &parameters) const
662  {
663  SecByteBlock agreedSecret;
664  if (DHAES_MODE)
665  {
666  agreedSecret.New(params.GetEncodedElementSize(true) + params.GetEncodedElementSize(false));
667  params.EncodeElement(true, ephemeralPublicKey, agreedSecret);
668  params.EncodeElement(false, agreedElement, agreedSecret + params.GetEncodedElementSize(true));
669  }
670  else
671  {
672  agreedSecret.New(params.GetEncodedElementSize(false));
673  params.EncodeElement(false, agreedElement, agreedSecret);
674  }
675 
676  ConstByteArrayParameter derivationParameters;
677  parameters.GetValue(Name::KeyDerivationParameters(), derivationParameters);
678  KDF::DeriveKey(derivedKey, derivedLength, agreedSecret, agreedSecret.size(), derivationParameters.begin(), derivationParameters.size());
679  }
680 };
681 
682 //! \class DLIES
683 //! \brief Discrete Log Integrated Encryption Scheme
684 //! \tparam COFACTOR_OPTION \ref CofactorMultiplicationOption "cofactor multiplication option"
685 //! \tparam HASH HashTransformation derived class used for key drivation and MAC computation
686 //! \tparam DHAES_MODE flag indicating if the MAC includes addition context parameters such as the label
687 //! \tparam LABEL_OCTETS flag indicating if the label size is specified in octets or bits
688 //! \details DLIES is an Integer based Integrated Encryption Scheme (IES). The scheme combines a Key Encapsulation Method (KEM)
689 //! with a Data Encapsulation Method (DEM) and a MAC tag. The scheme is
690 //! <A HREF="http://en.wikipedia.org/wiki/ciphertext_indistinguishability">IND-CCA2</A>, which is a strong notion of security.
691 //! You should prefer an Integrated Encryption Scheme over homegrown schemes.
692 //! \details The library's original implementation is based on an early P1363 draft, which itself appears to be based on an early Certicom
693 //! SEC-1 draft (or an early SEC-1 draft was based on a P1363 draft). Crypto++ 4.2 used the early draft in its Integrated Ecryption
694 //! Schemes with <tt>NoCofactorMultiplication</tt>, <tt>DHAES_MODE=false</tt> and <tt>LABEL_OCTETS=true</tt>.
695 //! \details If you desire an Integrated Encryption Scheme with Crypto++ 4.2 compatibility, then use the DLIES template class with
696 //! <tt>NoCofactorMultiplication</tt>, <tt>DHAES_MODE=false</tt> and <tt>LABEL_OCTETS=true</tt>.
697 //! \details If you desire an Integrated Encryption Scheme with Bouncy Castle 1.54 and Botan 1.11 compatibility, then use the DLIES
698 //! template class with <tt>NoCofactorMultiplication</tt>, <tt>DHAES_MODE=true</tt> and <tt>LABEL_OCTETS=false</tt>.
699 //! \details The default template parameters ensure compatibility with Bouncy Castle 1.54 and Botan 1.11. The combination of
700 //! <tt>IncompatibleCofactorMultiplication</tt> and <tt>DHAES_MODE=true</tt> is recommended for best efficiency and security.
701 //! SHA1 is used for compatibility reasons, but it can be changed if desired. SHA-256 or another hash will likely improve the
702 //! security provided by the MAC. The hash is also used in the key derivation function as a PRF.
703 //! \details Below is an example of constructing a Crypto++ 4.2 compatible DLIES encryptor and decryptor.
704 //! <pre>
705 //! AutoSeededRandomPool prng;
706 //! DL_PrivateKey_GFP<DL_GroupParameters_GFP> key;
707 //! key.Initialize(prng, 2048);
708 //!
709 //! DLIES<SHA1,NoCofactorMultiplication,true,true>::Decryptor decryptor(key);
710 //! DLIES<SHA1,NoCofactorMultiplication,true,true>::Encryptor encryptor(decryptor);
711 //! </pre>
712 //! \sa ECIES, <a href="http://www.weidai.com/scan-mirror/ca.html#DLIES">Discrete Log Integrated Encryption Scheme (DLIES)</a>,
713 //! Martínez, Encinas, and Ávila's <A HREF="http://digital.csic.es/bitstream/10261/32671/1/V2-I2-P7-13.pdf">A Survey of the Elliptic
714 //! Curve Integrated Encryption Schemes</A>
715 //! \since Crypto++ 4.0, Crypto++ 5.7 for Bouncy Castle and Botan compatibility
716 template <class HASH = SHA1, class COFACTOR_OPTION = NoCofactorMultiplication, bool DHAES_MODE = true, bool LABEL_OCTETS=false>
717 struct DLIES
718  : public DL_ES<
719  DL_CryptoKeys_GFP,
720  DL_KeyAgreementAlgorithm_DH<Integer, COFACTOR_OPTION>,
721  DL_KeyDerivationAlgorithm_P1363<Integer, DHAES_MODE, P1363_KDF2<HASH> >,
722  DL_EncryptionAlgorithm_Xor<HMAC<HASH>, DHAES_MODE, LABEL_OCTETS>,
723  DLIES<> >
724 {
725  static std::string CRYPTOPP_API StaticAlgorithmName() {return "DLIES";} // TODO: fix this after name is standardized
726 };
727 
728 NAMESPACE_END
729 
730 #if CRYPTOPP_MSC_VERSION
731 # pragma warning(pop)
732 #endif
733 
734 #endif
Used to pass byte array input as part of a NameValuePairs object.
Definition: algparam.h:29
virtual void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const =0
Exponentiates a base to multiple exponents.
void Initialize(RandomNumberGenerator &rng, const Integer &p, const Integer &q, const Integer &g)
Create a private key.
Definition: gfpcrypt.h:333
bool IsIdentity(const Integer &element) const
Determines if an element is an identity.
Definition: gfpcrypt.h:163
Discrete Log Integrated Encryption Scheme.
Definition: gfpcrypt.h:717
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
Get a named value.
Definition: gfpcrypt.h:167
Classes for working with NameValuePairs.
Utility functions for the Crypto++ library.
GF(p) group parameters.
Definition: gfpcrypt.h:157
void Initialize(const DL_GroupParameters_IntegerBased &params, const Integer &y)
Initialize a public key over GF(p)
Definition: gfpcrypt.h:272
Integer GetGroupOrder() const
Retrieves the order of the group.
Definition: gfpcrypt.h:79
This file contains helper classes/functions for implementing public key algorithms.
void Initialize(RandomNumberGenerator &rng, unsigned int modulusBits)
Create a private key.
Definition: gfpcrypt.h:312
void PutWord(bool assumeAligned, ByteOrder order, byte *block, T value, const byte *xorBlock=NULL)
Access a block of memory.
Definition: misc.h:2123
void Initialize(const Integer &p, const Integer &g)
Initialize a group parameters over integers.
Definition: gfpcrypt.h:57
virtual Integer ConvertElementToInteger(const Element &element) const =0
Converts an element to an Integer.
Interface for Discrete Log (DL) group parameters.
Definition: pubkey.h:730
P1363 based XOR Encryption Method.
Definition: gfpcrypt.h:572
Converts an enumeration to a type suitable for use as a template parameter.
Definition: cryptlib.h:116
Abstract base classes that provide a uniform interface to this library.
size_type size() const
Provides the count of elements in the SecBlock.
Definition: secblock.h:524
Interface for key derivation algorithms used in DL cryptosystems.
Definition: pubkey.h:1285
Classes for automatic resource management.
size_t size() const
Length of the memory block.
Definition: algparam.h:93
Library configuration file.
DSA keys.
Definition: gfpcrypt.h:522
Interface for random number generators.
Definition: cryptlib.h:1188
void Initialize(RandomNumberGenerator &rng, unsigned int pbits)
Create a group parameters over integers.
Definition: gfpcrypt.h:51
void New(size_type newSize)
Change size without preserving contents.
Definition: secblock.h:647
Discrete Log (DL) encryption scheme.
Definition: pubkey.h:2120
SecBlock typedef.
Definition: secblock.h:731
BER Sequence Decoder.
Definition: asn.h:302
Interface for buffered transformations.
Definition: cryptlib.h:1352
DSA signature scheme.
Definition: gfpcrypt.h:474
const byte * begin() const
Pointer to the first byte in the memory block.
Definition: algparam.h:89
static const Integer & One()
Integer representing 1.
Definition: integer.cpp:3035
bool operator==(const OID &lhs, const OID &rhs)
Compare two OIDs for equality.
Interface for Discrete Log (DL) public keys.
Definition: pubkey.h:986
virtual const Element & GetSubgroupGenerator() const
Retrieves the subgroup generator.
Definition: pubkey.h:787
void Initialize(const Integer &p, const Integer &q, const Integer &g)
Initialize a group parameters over integers.
Definition: gfpcrypt.h:64
Discrete Log (DL) signature scheme.
Definition: pubkey.h:2097
void Initialize(RandomNumberGenerator &rng, const Integer &p, const Integer &g)
Create a private key.
Definition: gfpcrypt.h:322
Integer ConvertElementToInteger(const Element &element) const
Converts an element to an Integer.
Definition: gfpcrypt.h:89
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
Get a named value.
Definition: gfpcrypt.h:129
bool operator!=(const OID &lhs, const OID &rhs)
Compare two OIDs for inequality.
virtual void EncodeElement(bool reversible, const Element &element, byte *encoded) const =0
Encodes the element.
DL_FixedBasePrecomputation< Element > & AccessBasePrecomputation()
Retrieves the group precomputation.
Definition: gfpcrypt.h:137
Returns a decoding results.
Definition: cryptlib.h:238
Classes for HMAC message authentication codes.
bool GetValue(const char *name, T &value) const
Get a named value.
Definition: cryptlib.h:337
DSA signature scheme.
Definition: gfpcrypt.h:517
Discrete Log (DL) public key in GF(p) groups.
Definition: gfpcrypt.h:382
AlgorithmParameters MakeParameters(const char *name, const T &value, bool throwIfNotUsed=true)
Create an object that implements NameValuePairs.
Definition: algparam.h:500
Interface for Elgamal-like signature algorithms.
Definition: pubkey.h:1251
void Initialize(const Integer &p, const Integer &g, const Integer &y)
Initialize a public key over GF(p)
Definition: gfpcrypt.h:279
const char * EncodingParameters()
ConstByteArrayParameter.
Definition: argnames.h:66
Discrete Log (DL) signing/verification keys in GF(p) groups.
Definition: gfpcrypt.h:360
Discrete Log (DL) encryption/decryption keys in GF(p) groups.
Definition: gfpcrypt.h:369
const Integer & GetSubgroupOrder() const
Retrieves the subgroup order.
Definition: gfpcrypt.h:78
Multiple precision integer with arithmetic operations.
Definition: integer.h:43
NR signature scheme.
Definition: gfpcrypt.h:487
T1 SaturatingSubtract(const T1 &a, const T2 &b)
Performs a saturating subtract clamped at 0.
Definition: misc.h:847
Integer-based GroupParameters default implementation.
Definition: gfpcrypt.h:119
virtual const Integer & GetSubgroupOrder() const =0
Retrieves the subgroup order.
const DL_GroupPrecomputation< Element > & GetGroupPrecomputation() const
Retrieves the group precomputation.
Definition: pubkey.h:952
const DL_FixedBasePrecomputation< Element > & GetBasePrecomputation() const
Retrieves the group precomputation.
Definition: gfpcrypt.h:136
void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg)
Definition: gfpcrypt.cpp:179
byte order is big-endian
Definition: cryptlib.h:128
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:62
DSA group parameters.
Definition: gfpcrypt.h:499
Classes and functions for working with ANS.1 objects.
Classes for SHA-1 and SHA-2 family of message digests.
void Initialize(const Integer &p, const Integer &q, const Integer &g, const Integer &x)
Initialize a private key over GF(p)
Definition: gfpcrypt.h:354
void Initialize(const DL_GroupParameters_IntegerBased &params)
Initialize a group parameters over integers.
Definition: gfpcrypt.h:42
Discrete Log (DL) public key in GF(p) groups.
Definition: gfpcrypt.h:264
DER Sequence Encoder.
Definition: asn.h:312
Discrete Log (DL) private key in GF(p) groups.
Definition: gfpcrypt.h:427
virtual unsigned int GetEncodedElementSize(bool reversible) const =0
Retrieves the encoded element's size.
Discrete Log (DL) private key in GF(p) groups.
Definition: gfpcrypt.h:301
GDSA algorithm.
Definition: gfpcrypt.h:197
void xorbuf(byte *buf, const byte *mask, size_t count)
Performs an XOR of a buffer with a mask.
Definition: misc.cpp:28
void Initialize(const DL_GroupParameters_IntegerBased &params, const Integer &x)
Initialize a private key over GF(p)
Definition: gfpcrypt.h:339
bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const
Check the group for errors.
Definition: gfpcrypt.cpp:129
Integer InverseMod(const Integer &n) const
calculate multiplicative inverse of *this mod n
Definition: integer.cpp:4370
void GenerateRandomWithKeySize(RandomNumberGenerator &rng, unsigned int keySize)
Generate a random key or crypto parameters.
Definition: cryptlib.cpp:780
NR algorithm.
Definition: gfpcrypt.h:233
void AssignFrom(const NameValuePairs &source)
Assign values to this object.
Definition: gfpcrypt.h:132
Multiple precision integer with arithmetic operations.
void DEREncodePublicKey(BufferedTransformation &bt) const
encode subjectPublicKey part of subjectPublicKeyInfo, without the BIT STRING header ...
Definition: gfpcrypt.h:293
const char * KeyDerivationParameters()
ConstByteArrayParameter.
Definition: argnames.h:67
Crypto++ library namespace.
Interface for symmetric encryption algorithms used in DL cryptosystems.
Definition: pubkey.h:1296
Base implmentation of Discrete Log (DL) group parameters.
Definition: pubkey.h:941
void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &params)
Generate a random key or crypto parameters.
Definition: pubkey.h:1129
void BERDecodePublicKey(BufferedTransformation &bt, bool, size_t)
decode subjectPublicKey part of subjectPublicKeyInfo, without the BIT STRING header ...
Definition: gfpcrypt.h:291
void Initialize(const Integer &p, const Integer &q, const Integer &g, const Integer &y)
Initialize a public key over GF(p)
Definition: gfpcrypt.h:287
Integer-based GroupParameters specialization.
Definition: gfpcrypt.h:33
Encode and decode ASN.1 objects with additional information.
Definition: asn.h:373
void Initialize(const Integer &p, const Integer &g, const Integer &x)
Initialize a private key over GF(p)
Definition: gfpcrypt.h:346
Object Identifier.
Definition: asn.h:165
Interface for retrieving values given their names.
Definition: cryptlib.h:279