source: git/src-cryptopp/pubkey.h

Last change on this file was e230cb0, checked in by David Stainton <dstainton415@…>, at 2016-10-12T13:27:29Z

Add cryptopp from tag CRYPTOPP_5_6_5

  • Property mode set to 100644
File size: 93.0 KB
Line 
1// pubkey.h - written and placed in the public domain by Wei Dai
2
3//! \file pubkey.h
4//! \brief This file contains helper classes/functions for implementing public key algorithms.
5//! \details The class hierachies in this header file tend to look like this:
6//!
7//! <pre>
8//!                   x1
9//!                  +--+
10//!                  |  |
11//!                 y1  z1
12//!                  |  |
13//!             x2<y1>  x2<z1>
14//!                  |  |
15//!                 y2  z2
16//!                  |  |
17//!             x3<y2>  x3<z2>
18//!                  |  |
19//!                 y3  z3
20//! </pre>
21//!
22//! <ul>
23//!   <li>x1, y1, z1 are abstract interface classes defined in cryptlib.h
24//!   <li>x2, y2, z2 are implementations of the interfaces using "abstract policies", which
25//!       are pure virtual functions that should return interfaces to interchangeable algorithms.
26//!       These classes have \p Base suffixes.
27//!   <li>x3, y3, z3 hold actual algorithms and implement those virtual functions.
28//!       These classes have \p Impl suffixes.
29//! </ul>
30//!
31//! \details The \p TF_ prefix means an implementation using trapdoor functions on integers.
32//! \details The \p DL_ prefix means an implementation using group operations in groups where discrete log is hard.
33
34#ifndef CRYPTOPP_PUBKEY_H
35#define CRYPTOPP_PUBKEY_H
36
37#include "config.h"
38
39#if CRYPTOPP_MSC_VERSION
40# pragma warning(push)
41# pragma warning(disable: 4702)
42#endif
43
44#include "cryptlib.h"
45#include "integer.h"
46#include "algebra.h"
47#include "modarith.h"
48#include "filters.h"
49#include "eprecomp.h"
50#include "fips140.h"
51#include "argnames.h"
52#include "smartptr.h"
53#include "stdcpp.h"
54
55// VC60 workaround: this macro is defined in shlobj.h and conflicts with a template parameter used in this file
56#undef INTERFACE
57
58#if defined(__SUNPRO_CC)
59# define MAYBE_RETURN(x) return x
60#else
61# define MAYBE_RETURN(x) CRYPTOPP_UNUSED(x)
62#endif
63
64NAMESPACE_BEGIN(CryptoPP)
65
66//! \class TrapdoorFunctionBounds
67//! \brief Provides range for plaintext and ciphertext lengths
68//! \details A trapdoor function is a function that is easy to compute in one direction,
69//!   but difficult to compute in the opposite direction without special knowledge.
70//!   The special knowledge is usually the private key.
71//! \details Trapdoor functions only handle messages of a limited length or size.
72//!   \p MaxPreimage is the plaintext's maximum length, and \p MaxImage is the
73//!   ciphertext's maximum length.
74//! \sa TrapdoorFunctionBounds(), RandomizedTrapdoorFunction(), TrapdoorFunction(),
75//!   RandomizedTrapdoorFunctionInverse() and TrapdoorFunctionInverse()
76class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TrapdoorFunctionBounds
77{
78public:
79        virtual ~TrapdoorFunctionBounds() {}
80
81        //! \brief Returns the maximum size of a message before the trapdoor function is applied
82        //! \returns the maximum size of a message before the trapdoor function is applied
83        //! \details Derived classes must implement \p PreimageBound().
84        virtual Integer PreimageBound() const =0;
85        //! \brief Returns the maximum size of a message after the trapdoor function is applied
86        //! \returns the maximum size of a message after the trapdoor function is applied
87        //! \details Derived classes must implement \p ImageBound().
88        virtual Integer ImageBound() const =0;
89        //! \brief Returns the maximum size of a message before the trapdoor function is applied bound to a public key
90        //! \returns the maximum size of a message before the trapdoor function is applied bound to a public key
91        //! \details The default implementation returns <tt>PreimageBound() - 1</tt>.
92        virtual Integer MaxPreimage() const {return --PreimageBound();}
93        //! \brief Returns the maximum size of a message after the trapdoor function is applied bound to a public key
94        //! \returns the the maximum size of a message after the trapdoor function is applied bound to a public key
95        //! \details The default implementation returns <tt>ImageBound() - 1</tt>.
96        virtual Integer MaxImage() const {return --ImageBound();}
97};
98
99//! \class RandomizedTrapdoorFunction
100//! \brief Applies the trapdoor function, using random data if required
101//! \details \p ApplyFunction() is the foundation for encrypting a message under a public key.
102//!   Derived classes will override it at some point.
103//! \sa TrapdoorFunctionBounds(), RandomizedTrapdoorFunction(), TrapdoorFunction(),
104//!   RandomizedTrapdoorFunctionInverse() and TrapdoorFunctionInverse()
105class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE RandomizedTrapdoorFunction : public TrapdoorFunctionBounds
106{
107public:
108#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
109        virtual ~RandomizedTrapdoorFunction() { }
110#endif
111
112        //! \brief Applies the trapdoor function, using random data if required
113        //! \param rng a \p RandomNumberGenerator derived class
114        //! \param x the message on which the encryption function is applied
115        //! \returns the message \p x encrypted under the public key
116        //! \details \p ApplyRandomizedFunction is a generalization of encryption under a public key
117        //!    cryptosystem. The \p RandomNumberGenerator may (or may not) be required.
118        //!    Derived classes must implement it.
119        virtual Integer ApplyRandomizedFunction(RandomNumberGenerator &rng, const Integer &x) const =0;
120
121        //! \brief Determines if the encryption algorithm is randomized
122        //! \returns \p true if the encryption algorithm is randomized, \p false otherwise
123        //! \details If \p IsRandomized() returns \p false, then \p NullRNG() can be used.
124        virtual bool IsRandomized() const {return true;}
125};
126
127//! \class TrapdoorFunction
128//! \brief Applies the trapdoor function
129//! \details \p ApplyFunction() is the foundation for encrypting a message under a public key.
130//!    Derived classes will override it at some point.
131//! \sa TrapdoorFunctionBounds(), RandomizedTrapdoorFunction(), TrapdoorFunction(),
132//!   RandomizedTrapdoorFunctionInverse() and TrapdoorFunctionInverse()
133class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TrapdoorFunction : public RandomizedTrapdoorFunction
134{
135public:
136#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
137        virtual ~TrapdoorFunction() { }
138#endif
139
140        //! \brief Applies the trapdoor function
141        //! \param rng a \p RandomNumberGenerator derived class
142        //! \param x the message on which the encryption function is applied
143        //! \details \p ApplyRandomizedFunction is a generalization of encryption under a public key
144        //!    cryptosystem. The \p RandomNumberGenerator may (or may not) be required.
145        //! \details Internally, \p ApplyRandomizedFunction() calls \p ApplyFunction() \a
146        //!   without the \p RandomNumberGenerator.
147        Integer ApplyRandomizedFunction(RandomNumberGenerator &rng, const Integer &x) const
148                {CRYPTOPP_UNUSED(rng); return ApplyFunction(x);}
149        bool IsRandomized() const {return false;}
150
151        //! \brief Applies the trapdoor
152        //! \param x the message on which the encryption function is applied
153        //! \returns the message \p x encrypted under the public key
154        //! \details \p ApplyFunction is a generalization of encryption under a public key
155        //!    cryptosystem. Derived classes must implement it.
156        virtual Integer ApplyFunction(const Integer &x) const =0;
157};
158
159//! \class RandomizedTrapdoorFunctionInverse
160//! \brief Applies the inverse of the trapdoor function, using random data if required
161//! \details \p CalculateInverse() is the foundation for decrypting a message under a private key
162//!   in a public key cryptosystem. Derived classes will override it at some point.
163//! \sa TrapdoorFunctionBounds(), RandomizedTrapdoorFunction(), TrapdoorFunction(),
164//!   RandomizedTrapdoorFunctionInverse() and TrapdoorFunctionInverse()
165class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE RandomizedTrapdoorFunctionInverse
166{
167public:
168        virtual ~RandomizedTrapdoorFunctionInverse() {}
169
170        //! \brief Applies the inverse of the trapdoor function, using random data if required
171        //! \param rng a \p RandomNumberGenerator derived class
172        //! \param x the message on which the decryption function is applied
173        //! \returns the message \p x decrypted under the private key
174        //! \details \p CalculateRandomizedInverse is a generalization of decryption using the private key
175        //!    The \p RandomNumberGenerator may (or may not) be required. Derived classes must implement it.
176        virtual Integer CalculateRandomizedInverse(RandomNumberGenerator &rng, const Integer &x) const =0;
177
178        //! \brief Determines if the decryption algorithm is randomized
179        //! \returns \p true if the decryption algorithm is randomized, \p false otherwise
180        //! \details If \p IsRandomized() returns \p false, then \p NullRNG() can be used.
181        virtual bool IsRandomized() const {return true;}
182};
183
184//! \class TrapdoorFunctionInverse
185//! \brief Applies the inverse of the trapdoor function
186//! \details \p CalculateInverse() is the foundation for decrypting a message under a private key
187//!   in a public key cryptosystem. Derived classes will override it at some point.
188//! \sa TrapdoorFunctionBounds(), RandomizedTrapdoorFunction(), TrapdoorFunction(),
189//!   RandomizedTrapdoorFunctionInverse() and TrapdoorFunctionInverse()
190class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TrapdoorFunctionInverse : public RandomizedTrapdoorFunctionInverse
191{
192public:
193        virtual ~TrapdoorFunctionInverse() {}
194
195        //! \brief Applies the inverse of the trapdoor function
196        //! \param rng a \p RandomNumberGenerator derived class
197        //! \param x the message on which the decryption function is applied
198        //! \returns the message \p x decrypted under the private key
199        //! \details \p CalculateRandomizedInverse is a generalization of decryption using the private key
200        //! \details Internally, \p CalculateRandomizedInverse() calls \p CalculateInverse() \a
201        //!   without the \p RandomNumberGenerator.
202        Integer CalculateRandomizedInverse(RandomNumberGenerator &rng, const Integer &x) const
203                {return CalculateInverse(rng, x);}
204
205        //! \brief Determines if the decryption algorithm is randomized
206        //! \returns \p true if the decryption algorithm is randomized, \p false otherwise
207        //! \details If \p IsRandomized() returns \p false, then \p NullRNG() can be used.
208        bool IsRandomized() const {return false;}
209
210        //! \brief Calculates the inverse of an element
211        //! \param rng a \p RandomNumberGenerator derived class
212        //! \param x the element
213        //! \returns the inverse of the element in the group
214        virtual Integer CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const =0;
215};
216
217// ********************************************************
218
219//! \class PK_EncryptionMessageEncodingMethod
220//! \brief Message encoding method for public key encryption
221class CRYPTOPP_NO_VTABLE PK_EncryptionMessageEncodingMethod
222{
223public:
224        virtual ~PK_EncryptionMessageEncodingMethod() {}
225
226        virtual bool ParameterSupported(const char *name) const
227                {CRYPTOPP_UNUSED(name); return false;}
228
229        //! max size of unpadded message in bytes, given max size of padded message in bits (1 less than size of modulus)
230        virtual size_t MaxUnpaddedLength(size_t paddedLength) const =0;
231
232        virtual void Pad(RandomNumberGenerator &rng, const byte *raw, size_t inputLength, byte *padded, size_t paddedBitLength, const NameValuePairs &parameters) const =0;
233
234        virtual DecodingResult Unpad(const byte *padded, size_t paddedBitLength, byte *raw, const NameValuePairs &parameters) const =0;
235};
236
237// ********************************************************
238
239//! \class TF_Base
240//! \brief The base for trapdoor based cryptosystems
241//! \tparam TFI trapdoor function interface derived class
242//! \tparam MEI message encoding interface derived class
243template <class TFI, class MEI>
244class CRYPTOPP_NO_VTABLE TF_Base
245{
246protected:
247#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
248        virtual ~TF_Base() { }
249#endif
250
251        virtual const TrapdoorFunctionBounds & GetTrapdoorFunctionBounds() const =0;
252
253        typedef TFI TrapdoorFunctionInterface;
254        virtual const TrapdoorFunctionInterface & GetTrapdoorFunctionInterface() const =0;
255
256        typedef MEI MessageEncodingInterface;
257        virtual const MessageEncodingInterface & GetMessageEncodingInterface() const =0;
258};
259
260// ********************************************************
261
262//! \class PK_FixedLengthCryptoSystemImpl
263//! \brief Public key trapdoor function default implementation
264//! \tparam BASE public key cryptosystem with a fixed length
265template <class BASE>
266class CRYPTOPP_NO_VTABLE PK_FixedLengthCryptoSystemImpl : public BASE
267{
268public:
269#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
270        virtual ~PK_FixedLengthCryptoSystemImpl() { }
271#endif
272
273        size_t MaxPlaintextLength(size_t ciphertextLength) const
274                {return ciphertextLength == FixedCiphertextLength() ? FixedMaxPlaintextLength() : 0;}
275        size_t CiphertextLength(size_t plaintextLength) const
276                {return plaintextLength <= FixedMaxPlaintextLength() ? FixedCiphertextLength() : 0;}
277
278        virtual size_t FixedMaxPlaintextLength() const =0;
279        virtual size_t FixedCiphertextLength() const =0;
280};
281
282//! \class TF_CryptoSystemBase
283//! \brief Trapdoor function cryptosystem base class
284//! \tparam INTERFACE public key cryptosystem base interface
285//! \tparam BASE public key cryptosystem implementation base
286template <class INTERFACE, class BASE>
287class CRYPTOPP_NO_VTABLE TF_CryptoSystemBase : public PK_FixedLengthCryptoSystemImpl<INTERFACE>, protected BASE
288{
289public:
290#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
291        virtual ~TF_CryptoSystemBase() { }
292#endif
293
294        bool ParameterSupported(const char *name) const {return this->GetMessageEncodingInterface().ParameterSupported(name);}
295        size_t FixedMaxPlaintextLength() const {return this->GetMessageEncodingInterface().MaxUnpaddedLength(PaddedBlockBitLength());}
296        size_t FixedCiphertextLength() const {return this->GetTrapdoorFunctionBounds().MaxImage().ByteCount();}
297
298protected:
299        size_t PaddedBlockByteLength() const {return BitsToBytes(PaddedBlockBitLength());}
300        // Coverity finding on potential overflow/underflow.
301        size_t PaddedBlockBitLength() const {return SaturatingSubtract(this->GetTrapdoorFunctionBounds().PreimageBound().BitCount(),1U);}
302};
303
304//! \class TF_DecryptorBase
305//! \brief Trapdoor function cryptosystems decryption base class
306class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_DecryptorBase : public TF_CryptoSystemBase<PK_Decryptor, TF_Base<TrapdoorFunctionInverse, PK_EncryptionMessageEncodingMethod> >
307{
308public:
309#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
310        virtual ~TF_DecryptorBase() { }
311#endif
312
313        DecodingResult Decrypt(RandomNumberGenerator &rng, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs &parameters = g_nullNameValuePairs) const;
314};
315
316//! \class TF_DecryptorBase
317//! \brief Trapdoor function cryptosystems encryption base class
318class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_EncryptorBase : public TF_CryptoSystemBase<PK_Encryptor, TF_Base<RandomizedTrapdoorFunction, PK_EncryptionMessageEncodingMethod> >
319{
320public:
321#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
322        virtual ~TF_EncryptorBase() { }
323#endif
324
325        void Encrypt(RandomNumberGenerator &rng, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs &parameters = g_nullNameValuePairs) const;
326};
327
328// ********************************************************
329
330// Typedef change due to Clang, http://github.com/weidai11/cryptopp/issues/300
331typedef std::pair<const byte *, unsigned int> HashIdentifier;
332
333//! \class PK_SignatureMessageEncodingMethod
334//! \brief Interface for message encoding method for public key signature schemes.
335//! \details \p PK_SignatureMessageEncodingMethod provides interfaces for message
336//!   encoding method for public key signature schemes. The methods support both
337//!   trapdoor functions (<tt>TF_*</tt>) and discrete logarithm (<tt>DL_*</tt>)
338//!   based schemes.
339class CRYPTOPP_NO_VTABLE PK_SignatureMessageEncodingMethod
340{
341public:
342        virtual ~PK_SignatureMessageEncodingMethod() {}
343
344        virtual size_t MinRepresentativeBitLength(size_t hashIdentifierLength, size_t digestLength) const
345                {CRYPTOPP_UNUSED(hashIdentifierLength); CRYPTOPP_UNUSED(digestLength); return 0;}
346        virtual size_t MaxRecoverableLength(size_t representativeBitLength, size_t hashIdentifierLength, size_t digestLength) const
347                {CRYPTOPP_UNUSED(representativeBitLength); CRYPTOPP_UNUSED(representativeBitLength); CRYPTOPP_UNUSED(hashIdentifierLength); CRYPTOPP_UNUSED(digestLength); return 0;}
348
349        bool IsProbabilistic() const
350                {return true;}
351        bool AllowNonrecoverablePart() const
352                {throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");}
353        virtual bool RecoverablePartFirst() const
354                {throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");}
355
356        // for verification, DL
357        virtual void ProcessSemisignature(HashTransformation &hash, const byte *semisignature, size_t semisignatureLength) const
358                {CRYPTOPP_UNUSED(hash); CRYPTOPP_UNUSED(semisignature); CRYPTOPP_UNUSED(semisignatureLength);}
359
360        // for signature
361        virtual void ProcessRecoverableMessage(HashTransformation &hash,
362                const byte *recoverableMessage, size_t recoverableMessageLength,
363                const byte *presignature, size_t presignatureLength,
364                SecByteBlock &semisignature) const
365        {
366                CRYPTOPP_UNUSED(hash);CRYPTOPP_UNUSED(recoverableMessage); CRYPTOPP_UNUSED(recoverableMessageLength);
367                CRYPTOPP_UNUSED(presignature); CRYPTOPP_UNUSED(presignatureLength); CRYPTOPP_UNUSED(semisignature);
368                if (RecoverablePartFirst())
369                        CRYPTOPP_ASSERT(!"ProcessRecoverableMessage() not implemented");
370        }
371
372        virtual void ComputeMessageRepresentative(RandomNumberGenerator &rng,
373                const byte *recoverableMessage, size_t recoverableMessageLength,
374                HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
375                byte *representative, size_t representativeBitLength) const =0;
376
377        virtual bool VerifyMessageRepresentative(
378                HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
379                byte *representative, size_t representativeBitLength) const =0;
380
381        virtual DecodingResult RecoverMessageFromRepresentative(        // for TF
382                HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
383                byte *representative, size_t representativeBitLength,
384                byte *recoveredMessage) const
385                {CRYPTOPP_UNUSED(hash);CRYPTOPP_UNUSED(hashIdentifier); CRYPTOPP_UNUSED(messageEmpty);
386                CRYPTOPP_UNUSED(representative); CRYPTOPP_UNUSED(representativeBitLength); CRYPTOPP_UNUSED(recoveredMessage);
387                throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");}
388
389        virtual DecodingResult RecoverMessageFromSemisignature(         // for DL
390                HashTransformation &hash, HashIdentifier hashIdentifier,
391                const byte *presignature, size_t presignatureLength,
392                const byte *semisignature, size_t semisignatureLength,
393                byte *recoveredMessage) const
394                {CRYPTOPP_UNUSED(hash);CRYPTOPP_UNUSED(hashIdentifier); CRYPTOPP_UNUSED(presignature); CRYPTOPP_UNUSED(presignatureLength);
395                CRYPTOPP_UNUSED(semisignature); CRYPTOPP_UNUSED(semisignatureLength); CRYPTOPP_UNUSED(recoveredMessage);
396                throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");}
397
398        // VC60 workaround
399        struct HashIdentifierLookup
400        {
401                template <class H> struct HashIdentifierLookup2
402                {
403                        static HashIdentifier CRYPTOPP_API Lookup()
404                        {
405                                return HashIdentifier((const byte *)NULL, 0);
406                        }
407                };
408        };
409};
410
411//! \class PK_DeterministicSignatureMessageEncodingMethod
412//! \brief Interface for message encoding method for public key signature schemes.
413//! \details \p PK_DeterministicSignatureMessageEncodingMethod provides interfaces
414//!   for message encoding method for public key signature schemes.
415class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_DeterministicSignatureMessageEncodingMethod : public PK_SignatureMessageEncodingMethod
416{
417public:
418        bool VerifyMessageRepresentative(
419                HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
420                byte *representative, size_t representativeBitLength) const;
421};
422
423//! \class PK_RecoverableSignatureMessageEncodingMethod
424//! \brief Interface for message encoding method for public key signature schemes.
425//! \details \p PK_RecoverableSignatureMessageEncodingMethod provides interfaces
426//!   for message encoding method for public key signature schemes.
427class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_RecoverableSignatureMessageEncodingMethod : public PK_SignatureMessageEncodingMethod
428{
429public:
430        bool VerifyMessageRepresentative(
431                HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
432                byte *representative, size_t representativeBitLength) const;
433};
434
435//! \class DL_SignatureMessageEncodingMethod_DSA
436//! \brief Interface for message encoding method for public key signature schemes.
437//! \details \p DL_SignatureMessageEncodingMethod_DSA provides interfaces
438//!   for message encoding method for DSA.
439class CRYPTOPP_DLL DL_SignatureMessageEncodingMethod_DSA : public PK_DeterministicSignatureMessageEncodingMethod
440{
441public:
442        void ComputeMessageRepresentative(RandomNumberGenerator &rng,
443                const byte *recoverableMessage, size_t recoverableMessageLength,
444                HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
445                byte *representative, size_t representativeBitLength) const;
446};
447
448//! \class DL_SignatureMessageEncodingMethod_NR
449//! \brief Interface for message encoding method for public key signature schemes.
450//! \details \p DL_SignatureMessageEncodingMethod_NR provides interfaces
451//!   for message encoding method for Nyberg-Rueppel.
452class CRYPTOPP_DLL DL_SignatureMessageEncodingMethod_NR : public PK_DeterministicSignatureMessageEncodingMethod
453{
454public:
455        void ComputeMessageRepresentative(RandomNumberGenerator &rng,
456                const byte *recoverableMessage, size_t recoverableMessageLength,
457                HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
458                byte *representative, size_t representativeBitLength) const;
459};
460
461//! \class PK_MessageAccumulatorBase
462//! \brief Interface for message encoding method for public key signature schemes.
463//! \details \p PK_MessageAccumulatorBase provides interfaces
464//!   for message encoding method.
465class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_MessageAccumulatorBase : public PK_MessageAccumulator
466{
467public:
468        PK_MessageAccumulatorBase() : m_empty(true) {}
469
470        virtual HashTransformation & AccessHash() =0;
471
472        void Update(const byte *input, size_t length)
473        {
474                AccessHash().Update(input, length);
475                m_empty = m_empty && length == 0;
476        }
477
478        SecByteBlock m_recoverableMessage, m_representative, m_presignature, m_semisignature;
479        Integer m_k, m_s;
480        bool m_empty;
481};
482
483//! \class PK_MessageAccumulatorImpl
484//! \brief Interface for message encoding method for public key signature schemes.
485//! \details \p PK_MessageAccumulatorBase provides interfaces
486//!   for message encoding method.
487template <class HASH_ALGORITHM>
488class PK_MessageAccumulatorImpl : public PK_MessageAccumulatorBase, protected ObjectHolder<HASH_ALGORITHM>
489{
490public:
491        HashTransformation & AccessHash() {return this->m_object;}
492};
493
494//! _
495template <class INTERFACE, class BASE>
496class CRYPTOPP_NO_VTABLE TF_SignatureSchemeBase : public INTERFACE, protected BASE
497{
498public:
499#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
500        virtual ~TF_SignatureSchemeBase() { }
501#endif
502
503        size_t SignatureLength() const
504                {return this->GetTrapdoorFunctionBounds().MaxPreimage().ByteCount();}
505        size_t MaxRecoverableLength() const
506                {return this->GetMessageEncodingInterface().MaxRecoverableLength(MessageRepresentativeBitLength(), GetHashIdentifier().second, GetDigestSize());}
507        size_t MaxRecoverableLengthFromSignatureLength(size_t signatureLength) const
508                {CRYPTOPP_UNUSED(signatureLength); return this->MaxRecoverableLength();}
509
510        bool IsProbabilistic() const
511                {return this->GetTrapdoorFunctionInterface().IsRandomized() || this->GetMessageEncodingInterface().IsProbabilistic();}
512        bool AllowNonrecoverablePart() const
513                {return this->GetMessageEncodingInterface().AllowNonrecoverablePart();}
514        bool RecoverablePartFirst() const
515                {return this->GetMessageEncodingInterface().RecoverablePartFirst();}
516
517protected:
518        size_t MessageRepresentativeLength() const {return BitsToBytes(MessageRepresentativeBitLength());}
519        // Coverity finding on potential overflow/underflow.
520        size_t MessageRepresentativeBitLength() const {return SaturatingSubtract(this->GetTrapdoorFunctionBounds().ImageBound().BitCount(),1U);}
521        virtual HashIdentifier GetHashIdentifier() const =0;
522        virtual size_t GetDigestSize() const =0;
523};
524
525//! _
526class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_SignerBase : public TF_SignatureSchemeBase<PK_Signer, TF_Base<RandomizedTrapdoorFunctionInverse, PK_SignatureMessageEncodingMethod> >
527{
528public:
529#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
530        virtual ~TF_SignerBase() { }
531#endif
532
533        void InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, size_t recoverableMessageLength) const;
534        size_t SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart=true) const;
535};
536
537//! _
538class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_VerifierBase : public TF_SignatureSchemeBase<PK_Verifier, TF_Base<TrapdoorFunction, PK_SignatureMessageEncodingMethod> >
539{
540public:
541#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
542        virtual ~TF_VerifierBase() { }
543#endif
544
545        void InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, size_t signatureLength) const;
546        bool VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const;
547        DecodingResult RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &recoveryAccumulator) const;
548};
549
550// ********************************************************
551
552//! _
553template <class T1, class T2, class T3>
554struct TF_CryptoSchemeOptions
555{
556        typedef T1 AlgorithmInfo;
557        typedef T2 Keys;
558        typedef typename Keys::PrivateKey PrivateKey;
559        typedef typename Keys::PublicKey PublicKey;
560        typedef T3 MessageEncodingMethod;
561};
562
563//! _
564template <class T1, class T2, class T3, class T4>
565struct TF_SignatureSchemeOptions : public TF_CryptoSchemeOptions<T1, T2, T3>
566{
567        typedef T4 HashFunction;
568};
569
570//! _
571template <class BASE, class SCHEME_OPTIONS, class KEY_CLASS>
572class CRYPTOPP_NO_VTABLE TF_ObjectImplBase : public AlgorithmImpl<BASE, typename SCHEME_OPTIONS::AlgorithmInfo>
573{
574public:
575        typedef SCHEME_OPTIONS SchemeOptions;
576        typedef KEY_CLASS KeyClass;
577
578#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
579        virtual ~TF_ObjectImplBase() { }
580#endif
581
582        PublicKey & AccessPublicKey() {return AccessKey();}
583        const PublicKey & GetPublicKey() const {return GetKey();}
584
585        PrivateKey & AccessPrivateKey() {return AccessKey();}
586        const PrivateKey & GetPrivateKey() const {return GetKey();}
587
588        virtual const KeyClass & GetKey() const =0;
589        virtual KeyClass & AccessKey() =0;
590
591        const KeyClass & GetTrapdoorFunction() const {return GetKey();}
592
593        PK_MessageAccumulator * NewSignatureAccumulator(RandomNumberGenerator &rng) const
594        {
595                CRYPTOPP_UNUSED(rng);
596                return new PK_MessageAccumulatorImpl<CPP_TYPENAME SCHEME_OPTIONS::HashFunction>;
597        }
598        PK_MessageAccumulator * NewVerificationAccumulator() const
599        {
600                return new PK_MessageAccumulatorImpl<CPP_TYPENAME SCHEME_OPTIONS::HashFunction>;
601        }
602
603protected:
604        const typename BASE::MessageEncodingInterface & GetMessageEncodingInterface() const
605                {return Singleton<CPP_TYPENAME SCHEME_OPTIONS::MessageEncodingMethod>().Ref();}
606        const TrapdoorFunctionBounds & GetTrapdoorFunctionBounds() const
607                {return GetKey();}
608        const typename BASE::TrapdoorFunctionInterface & GetTrapdoorFunctionInterface() const
609                {return GetKey();}
610
611        // for signature scheme
612        HashIdentifier GetHashIdentifier() const
613        {
614        typedef CPP_TYPENAME SchemeOptions::MessageEncodingMethod::HashIdentifierLookup::template HashIdentifierLookup2<CPP_TYPENAME SchemeOptions::HashFunction> L;
615        return L::Lookup();
616        }
617        size_t GetDigestSize() const
618        {
619                typedef CPP_TYPENAME SchemeOptions::HashFunction H;
620                return H::DIGESTSIZE;
621        }
622};
623
624//! _
625template <class BASE, class SCHEME_OPTIONS, class KEY>
626class TF_ObjectImplExtRef : public TF_ObjectImplBase<BASE, SCHEME_OPTIONS, KEY>
627{
628public:
629#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
630        virtual ~TF_ObjectImplExtRef() { }
631#endif
632
633        TF_ObjectImplExtRef(const KEY *pKey = NULL) : m_pKey(pKey) {}
634        void SetKeyPtr(const KEY *pKey) {m_pKey = pKey;}
635
636        const KEY & GetKey() const {return *m_pKey;}
637        KEY & AccessKey() {throw NotImplemented("TF_ObjectImplExtRef: cannot modify refererenced key");}
638
639private:
640        const KEY * m_pKey;
641};
642
643//! _
644template <class BASE, class SCHEME_OPTIONS, class KEY_CLASS>
645class CRYPTOPP_NO_VTABLE TF_ObjectImpl : public TF_ObjectImplBase<BASE, SCHEME_OPTIONS, KEY_CLASS>
646{
647public:
648        typedef KEY_CLASS KeyClass;
649
650#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
651        virtual ~TF_ObjectImpl() { }
652#endif
653
654        const KeyClass & GetKey() const {return m_trapdoorFunction;}
655        KeyClass & AccessKey() {return m_trapdoorFunction;}
656
657private:
658        KeyClass m_trapdoorFunction;
659};
660
661//! _
662template <class SCHEME_OPTIONS>
663class TF_DecryptorImpl : public TF_ObjectImpl<TF_DecryptorBase, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PrivateKey>
664{
665};
666
667//! _
668template <class SCHEME_OPTIONS>
669class TF_EncryptorImpl : public TF_ObjectImpl<TF_EncryptorBase, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PublicKey>
670{
671};
672
673//! _
674template <class SCHEME_OPTIONS>
675class TF_SignerImpl : public TF_ObjectImpl<TF_SignerBase, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PrivateKey>
676{
677};
678
679//! _
680template <class SCHEME_OPTIONS>
681class TF_VerifierImpl : public TF_ObjectImpl<TF_VerifierBase, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PublicKey>
682{
683};
684
685// ********************************************************
686
687//! \class MaskGeneratingFunction
688//! \brief Mask generation function interface
689class CRYPTOPP_NO_VTABLE MaskGeneratingFunction
690{
691public:
692        virtual ~MaskGeneratingFunction() {}
693
694        //! \brief Generate and apply mask
695        //! \param hash HashTransformation derived class
696        //! \param output the destination byte array
697        //! \param outputLength the size fo the the destination byte array
698        //! \param input the message to hash
699        //! \param inputLength the size of the message
700        //! \param mask flag indicating whether to apply the mask
701        virtual void GenerateAndMask(HashTransformation &hash, byte *output, size_t outputLength, const byte *input, size_t inputLength, bool mask = true) const =0;
702};
703
704//! \fn P1363_MGF1KDF2_Common
705//! \brief P1363 mask generation function
706//! \param hash HashTransformation derived class
707//! \param output the destination byte array
708//! \param outputLength the size fo the the destination byte array
709//! \param input the message to hash
710//! \param inputLength the size of the message
711//! \param derivationParams additional derivation parameters
712//! \param derivationParamsLength the size of the additional derivation parameters
713//! \param mask flag indicating whether to apply the mask
714//! \param counterStart starting counter value used in generation function
715CRYPTOPP_DLL void CRYPTOPP_API P1363_MGF1KDF2_Common(HashTransformation &hash, byte *output, size_t outputLength, const byte *input, size_t inputLength, const byte *derivationParams, size_t derivationParamsLength, bool mask, unsigned int counterStart);
716
717//! \class P1363_MGF1
718//! \brief P1363 mask generation function
719class P1363_MGF1 : public MaskGeneratingFunction
720{
721public:
722        CRYPTOPP_CONSTEXPR static const char * CRYPTOPP_API StaticAlgorithmName() {return "MGF1";}
723        void GenerateAndMask(HashTransformation &hash, byte *output, size_t outputLength, const byte *input, size_t inputLength, bool mask = true) const
724        {
725                P1363_MGF1KDF2_Common(hash, output, outputLength, input, inputLength, NULL, 0, mask, 0);
726        }
727};
728
729// ********************************************************
730
731//! \class MaskGeneratingFunction
732//! \brief P1363 key derivation function
733//! \tparam H hash function used in the derivation
734template <class H>
735class P1363_KDF2
736{
737public:
738        static void CRYPTOPP_API DeriveKey(byte *output, size_t outputLength, const byte *input, size_t inputLength, const byte *derivationParams, size_t derivationParamsLength)
739        {
740                H h;
741                P1363_MGF1KDF2_Common(h, output, outputLength, input, inputLength, derivationParams, derivationParamsLength, false, 1);
742        }
743};
744
745// ********************************************************
746
747//! \brief Exception thrown when an invalid group element is encountered
748//! \details Thrown by DecodeElement and AgreeWithStaticPrivateKey
749class DL_BadElement : public InvalidDataFormat
750{
751public:
752        DL_BadElement() : InvalidDataFormat("CryptoPP: invalid group element") {}
753};
754
755//! \brief Interface for Discrete Log (DL) group parameters
756//! \tparam T element in the group
757//! \details The element is usually an Integer, \ref ECP "ECP::Point" or \ref EC2N "EC2N::Point"
758template <class T>
759class CRYPTOPP_NO_VTABLE DL_GroupParameters : public CryptoParameters
760{
761        typedef DL_GroupParameters<T> ThisClass;
762
763public:
764        typedef T Element;
765
766#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
767        virtual ~DL_GroupParameters() { }
768#endif
769
770        DL_GroupParameters() : m_validationLevel(0) {}
771
772        // CryptoMaterial
773        bool Validate(RandomNumberGenerator &rng, unsigned int level) const
774        {
775                if (!GetBasePrecomputation().IsInitialized())
776                        return false;
777
778                if (m_validationLevel > level)
779                        return true;
780
781                bool pass = ValidateGroup(rng, level);
782                pass = pass && ValidateElement(level, GetSubgroupGenerator(), &GetBasePrecomputation());
783
784                m_validationLevel = pass ? level+1 : 0;
785
786                return pass;
787        }
788
789        bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
790        {
791                return GetValueHelper(this, name, valueType, pValue)
792                        CRYPTOPP_GET_FUNCTION_ENTRY(SubgroupOrder)
793                        CRYPTOPP_GET_FUNCTION_ENTRY(SubgroupGenerator)
794                        ;
795        }
796
797        bool SupportsPrecomputation() const {return true;}
798
799        void Precompute(unsigned int precomputationStorage=16)
800        {
801                AccessBasePrecomputation().Precompute(GetGroupPrecomputation(), GetSubgroupOrder().BitCount(), precomputationStorage);
802        }
803
804        void LoadPrecomputation(BufferedTransformation &storedPrecomputation)
805        {
806                AccessBasePrecomputation().Load(GetGroupPrecomputation(), storedPrecomputation);
807                m_validationLevel = 0;
808        }
809
810        void SavePrecomputation(BufferedTransformation &storedPrecomputation) const
811        {
812                GetBasePrecomputation().Save(GetGroupPrecomputation(), storedPrecomputation);
813        }
814
815        //! \brief Retrieves the subgroup generator
816        //! \return the subgroup generator
817        //! \details The subgroup generator is retrieved from the base precomputation
818        virtual const Element & GetSubgroupGenerator() const {return GetBasePrecomputation().GetBase(GetGroupPrecomputation());}
819
820        //! \brief Set the subgroup generator
821        //! \param base the new subgroup generator
822        //! \details The subgroup generator is set in the base precomputation
823        virtual void SetSubgroupGenerator(const Element &base) {AccessBasePrecomputation().SetBase(GetGroupPrecomputation(), base);}
824
825        //! \brief Retrieves the subgroup generator
826        //! \return the subgroup generator
827        //! \details The subgroup generator is retrieved from the base precomputation.
828        virtual Element ExponentiateBase(const Integer &exponent) const
829        {
830                return GetBasePrecomputation().Exponentiate(GetGroupPrecomputation(), exponent);
831        }
832
833        //! \brief Exponentiates an element
834        //! \param base the base elemenet
835        //! \param exponent the exponent to raise the base
836        //! \return the result of the exponentiation
837        //! \details Internally, ExponentiateElement() calls SimultaneousExponentiate().
838        virtual Element ExponentiateElement(const Element &base, const Integer &exponent) const
839        {
840                Element result;
841                SimultaneousExponentiate(&result, base, &exponent, 1);
842                return result;
843        }
844
845        //! \brief Retrieves the group precomputation
846        //! \return a const reference to the group precomputation
847        virtual const DL_GroupPrecomputation<Element> & GetGroupPrecomputation() const =0;
848
849        //! \brief Retrieves the group precomputation
850        //! \return a const reference to the group precomputation using a fixed base
851        virtual const DL_FixedBasePrecomputation<Element> & GetBasePrecomputation() const =0;
852
853        //! \brief Retrieves the group precomputation
854        //! \return a non-const reference to the group precomputation using a fixed base
855        virtual DL_FixedBasePrecomputation<Element> & AccessBasePrecomputation() =0;
856
857        //! \brief Retrieves the subgroup order
858        //! \return the order of subgroup generated by the base element
859        virtual const Integer & GetSubgroupOrder() const =0;
860
861        //! \brief Retrieves the maximum exponent for the group
862        //! \return the maximum exponent for the group
863        virtual Integer GetMaxExponent() const =0;
864
865        //! \brief Retrieves the order of the group
866        //! \return the order of the group
867        //! \details Either GetGroupOrder() or GetCofactor() must be overriden in a derived class.
868        virtual Integer GetGroupOrder() const {return GetSubgroupOrder()*GetCofactor();}
869
870        //! \brief Retrieves the cofactor
871        //! \return the cofactor
872        //! \details Either GetGroupOrder() or GetCofactor() must be overriden in a derived class.
873        virtual Integer GetCofactor() const {return GetGroupOrder()/GetSubgroupOrder();}
874
875        //! \brief Retrieves the encoded element's size
876        //! \param reversible flag indicating the encoding format
877        //! \return encoded element's size, in bytes
878        //! \details The format of the encoded element varies by the underlyinhg type of the element and the
879        //!   reversible flag. GetEncodedElementSize() must be implemented in a derived class.
880        //! \sa GetEncodedElementSize(), EncodeElement(), DecodeElement()
881        virtual unsigned int GetEncodedElementSize(bool reversible) const =0;
882
883        //! \brief Encodes the element
884        //! \param reversible flag indicating the encoding format
885        //! \param element reference to the element to encode
886        //! \param encoded destination byte array for the encoded element
887        //! \details EncodeElement() must be implemented in a derived class.
888        //! \pre <tt>COUNTOF(encoded) == GetEncodedElementSize()</tt>
889        virtual void EncodeElement(bool reversible, const Element &element, byte *encoded) const =0;
890
891        //! \brief Decodes the element
892        //! \param encoded byte array with the encoded element
893        //! \param checkForGroupMembership flag indicating if the element should be validated
894        //! \return Element after decoding
895        //! \details DecodeElement() must be implemented in a derived class.
896        //! \pre <tt>COUNTOF(encoded) == GetEncodedElementSize()</tt>
897        virtual Element DecodeElement(const byte *encoded, bool checkForGroupMembership) const =0;
898
899        //! \brief Converts an element to an Integer
900        //! \param element the element to convert to an Integer
901        //! \return Element after converting to an Integer
902        //! \details ConvertElementToInteger() must be implemented in a derived class.
903        virtual Integer ConvertElementToInteger(const Element &element) const =0;
904
905        //! \brief Check the group for errors
906        //! \param rng RandomNumberGenerator for objects which use randomized testing
907        //! \param level level of thoroughness
908        //! \return true if the tests succeed, false otherwise
909        //! \details There are four levels of thoroughness:
910        //!   <ul>
911        //!   <li>0 - using this object won't cause a crash or exception
912        //!   <li>1 - this object will probably function, and encrypt, sign, other operations correctly
913        //!   <li>2 - ensure this object will function correctly, and perform reasonable security checks
914        //!   <li>3 - perform reasonable security checks, and do checks that may take a long time
915        //!   </ul>
916        //! \details Level 0 does not require a RandomNumberGenerator. A NullRNG() can be used for level 0.
917        //!   Level 1 may not check for weak keys and such. Levels 2 and 3 are recommended.
918        //! \details ValidateGroup() must be implemented in a derived class.
919        virtual bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const =0;
920
921        //! \brief Check the element for errors
922        //! \param level level of thoroughness
923        //! \param element element to check
924        //! \param precomp optional pointer to DL_FixedBasePrecomputation
925        //! \return true if the tests succeed, false otherwise
926        //! \details There are four levels of thoroughness:
927        //!   <ul>
928        //!   <li>0 - using this object won't cause a crash or exception
929        //!   <li>1 - this object will probably function, and encrypt, sign, other operations correctly
930        //!   <li>2 - ensure this object will function correctly, and perform reasonable security checks
931        //!   <li>3 - perform reasonable security checks, and do checks that may take a long time
932        //!   </ul>
933        //! \details Level 0 performs group membership checks. Level 1 may not check for weak keys and such.
934        //!   Levels 2 and 3 are recommended.
935        //! \details ValidateElement() must be implemented in a derived class.
936        virtual bool ValidateElement(unsigned int level, const Element &element, const DL_FixedBasePrecomputation<Element> *precomp) const =0;
937
938        virtual bool FastSubgroupCheckAvailable() const =0;
939
940        //! \brief Determines if an element is an identity
941        //! \param element element to check
942        //! \return true if the element is an identity, false otherwise
943        //! \details The identity element or or neutral element is a special element in a group that leaves
944        //!   other elements unchanged when combined with it.
945        //! \details IsIdentity() must be implemented in a derived class.
946        virtual bool IsIdentity(const Element &element) const =0;
947
948        //! \brief Exponentiates a base to multiple exponents
949        //! \param results an array of Elements
950        //! \param base the base to raise to the exponents
951        //! \param exponents an array of exponents
952        //! \param exponentsCount the number of exponents in the array
953        //! \details SimultaneousExponentiate() raises the base to each exponent in the exponents array and stores the
954        //!   result at the respective position in the results array.
955        //! \details SimultaneousExponentiate() must be implemented in a derived class.
956        //! \pre <tt>COUNTOF(results) == exponentsCount</tt>
957        //! \pre <tt>COUNTOF(exponents) == exponentsCount</tt>
958        virtual void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const =0;
959
960protected:
961        void ParametersChanged() {m_validationLevel = 0;}
962
963private:
964        mutable unsigned int m_validationLevel;
965};
966
967//! \brief Base implmentation of Discrete Log (DL) group parameters
968//! \tparam GROUP_PRECOMP group precomputation class
969//! \tparam BASE_PRECOMP fixed base precomputation class
970//! \tparam BASE class or type of an element
971template <class GROUP_PRECOMP, class BASE_PRECOMP = DL_FixedBasePrecomputationImpl<CPP_TYPENAME GROUP_PRECOMP::Element>, class BASE = DL_GroupParameters<CPP_TYPENAME GROUP_PRECOMP::Element> >
972class DL_GroupParametersImpl : public BASE
973{
974public:
975        typedef GROUP_PRECOMP GroupPrecomputation;
976        typedef typename GROUP_PRECOMP::Element Element;
977        typedef BASE_PRECOMP BasePrecomputation;
978
979#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
980        virtual ~DL_GroupParametersImpl() { }
981#endif
982
983        //! \brief Retrieves the group precomputation
984        //! \return a const reference to the group precomputation
985        const DL_GroupPrecomputation<Element> & GetGroupPrecomputation() const {return m_groupPrecomputation;}
986
987        //! \brief Retrieves the group precomputation
988        //! \return a const reference to the group precomputation using a fixed base
989        const DL_FixedBasePrecomputation<Element> & GetBasePrecomputation() const {return m_gpc;}
990
991        //! \brief Retrieves the group precomputation
992        //! \return a non-const reference to the group precomputation using a fixed base
993        DL_FixedBasePrecomputation<Element> & AccessBasePrecomputation() {return m_gpc;}
994
995protected:
996        GROUP_PRECOMP m_groupPrecomputation;
997        BASE_PRECOMP m_gpc;
998};
999
1000//! \brief Base class for a Discrete Log (DL) key
1001//! \tparam T class or type of an element
1002//! \details The element is usually an Integer, \ref ECP "ECP::Point" or \ref EC2N "EC2N::Point"
1003template <class T>
1004class CRYPTOPP_NO_VTABLE DL_Key
1005{
1006public:
1007#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
1008        virtual ~DL_Key() { }
1009#endif
1010
1011        //! \brief Retrieves abstract group parameters
1012        //! \return a const reference to the group parameters
1013        virtual const DL_GroupParameters<T> & GetAbstractGroupParameters() const =0;
1014        //! \brief Retrieves abstract group parameters
1015        //! \return a non-const reference to the group parameters
1016        virtual DL_GroupParameters<T> & AccessAbstractGroupParameters() =0;
1017};
1018
1019//! \brief Interface for Discrete Log (DL) public keys
1020template <class T>
1021class CRYPTOPP_NO_VTABLE DL_PublicKey : public DL_Key<T>
1022{
1023        typedef DL_PublicKey<T> ThisClass;
1024
1025public:
1026        typedef T Element;
1027
1028#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
1029        virtual ~DL_PublicKey() { }
1030#endif
1031
1032        bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
1033        {
1034                return GetValueHelper(this, name, valueType, pValue, &this->GetAbstractGroupParameters())
1035                                CRYPTOPP_GET_FUNCTION_ENTRY(PublicElement);
1036        }
1037
1038        void AssignFrom(const NameValuePairs &source);
1039
1040        // non-inherited
1041        virtual const Element & GetPublicElement() const {return GetPublicPrecomputation().GetBase(this->GetAbstractGroupParameters().GetGroupPrecomputation());}
1042        virtual void SetPublicElement(const Element &y) {AccessPublicPrecomputation().SetBase(this->GetAbstractGroupParameters().GetGroupPrecomputation(), y);}
1043        virtual Element ExponentiatePublicElement(const Integer &exponent) const
1044        {
1045                const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
1046                return GetPublicPrecomputation().Exponentiate(params.GetGroupPrecomputation(), exponent);
1047        }
1048        virtual Element CascadeExponentiateBaseAndPublicElement(const Integer &baseExp, const Integer &publicExp) const
1049        {
1050                const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
1051                return params.GetBasePrecomputation().CascadeExponentiate(params.GetGroupPrecomputation(), baseExp, GetPublicPrecomputation(), publicExp);
1052        }
1053
1054        virtual const DL_FixedBasePrecomputation<T> & GetPublicPrecomputation() const =0;
1055        virtual DL_FixedBasePrecomputation<T> & AccessPublicPrecomputation() =0;
1056};
1057
1058//! \brief Interface for Discrete Log (DL) private keys
1059template <class T>
1060class CRYPTOPP_NO_VTABLE DL_PrivateKey : public DL_Key<T>
1061{
1062        typedef DL_PrivateKey<T> ThisClass;
1063
1064public:
1065        typedef T Element;
1066
1067#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
1068        virtual ~DL_PrivateKey() { }
1069#endif
1070
1071        void MakePublicKey(DL_PublicKey<T> &pub) const
1072        {
1073                pub.AccessAbstractGroupParameters().AssignFrom(this->GetAbstractGroupParameters());
1074                pub.SetPublicElement(this->GetAbstractGroupParameters().ExponentiateBase(GetPrivateExponent()));
1075        }
1076
1077        bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
1078        {
1079                return GetValueHelper(this, name, valueType, pValue, &this->GetAbstractGroupParameters())
1080                                CRYPTOPP_GET_FUNCTION_ENTRY(PrivateExponent);
1081        }
1082
1083        void AssignFrom(const NameValuePairs &source)
1084        {
1085                this->AccessAbstractGroupParameters().AssignFrom(source);
1086                AssignFromHelper(this, source)
1087                        CRYPTOPP_SET_FUNCTION_ENTRY(PrivateExponent);
1088        }
1089
1090        virtual const Integer & GetPrivateExponent() const =0;
1091        virtual void SetPrivateExponent(const Integer &x) =0;
1092};
1093
1094template <class T>
1095void DL_PublicKey<T>::AssignFrom(const NameValuePairs &source)
1096{
1097        DL_PrivateKey<T> *pPrivateKey = NULL;
1098        if (source.GetThisPointer(pPrivateKey))
1099                pPrivateKey->MakePublicKey(*this);
1100        else
1101        {
1102                this->AccessAbstractGroupParameters().AssignFrom(source);
1103                AssignFromHelper(this, source)
1104                        CRYPTOPP_SET_FUNCTION_ENTRY(PublicElement);
1105        }
1106}
1107
1108class OID;
1109
1110//! _
1111template <class PK, class GP, class O = OID>
1112class DL_KeyImpl : public PK
1113{
1114public:
1115        typedef GP GroupParameters;
1116
1117#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
1118        virtual ~DL_KeyImpl() { }
1119#endif
1120
1121        O GetAlgorithmID() const {return GetGroupParameters().GetAlgorithmID();}
1122//      void BERDecode(BufferedTransformation &bt)
1123//              {PK::BERDecode(bt);}
1124//      void DEREncode(BufferedTransformation &bt) const
1125//              {PK::DEREncode(bt);}
1126        bool BERDecodeAlgorithmParameters(BufferedTransformation &bt)
1127                {AccessGroupParameters().BERDecode(bt); return true;}
1128        bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const
1129                {GetGroupParameters().DEREncode(bt); return true;}
1130
1131        const GP & GetGroupParameters() const {return m_groupParameters;}
1132        GP & AccessGroupParameters() {return m_groupParameters;}
1133
1134private:
1135        GP m_groupParameters;
1136};
1137
1138class X509PublicKey;
1139class PKCS8PrivateKey;
1140
1141//! _
1142template <class GP>
1143class DL_PrivateKeyImpl : public DL_PrivateKey<CPP_TYPENAME GP::Element>, public DL_KeyImpl<PKCS8PrivateKey, GP>
1144{
1145public:
1146        typedef typename GP::Element Element;
1147
1148#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
1149        virtual ~DL_PrivateKeyImpl() { }
1150#endif
1151
1152        // GeneratableCryptoMaterial
1153        bool Validate(RandomNumberGenerator &rng, unsigned int level) const
1154        {
1155                bool pass = GetAbstractGroupParameters().Validate(rng, level);
1156
1157                const Integer &q = GetAbstractGroupParameters().GetSubgroupOrder();
1158                const Integer &x = GetPrivateExponent();
1159
1160                pass = pass && x.IsPositive() && x < q;
1161                if (level >= 1)
1162                        pass = pass && Integer::Gcd(x, q) == Integer::One();
1163                return pass;
1164        }
1165
1166        bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
1167        {
1168                return GetValueHelper<DL_PrivateKey<Element> >(this, name, valueType, pValue).Assignable();
1169        }
1170
1171        void AssignFrom(const NameValuePairs &source)
1172        {
1173                AssignFromHelper<DL_PrivateKey<Element> >(this, source);
1174        }
1175
1176        void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &params)
1177        {
1178                if (!params.GetThisObject(this->AccessGroupParameters()))
1179                        this->AccessGroupParameters().GenerateRandom(rng, params);
1180//              std::pair<const byte *, int> seed;
1181                Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent());
1182//                      Integer::ANY, Integer::Zero(), Integer::One(),
1183//                      params.GetValue("DeterministicKeyGenerationSeed", seed) ? &seed : NULL);
1184                SetPrivateExponent(x);
1185        }
1186
1187        bool SupportsPrecomputation() const {return true;}
1188
1189        void Precompute(unsigned int precomputationStorage=16)
1190                {AccessAbstractGroupParameters().Precompute(precomputationStorage);}
1191
1192        void LoadPrecomputation(BufferedTransformation &storedPrecomputation)
1193                {AccessAbstractGroupParameters().LoadPrecomputation(storedPrecomputation);}
1194
1195        void SavePrecomputation(BufferedTransformation &storedPrecomputation) const
1196                {GetAbstractGroupParameters().SavePrecomputation(storedPrecomputation);}
1197
1198        // DL_Key
1199        const DL_GroupParameters<Element> & GetAbstractGroupParameters() const {return this->GetGroupParameters();}
1200        DL_GroupParameters<Element> & AccessAbstractGroupParameters() {return this->AccessGroupParameters();}
1201
1202        // DL_PrivateKey
1203        const Integer & GetPrivateExponent() const {return m_x;}
1204        void SetPrivateExponent(const Integer &x) {m_x = x;}
1205
1206        // PKCS8PrivateKey
1207        void BERDecodePrivateKey(BufferedTransformation &bt, bool, size_t)
1208                {m_x.BERDecode(bt);}
1209        void DEREncodePrivateKey(BufferedTransformation &bt) const
1210                {m_x.DEREncode(bt);}
1211
1212private:
1213        Integer m_x;
1214};
1215
1216//! _
1217template <class BASE, class SIGNATURE_SCHEME>
1218class DL_PrivateKey_WithSignaturePairwiseConsistencyTest : public BASE
1219{
1220public:
1221#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
1222        virtual ~DL_PrivateKey_WithSignaturePairwiseConsistencyTest() { }
1223#endif
1224
1225        void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &params)
1226        {
1227                BASE::GenerateRandom(rng, params);
1228
1229                if (FIPS_140_2_ComplianceEnabled())
1230                {
1231                        typename SIGNATURE_SCHEME::Signer signer(*this);
1232                        typename SIGNATURE_SCHEME::Verifier verifier(signer);
1233                        SignaturePairwiseConsistencyTest_FIPS_140_Only(signer, verifier);
1234                }
1235        }
1236};
1237
1238//! _
1239template <class GP>
1240class DL_PublicKeyImpl : public DL_PublicKey<typename GP::Element>, public DL_KeyImpl<X509PublicKey, GP>
1241{
1242public:
1243        typedef typename GP::Element Element;
1244
1245#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
1246        virtual ~DL_PublicKeyImpl() { }
1247#endif
1248
1249        // CryptoMaterial
1250        bool Validate(RandomNumberGenerator &rng, unsigned int level) const
1251        {
1252                bool pass = GetAbstractGroupParameters().Validate(rng, level);
1253                pass = pass && GetAbstractGroupParameters().ValidateElement(level, this->GetPublicElement(), &GetPublicPrecomputation());
1254                return pass;
1255        }
1256
1257        bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
1258        {
1259                return GetValueHelper<DL_PublicKey<Element> >(this, name, valueType, pValue).Assignable();
1260        }
1261
1262        void AssignFrom(const NameValuePairs &source)
1263        {
1264                AssignFromHelper<DL_PublicKey<Element> >(this, source);
1265        }
1266
1267        bool SupportsPrecomputation() const {return true;}
1268
1269        void Precompute(unsigned int precomputationStorage=16)
1270        {
1271                AccessAbstractGroupParameters().Precompute(precomputationStorage);
1272                AccessPublicPrecomputation().Precompute(GetAbstractGroupParameters().GetGroupPrecomputation(), GetAbstractGroupParameters().GetSubgroupOrder().BitCount(), precomputationStorage);
1273        }
1274
1275        void LoadPrecomputation(BufferedTransformation &storedPrecomputation)
1276        {
1277                AccessAbstractGroupParameters().LoadPrecomputation(storedPrecomputation);
1278                AccessPublicPrecomputation().Load(GetAbstractGroupParameters().GetGroupPrecomputation(), storedPrecomputation);
1279        }
1280
1281        void SavePrecomputation(BufferedTransformation &storedPrecomputation) const
1282        {
1283                GetAbstractGroupParameters().SavePrecomputation(storedPrecomputation);
1284                GetPublicPrecomputation().Save(GetAbstractGroupParameters().GetGroupPrecomputation(), storedPrecomputation);
1285        }
1286
1287        // DL_Key
1288        const DL_GroupParameters<Element> & GetAbstractGroupParameters() const {return this->GetGroupParameters();}
1289        DL_GroupParameters<Element> & AccessAbstractGroupParameters() {return this->AccessGroupParameters();}
1290
1291        // DL_PublicKey
1292        const DL_FixedBasePrecomputation<Element> & GetPublicPrecomputation() const {return m_ypc;}
1293        DL_FixedBasePrecomputation<Element> & AccessPublicPrecomputation() {return m_ypc;}
1294
1295        // non-inherited
1296        bool operator==(const DL_PublicKeyImpl<GP> &rhs) const
1297                {return this->GetGroupParameters() == rhs.GetGroupParameters() && this->GetPublicElement() == rhs.GetPublicElement();}
1298
1299private:
1300        typename GP::BasePrecomputation m_ypc;
1301};
1302
1303//! \brief Interface for Elgamal-like signature algorithms
1304template <class T>
1305class CRYPTOPP_NO_VTABLE DL_ElgamalLikeSignatureAlgorithm
1306{
1307public:
1308#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
1309        virtual ~DL_ElgamalLikeSignatureAlgorithm() { }
1310#endif
1311
1312        virtual void Sign(const DL_GroupParameters<T> &params, const Integer &privateKey, const Integer &k, const Integer &e, Integer &r, Integer &s) const =0;
1313        virtual bool Verify(const DL_GroupParameters<T> &params, const DL_PublicKey<T> &publicKey, const Integer &e, const Integer &r, const Integer &s) const =0;
1314        virtual Integer RecoverPresignature(const DL_GroupParameters<T> &params, const DL_PublicKey<T> &publicKey, const Integer &r, const Integer &s) const
1315        {
1316                CRYPTOPP_UNUSED(params); CRYPTOPP_UNUSED(publicKey); CRYPTOPP_UNUSED(r); CRYPTOPP_UNUSED(s);
1317                throw NotImplemented("DL_ElgamalLikeSignatureAlgorithm: this signature scheme does not support message recovery");
1318                MAYBE_RETURN(Integer::Zero());
1319        }
1320        virtual size_t RLen(const DL_GroupParameters<T> &params) const
1321                {return params.GetSubgroupOrder().ByteCount();}
1322        virtual size_t SLen(const DL_GroupParameters<T> &params) const
1323                {return params.GetSubgroupOrder().ByteCount();}
1324};
1325
1326//! \brief Interface for DL key agreement algorithms
1327template <class T>
1328class CRYPTOPP_NO_VTABLE DL_KeyAgreementAlgorithm
1329{
1330public:
1331        typedef T Element;
1332
1333#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
1334        virtual ~DL_KeyAgreementAlgorithm() { }
1335#endif
1336
1337        virtual Element AgreeWithEphemeralPrivateKey(const DL_GroupParameters<Element> &params, const DL_FixedBasePrecomputation<Element> &publicPrecomputation, const Integer &privateExponent) const =0;
1338        virtual Element AgreeWithStaticPrivateKey(const DL_GroupParameters<Element> &params, const Element &publicElement, bool validateOtherPublicKey, const Integer &privateExponent) const =0;
1339};
1340
1341//! \brief Interface for key derivation algorithms used in DL cryptosystems
1342template <class T>
1343class CRYPTOPP_NO_VTABLE DL_KeyDerivationAlgorithm
1344{
1345public:
1346#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
1347        virtual ~DL_KeyDerivationAlgorithm() { }
1348#endif
1349
1350        virtual bool ParameterSupported(const char *name) const
1351                {CRYPTOPP_UNUSED(name); return false;}
1352        virtual void Derive(const DL_GroupParameters<T> &groupParams, byte *derivedKey, size_t derivedLength, const T &agreedElement, const T &ephemeralPublicKey, const NameValuePairs &derivationParams) const =0;
1353};
1354
1355//! \brief Interface for symmetric encryption algorithms used in DL cryptosystems
1356class CRYPTOPP_NO_VTABLE DL_SymmetricEncryptionAlgorithm
1357{
1358public:
1359#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
1360        virtual ~DL_SymmetricEncryptionAlgorithm() { }
1361#endif
1362
1363        virtual bool ParameterSupported(const char *name) const
1364                {CRYPTOPP_UNUSED(name); return false;}
1365        virtual size_t GetSymmetricKeyLength(size_t plaintextLength) const =0;
1366        virtual size_t GetSymmetricCiphertextLength(size_t plaintextLength) const =0;
1367        virtual size_t GetMaxSymmetricPlaintextLength(size_t ciphertextLength) const =0;
1368        virtual void SymmetricEncrypt(RandomNumberGenerator &rng, const byte *key, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs &parameters) const =0;
1369        virtual DecodingResult SymmetricDecrypt(const byte *key, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs &parameters) const =0;
1370};
1371
1372//! \brief Discrete Log (DL) base interface
1373//! \tparam KI public or private key interface
1374template <class KI>
1375class CRYPTOPP_NO_VTABLE DL_Base
1376{
1377protected:
1378        typedef KI KeyInterface;
1379        typedef typename KI::Element Element;
1380
1381#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
1382        virtual ~DL_Base() { }
1383#endif
1384
1385        const DL_GroupParameters<Element> & GetAbstractGroupParameters() const {return GetKeyInterface().GetAbstractGroupParameters();}
1386        DL_GroupParameters<Element> & AccessAbstractGroupParameters() {return AccessKeyInterface().AccessAbstractGroupParameters();}
1387
1388        virtual KeyInterface & AccessKeyInterface() =0;
1389        virtual const KeyInterface & GetKeyInterface() const =0;
1390};
1391
1392//! \brief Discrete Log (DL) signature scheme base implementation
1393//! \tparam INTERFACE PK_Signer or PK_Verifier derived class
1394//! \tparam DL_Base key base used in the scheme
1395//! \details DL_SignatureSchemeBase provides common functions for signers and verifiers.
1396//!   DL_Base<DL_PrivateKey> is used for signers, and DL_Base<DL_PublicKey> is used for verifiers.
1397template <class INTERFACE, class KEY_INTERFACE>
1398class CRYPTOPP_NO_VTABLE DL_SignatureSchemeBase : public INTERFACE, public DL_Base<KEY_INTERFACE>
1399{
1400public:
1401#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
1402        virtual ~DL_SignatureSchemeBase() { }
1403#endif
1404
1405        //! \brief Provides the signature length
1406        //! \returns signature length, in bytes
1407        //! \details SignatureLength returns the size required for <tt>r+s</tt>.
1408        size_t SignatureLength() const
1409        {
1410                return GetSignatureAlgorithm().RLen(this->GetAbstractGroupParameters())
1411                        + GetSignatureAlgorithm().SLen(this->GetAbstractGroupParameters());
1412        }
1413
1414        //! \brief Provides the maximum recoverable length
1415        //! \returns maximum recoverable length, in bytes
1416        size_t MaxRecoverableLength() const
1417                {return GetMessageEncodingInterface().MaxRecoverableLength(0, GetHashIdentifier().second, GetDigestSize());}
1418
1419        //! \brief Provides the maximum recoverable length
1420        //! \param signatureLength the size fo the signature
1421        //! \returns maximum recoverable length based on signature length, in bytes
1422        //! \details this function is not implemented and always returns 0.
1423        size_t MaxRecoverableLengthFromSignatureLength(size_t signatureLength) const
1424                {CRYPTOPP_UNUSED(signatureLength); CRYPTOPP_ASSERT(false); return 0;}   // TODO
1425
1426        //! \brief Determines if the scheme is probabilistic
1427        //! \returns true if the scheme is probabilistic, false otherwise
1428        bool IsProbabilistic() const
1429                {return true;}
1430
1431        //! \brief Determines if the scheme has non-recoverable part
1432        //! \returns true if the message encoding has a non-recoverable part, false otherwise.
1433        bool AllowNonrecoverablePart() const
1434                {return GetMessageEncodingInterface().AllowNonrecoverablePart();}
1435
1436        //! \brief Determines if the scheme allows recoverable part first
1437        //! \returns true if the message encoding allows the recoverable part, false otherwise.
1438        bool RecoverablePartFirst() const
1439                {return GetMessageEncodingInterface().RecoverablePartFirst();}
1440
1441protected:
1442        size_t MessageRepresentativeLength() const {return BitsToBytes(MessageRepresentativeBitLength());}
1443        size_t MessageRepresentativeBitLength() const {return this->GetAbstractGroupParameters().GetSubgroupOrder().BitCount();}
1444
1445        virtual const DL_ElgamalLikeSignatureAlgorithm<CPP_TYPENAME KEY_INTERFACE::Element> & GetSignatureAlgorithm() const =0;
1446        virtual const PK_SignatureMessageEncodingMethod & GetMessageEncodingInterface() const =0;
1447        virtual HashIdentifier GetHashIdentifier() const =0;
1448        virtual size_t GetDigestSize() const =0;
1449};
1450
1451//! \brief Discrete Log (DL) signature scheme signer base implementation
1452//! \tparam T
1453template <class T>
1454class CRYPTOPP_NO_VTABLE DL_SignerBase : public DL_SignatureSchemeBase<PK_Signer, DL_PrivateKey<T> >
1455{
1456public:
1457#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
1458        virtual ~DL_SignerBase() { }
1459#endif
1460
1461        //! \brief Testing interface
1462        //! \param k Integer
1463        //! \param e Integer
1464        //! \param r Integer
1465        //! \param s Integer
1466        void RawSign(const Integer &k, const Integer &e, Integer &r, Integer &s) const
1467        {
1468                const DL_ElgamalLikeSignatureAlgorithm<T> &alg = this->GetSignatureAlgorithm();
1469                const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
1470                const DL_PrivateKey<T> &key = this->GetKeyInterface();
1471
1472                r = params.ConvertElementToInteger(params.ExponentiateBase(k));
1473                alg.Sign(params, key.GetPrivateExponent(), k, e, r, s);
1474        }
1475
1476        void InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, size_t recoverableMessageLength) const
1477        {
1478                PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
1479                ma.m_recoverableMessage.Assign(recoverableMessage, recoverableMessageLength);
1480                this->GetMessageEncodingInterface().ProcessRecoverableMessage(ma.AccessHash(),
1481                        recoverableMessage, recoverableMessageLength,
1482                        ma.m_presignature, ma.m_presignature.size(),
1483                        ma.m_semisignature);
1484        }
1485
1486        size_t SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart) const
1487        {
1488                this->GetMaterial().DoQuickSanityCheck();
1489
1490                PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
1491                const DL_ElgamalLikeSignatureAlgorithm<T> &alg = this->GetSignatureAlgorithm();
1492                const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
1493                const DL_PrivateKey<T> &key = this->GetKeyInterface();
1494
1495                SecByteBlock representative(this->MessageRepresentativeLength());
1496                this->GetMessageEncodingInterface().ComputeMessageRepresentative(
1497                        rng,
1498                        ma.m_recoverableMessage, ma.m_recoverableMessage.size(),
1499                        ma.AccessHash(), this->GetHashIdentifier(), ma.m_empty,
1500                        representative, this->MessageRepresentativeBitLength());
1501                ma.m_empty = true;
1502                Integer e(representative, representative.size());
1503
1504                // hash message digest into random number k to prevent reusing the same k on a different messages
1505                // after virtual machine rollback
1506                if (rng.CanIncorporateEntropy())
1507                        rng.IncorporateEntropy(representative, representative.size());
1508                Integer k(rng, 1, params.GetSubgroupOrder()-1);
1509                Integer r, s;
1510                r = params.ConvertElementToInteger(params.ExponentiateBase(k));
1511                alg.Sign(params, key.GetPrivateExponent(), k, e, r, s);
1512
1513                /*
1514                Integer r, s;
1515                if (this->MaxRecoverableLength() > 0)
1516                        r.Decode(ma.m_semisignature, ma.m_semisignature.size());
1517                else
1518                        r.Decode(ma.m_presignature, ma.m_presignature.size());
1519                alg.Sign(params, key.GetPrivateExponent(), ma.m_k, e, r, s);
1520                */
1521
1522                size_t rLen = alg.RLen(params);
1523                r.Encode(signature, rLen);
1524                s.Encode(signature+rLen, alg.SLen(params));
1525
1526                if (restart)
1527                        RestartMessageAccumulator(rng, ma);
1528
1529                return this->SignatureLength();
1530        }
1531
1532protected:
1533        void RestartMessageAccumulator(RandomNumberGenerator &rng, PK_MessageAccumulatorBase &ma) const
1534        {
1535                // k needs to be generated before hashing for signature schemes with recovery
1536                // but to defend against VM rollbacks we need to generate k after hashing.
1537                // so this code is commented out, since no DL-based signature scheme with recovery
1538                // has been implemented in Crypto++ anyway
1539                /*
1540                const DL_ElgamalLikeSignatureAlgorithm<T> &alg = this->GetSignatureAlgorithm();
1541                const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
1542                ma.m_k.Randomize(rng, 1, params.GetSubgroupOrder()-1);
1543                ma.m_presignature.New(params.GetEncodedElementSize(false));
1544                params.ConvertElementToInteger(params.ExponentiateBase(ma.m_k)).Encode(ma.m_presignature, ma.m_presignature.size());
1545                */
1546                CRYPTOPP_UNUSED(rng); CRYPTOPP_UNUSED(ma);
1547        }
1548};
1549
1550//! _
1551template <class T>
1552class CRYPTOPP_NO_VTABLE DL_VerifierBase : public DL_SignatureSchemeBase<PK_Verifier, DL_PublicKey<T> >
1553{
1554public:
1555#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
1556        virtual ~DL_VerifierBase() { }
1557#endif
1558
1559        void InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, size_t signatureLength) const
1560        {
1561                CRYPTOPP_UNUSED(signature); CRYPTOPP_UNUSED(signatureLength);
1562                PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
1563                const DL_ElgamalLikeSignatureAlgorithm<T> &alg = this->GetSignatureAlgorithm();
1564                const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
1565
1566                size_t rLen = alg.RLen(params);
1567                ma.m_semisignature.Assign(signature, rLen);
1568                ma.m_s.Decode(signature+rLen, alg.SLen(params));
1569
1570                this->GetMessageEncodingInterface().ProcessSemisignature(ma.AccessHash(), ma.m_semisignature, ma.m_semisignature.size());
1571        }
1572
1573        bool VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const
1574        {
1575                this->GetMaterial().DoQuickSanityCheck();
1576
1577                PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
1578                const DL_ElgamalLikeSignatureAlgorithm<T> &alg = this->GetSignatureAlgorithm();
1579                const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
1580                const DL_PublicKey<T> &key = this->GetKeyInterface();
1581
1582                SecByteBlock representative(this->MessageRepresentativeLength());
1583                this->GetMessageEncodingInterface().ComputeMessageRepresentative(NullRNG(), ma.m_recoverableMessage, ma.m_recoverableMessage.size(),
1584                        ma.AccessHash(), this->GetHashIdentifier(), ma.m_empty,
1585                        representative, this->MessageRepresentativeBitLength());
1586                ma.m_empty = true;
1587                Integer e(representative, representative.size());
1588
1589                Integer r(ma.m_semisignature, ma.m_semisignature.size());
1590                return alg.Verify(params, key, e, r, ma.m_s);
1591        }
1592
1593        DecodingResult RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &messageAccumulator) const
1594        {
1595                this->GetMaterial().DoQuickSanityCheck();
1596
1597                PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
1598                const DL_ElgamalLikeSignatureAlgorithm<T> &alg = this->GetSignatureAlgorithm();
1599                const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
1600                const DL_PublicKey<T> &key = this->GetKeyInterface();
1601
1602                SecByteBlock representative(this->MessageRepresentativeLength());
1603                this->GetMessageEncodingInterface().ComputeMessageRepresentative(
1604                        NullRNG(),
1605                        ma.m_recoverableMessage, ma.m_recoverableMessage.size(),
1606                        ma.AccessHash(), this->GetHashIdentifier(), ma.m_empty,
1607                        representative, this->MessageRepresentativeBitLength());
1608                ma.m_empty = true;
1609                Integer e(representative, representative.size());
1610
1611                ma.m_presignature.New(params.GetEncodedElementSize(false));
1612                Integer r(ma.m_semisignature, ma.m_semisignature.size());
1613                alg.RecoverPresignature(params, key, r, ma.m_s).Encode(ma.m_presignature, ma.m_presignature.size());
1614
1615                return this->GetMessageEncodingInterface().RecoverMessageFromSemisignature(
1616                        ma.AccessHash(), this->GetHashIdentifier(),
1617                        ma.m_presignature, ma.m_presignature.size(),
1618                        ma.m_semisignature, ma.m_semisignature.size(),
1619                        recoveredMessage);
1620        }
1621};
1622
1623//! \brief Discrete Log (DL) cryptosystem base implementation
1624//! \tparam PK field element type
1625//! \tparam KI public or private key interface
1626template <class PK, class KI>
1627class CRYPTOPP_NO_VTABLE DL_CryptoSystemBase : public PK, public DL_Base<KI>
1628{
1629public:
1630        typedef typename DL_Base<KI>::Element Element;
1631
1632#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
1633        virtual ~DL_CryptoSystemBase() { }
1634#endif
1635
1636        size_t MaxPlaintextLength(size_t ciphertextLength) const
1637        {
1638                unsigned int minLen = this->GetAbstractGroupParameters().GetEncodedElementSize(true);
1639                return ciphertextLength < minLen ? 0 : GetSymmetricEncryptionAlgorithm().GetMaxSymmetricPlaintextLength(ciphertextLength - minLen);
1640        }
1641
1642        size_t CiphertextLength(size_t plaintextLength) const
1643        {
1644                size_t len = GetSymmetricEncryptionAlgorithm().GetSymmetricCiphertextLength(plaintextLength);
1645                return len == 0 ? 0 : this->GetAbstractGroupParameters().GetEncodedElementSize(true) + len;
1646        }
1647
1648        bool ParameterSupported(const char *name) const
1649                {return GetKeyDerivationAlgorithm().ParameterSupported(name) || GetSymmetricEncryptionAlgorithm().ParameterSupported(name);}
1650
1651protected:
1652        virtual const DL_KeyAgreementAlgorithm<Element> & GetKeyAgreementAlgorithm() const =0;
1653        virtual const DL_KeyDerivationAlgorithm<Element> & GetKeyDerivationAlgorithm() const =0;
1654        virtual const DL_SymmetricEncryptionAlgorithm & GetSymmetricEncryptionAlgorithm() const =0;
1655};
1656
1657//! \brief Discrete Log (DL) decryptor base implementation
1658//! \tparam T field element type
1659template <class T>
1660class CRYPTOPP_NO_VTABLE DL_DecryptorBase : public DL_CryptoSystemBase<PK_Decryptor, DL_PrivateKey<T> >
1661{
1662public:
1663        typedef T Element;
1664
1665#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
1666        virtual ~DL_DecryptorBase() { }
1667#endif
1668
1669        DecodingResult Decrypt(RandomNumberGenerator &rng, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs &parameters = g_nullNameValuePairs) const
1670        {
1671                try
1672                {
1673                        CRYPTOPP_UNUSED(rng);
1674                        const DL_KeyAgreementAlgorithm<T> &agreeAlg = this->GetKeyAgreementAlgorithm();
1675                        const DL_KeyDerivationAlgorithm<T> &derivAlg = this->GetKeyDerivationAlgorithm();
1676                        const DL_SymmetricEncryptionAlgorithm &encAlg = this->GetSymmetricEncryptionAlgorithm();
1677                        const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
1678                        const DL_PrivateKey<T> &key = this->GetKeyInterface();
1679
1680                        Element q = params.DecodeElement(ciphertext, true);
1681                        size_t elementSize = params.GetEncodedElementSize(true);
1682                        ciphertext += elementSize;
1683                        ciphertextLength -= elementSize;
1684
1685                        Element z = agreeAlg.AgreeWithStaticPrivateKey(params, q, true, key.GetPrivateExponent());
1686
1687                        SecByteBlock derivedKey(encAlg.GetSymmetricKeyLength(encAlg.GetMaxSymmetricPlaintextLength(ciphertextLength)));
1688                        derivAlg.Derive(params, derivedKey, derivedKey.size(), z, q, parameters);
1689
1690                        return encAlg.SymmetricDecrypt(derivedKey, ciphertext, ciphertextLength, plaintext, parameters);
1691                }
1692                catch (DL_BadElement &)
1693                {
1694                        return DecodingResult();
1695                }
1696        }
1697};
1698
1699//! \brief Discrete Log (DL) encryptor base implementation
1700//! \tparam T field element type
1701template <class T>
1702class CRYPTOPP_NO_VTABLE DL_EncryptorBase : public DL_CryptoSystemBase<PK_Encryptor, DL_PublicKey<T> >
1703{
1704public:
1705        typedef T Element;
1706
1707#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
1708        virtual ~DL_EncryptorBase() { }
1709#endif
1710
1711        void Encrypt(RandomNumberGenerator &rng, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs &parameters = g_nullNameValuePairs) const
1712        {
1713                const DL_KeyAgreementAlgorithm<T> &agreeAlg = this->GetKeyAgreementAlgorithm();
1714                const DL_KeyDerivationAlgorithm<T> &derivAlg = this->GetKeyDerivationAlgorithm();
1715                const DL_SymmetricEncryptionAlgorithm &encAlg = this->GetSymmetricEncryptionAlgorithm();
1716                const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
1717                const DL_PublicKey<T> &key = this->GetKeyInterface();
1718
1719                Integer x(rng, Integer::One(), params.GetMaxExponent());
1720                Element q = params.ExponentiateBase(x);
1721                params.EncodeElement(true, q, ciphertext);
1722                unsigned int elementSize = params.GetEncodedElementSize(true);
1723                ciphertext += elementSize;
1724
1725                Element z = agreeAlg.AgreeWithEphemeralPrivateKey(params, key.GetPublicPrecomputation(), x);
1726
1727                SecByteBlock derivedKey(encAlg.GetSymmetricKeyLength(plaintextLength));
1728                derivAlg.Derive(params, derivedKey, derivedKey.size(), z, q, parameters);
1729
1730                encAlg.SymmetricEncrypt(rng, derivedKey, plaintext, plaintextLength, ciphertext, parameters);
1731        }
1732};
1733
1734//! \brief Discrete Log (DL) scheme options
1735//! \tparam T1 algorithm information
1736//! \tparam T2 group paramters for the scheme
1737template <class T1, class T2>
1738struct DL_SchemeOptionsBase
1739{
1740        typedef T1 AlgorithmInfo;
1741        typedef T2 GroupParameters;
1742        typedef typename GroupParameters::Element Element;
1743};
1744
1745//! \brief Discrete Log (DL) key options
1746//! \tparam T1 algorithm information
1747//! \tparam T2 keys used in the scheme
1748template <class T1, class T2>
1749struct DL_KeyedSchemeOptions : public DL_SchemeOptionsBase<T1, typename T2::PublicKey::GroupParameters>
1750{
1751        typedef T2 Keys;
1752        typedef typename Keys::PrivateKey PrivateKey;
1753        typedef typename Keys::PublicKey PublicKey;
1754};
1755
1756//! \brief Discrete Log (DL) signature scheme options
1757//! \tparam T1 algorithm information
1758//! \tparam T2 keys used in the scheme
1759//! \tparam T3 signature algorithm
1760//! \tparam T4 message encoding method
1761//! \tparam T5 hash function
1762template <class T1, class T2, class T3, class T4, class T5>
1763struct DL_SignatureSchemeOptions : public DL_KeyedSchemeOptions<T1, T2>
1764{
1765        typedef T3 SignatureAlgorithm;
1766        typedef T4 MessageEncodingMethod;
1767        typedef T5 HashFunction;
1768};
1769
1770//! \brief Discrete Log (DL) crypto scheme options
1771//! \tparam T1 algorithm information
1772//! \tparam T2 keys used in the scheme
1773//! \tparam T3 key agreement algorithm
1774//! \tparam T4 key derivation algorithm
1775//! \tparam T5 symmetric encryption algorithm
1776template <class T1, class T2, class T3, class T4, class T5>
1777struct DL_CryptoSchemeOptions : public DL_KeyedSchemeOptions<T1, T2>
1778{
1779        typedef T3 KeyAgreementAlgorithm;
1780        typedef T4 KeyDerivationAlgorithm;
1781        typedef T5 SymmetricEncryptionAlgorithm;
1782};
1783
1784//! \brief Discrete Log (DL) base object implementation
1785//! \tparam BASE TODO
1786//! \tparam SCHEME_OPTIONS options for the scheme
1787//! \tparam KEY key used in the scheme
1788template <class BASE, class SCHEME_OPTIONS, class KEY>
1789class CRYPTOPP_NO_VTABLE DL_ObjectImplBase : public AlgorithmImpl<BASE, typename SCHEME_OPTIONS::AlgorithmInfo>
1790{
1791public:
1792        typedef SCHEME_OPTIONS SchemeOptions;
1793        typedef typename KEY::Element Element;
1794
1795#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
1796        virtual ~DL_ObjectImplBase() { }
1797#endif
1798
1799        PrivateKey & AccessPrivateKey() {return m_key;}
1800        PublicKey & AccessPublicKey() {return m_key;}
1801
1802        // KeyAccessor
1803        const KEY & GetKey() const {return m_key;}
1804        KEY & AccessKey() {return m_key;}
1805
1806protected:
1807        typename BASE::KeyInterface & AccessKeyInterface() {return m_key;}
1808        const typename BASE::KeyInterface & GetKeyInterface() const {return m_key;}
1809
1810        // for signature scheme
1811        HashIdentifier GetHashIdentifier() const
1812        {
1813                typedef typename SchemeOptions::MessageEncodingMethod::HashIdentifierLookup HashLookup;
1814                return HashLookup::template HashIdentifierLookup2<CPP_TYPENAME SchemeOptions::HashFunction>::Lookup();
1815        }
1816        size_t GetDigestSize() const
1817        {
1818                typedef CPP_TYPENAME SchemeOptions::HashFunction H;
1819                return H::DIGESTSIZE;
1820        }
1821
1822private:
1823        KEY m_key;
1824};
1825
1826//! \brief Discrete Log (DL) object implementation
1827//! \tparam BASE TODO
1828//! \tparam SCHEME_OPTIONS options for the scheme
1829//! \tparam KEY key used in the scheme
1830template <class BASE, class SCHEME_OPTIONS, class KEY>
1831class CRYPTOPP_NO_VTABLE DL_ObjectImpl : public DL_ObjectImplBase<BASE, SCHEME_OPTIONS, KEY>
1832{
1833public:
1834        typedef typename KEY::Element Element;
1835
1836#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
1837        virtual ~DL_ObjectImpl() { }
1838#endif
1839
1840protected:
1841        const DL_ElgamalLikeSignatureAlgorithm<Element> & GetSignatureAlgorithm() const
1842                {return Singleton<CPP_TYPENAME SCHEME_OPTIONS::SignatureAlgorithm>().Ref();}
1843        const DL_KeyAgreementAlgorithm<Element> & GetKeyAgreementAlgorithm() const
1844                {return Singleton<CPP_TYPENAME SCHEME_OPTIONS::KeyAgreementAlgorithm>().Ref();}
1845        const DL_KeyDerivationAlgorithm<Element> & GetKeyDerivationAlgorithm() const
1846                {return Singleton<CPP_TYPENAME SCHEME_OPTIONS::KeyDerivationAlgorithm>().Ref();}
1847        const DL_SymmetricEncryptionAlgorithm & GetSymmetricEncryptionAlgorithm() const
1848                {return Singleton<CPP_TYPENAME SCHEME_OPTIONS::SymmetricEncryptionAlgorithm>().Ref();}
1849        HashIdentifier GetHashIdentifier() const
1850                {return HashIdentifier();}
1851        const PK_SignatureMessageEncodingMethod & GetMessageEncodingInterface() const
1852                {return Singleton<CPP_TYPENAME SCHEME_OPTIONS::MessageEncodingMethod>().Ref();}
1853};
1854
1855//! \brief Discrete Log (DL) signer implementation
1856//! \tparam SCHEME_OPTIONS options for the scheme
1857template <class SCHEME_OPTIONS>
1858class DL_SignerImpl : public DL_ObjectImpl<DL_SignerBase<typename SCHEME_OPTIONS::Element>, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PrivateKey>
1859{
1860public:
1861        PK_MessageAccumulator * NewSignatureAccumulator(RandomNumberGenerator &rng) const
1862        {
1863                member_ptr<PK_MessageAccumulatorBase> p(new PK_MessageAccumulatorImpl<CPP_TYPENAME SCHEME_OPTIONS::HashFunction>);
1864                this->RestartMessageAccumulator(rng, *p);
1865                return p.release();
1866        }
1867};
1868
1869//! \brief Discrete Log (DL) verifier implementation
1870//! \tparam SCHEME_OPTIONS options for the scheme
1871template <class SCHEME_OPTIONS>
1872class DL_VerifierImpl : public DL_ObjectImpl<DL_VerifierBase<typename SCHEME_OPTIONS::Element>, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PublicKey>
1873{
1874public:
1875        PK_MessageAccumulator * NewVerificationAccumulator() const
1876        {
1877                return new PK_MessageAccumulatorImpl<CPP_TYPENAME SCHEME_OPTIONS::HashFunction>;
1878        }
1879};
1880
1881//! \brief Discrete Log (DL) encryptor implementation
1882//! \tparam SCHEME_OPTIONS options for the scheme
1883template <class SCHEME_OPTIONS>
1884class DL_EncryptorImpl : public DL_ObjectImpl<DL_EncryptorBase<typename SCHEME_OPTIONS::Element>, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PublicKey>
1885{
1886};
1887
1888//! \brief Discrete Log (DL) decryptor implementation
1889//! \tparam SCHEME_OPTIONS options for the scheme
1890template <class SCHEME_OPTIONS>
1891class DL_DecryptorImpl : public DL_ObjectImpl<DL_DecryptorBase<typename SCHEME_OPTIONS::Element>, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PrivateKey>
1892{
1893};
1894
1895// ********************************************************
1896
1897//! \brief Discrete Log (DL) simple key agreement base implementation
1898//! \tparam T class or type
1899template <class T>
1900class CRYPTOPP_NO_VTABLE DL_SimpleKeyAgreementDomainBase : public SimpleKeyAgreementDomain
1901{
1902public:
1903        typedef T Element;
1904
1905#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
1906        virtual ~DL_SimpleKeyAgreementDomainBase() { }
1907#endif
1908
1909        CryptoParameters & AccessCryptoParameters() {return AccessAbstractGroupParameters();}
1910        unsigned int AgreedValueLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(false);}
1911        unsigned int PrivateKeyLength() const {return GetAbstractGroupParameters().GetSubgroupOrder().ByteCount();}
1912        unsigned int PublicKeyLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(true);}
1913
1914        void GeneratePrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
1915        {
1916                Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent());
1917                x.Encode(privateKey, PrivateKeyLength());
1918        }
1919
1920        void GeneratePublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
1921        {
1922                CRYPTOPP_UNUSED(rng);
1923                const DL_GroupParameters<T> &params = GetAbstractGroupParameters();
1924                Integer x(privateKey, PrivateKeyLength());
1925                Element y = params.ExponentiateBase(x);
1926                params.EncodeElement(true, y, publicKey);
1927        }
1928
1929        bool Agree(byte *agreedValue, const byte *privateKey, const byte *otherPublicKey, bool validateOtherPublicKey=true) const
1930        {
1931                try
1932                {
1933                        const DL_GroupParameters<T> &params = GetAbstractGroupParameters();
1934                        Integer x(privateKey, PrivateKeyLength());
1935                        Element w = params.DecodeElement(otherPublicKey, validateOtherPublicKey);
1936
1937                        Element z = GetKeyAgreementAlgorithm().AgreeWithStaticPrivateKey(
1938                                GetAbstractGroupParameters(), w, validateOtherPublicKey, x);
1939                        params.EncodeElement(false, z, agreedValue);
1940                }
1941                catch (DL_BadElement &)
1942                {
1943                        return false;
1944                }
1945                return true;
1946        }
1947
1948        //! \brief Retrieves a reference to the group generator
1949        //! \returns const reference to the group generator
1950        const Element &GetGenerator() const {return GetAbstractGroupParameters().GetSubgroupGenerator();}
1951
1952protected:
1953        virtual const DL_KeyAgreementAlgorithm<Element> & GetKeyAgreementAlgorithm() const =0;
1954        virtual DL_GroupParameters<Element> & AccessAbstractGroupParameters() =0;
1955        const DL_GroupParameters<Element> & GetAbstractGroupParameters() const {return const_cast<DL_SimpleKeyAgreementDomainBase<Element> *>(this)->AccessAbstractGroupParameters();}
1956};
1957
1958//! \brief Methods for avoiding "Small-Subgroup" attacks on Diffie-Hellman Key Agreement
1959//! \details Additional methods exist and include public key validation and choice of prime p.
1960//! \sa <A HREF="http://tools.ietf.org/html/rfc2785">Methods for Avoiding the "Small-Subgroup" Attacks on the
1961//!   Diffie-Hellman Key Agreement Method for S/MIME</A>
1962enum CofactorMultiplicationOption {
1963        //! \brief No cofactor multiplication applied
1964        NO_COFACTOR_MULTIPLICTION,
1965        //! \brief Cofactor multiplication compatible with ordinary Diffie-Hellman
1966        //! \details Modifies the computation of ZZ by including j (the cofactor) in the computations and is
1967        //!   compatible with ordinary Diffie-Hellman.
1968        COMPATIBLE_COFACTOR_MULTIPLICTION,
1969        //! \brief Cofactor multiplication incompatible with ordinary Diffie-Hellman
1970        //! \details Modifies the computation of ZZ by including j (the cofactor) in the computations but is
1971        //!   not compatible with ordinary Diffie-Hellman.
1972        INCOMPATIBLE_COFACTOR_MULTIPLICTION};
1973
1974typedef EnumToType<CofactorMultiplicationOption, NO_COFACTOR_MULTIPLICTION> NoCofactorMultiplication;
1975typedef EnumToType<CofactorMultiplicationOption, COMPATIBLE_COFACTOR_MULTIPLICTION> CompatibleCofactorMultiplication;
1976typedef EnumToType<CofactorMultiplicationOption, INCOMPATIBLE_COFACTOR_MULTIPLICTION> IncompatibleCofactorMultiplication;
1977
1978//! \details Diffie-Hellman key agreement algorithm
1979template <class ELEMENT, class COFACTOR_OPTION>
1980class DL_KeyAgreementAlgorithm_DH : public DL_KeyAgreementAlgorithm<ELEMENT>
1981{
1982public:
1983        typedef ELEMENT Element;
1984
1985#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
1986        virtual ~DL_KeyAgreementAlgorithm_DH() {}
1987#endif
1988
1989        CRYPTOPP_CONSTEXPR static const char * CRYPTOPP_API StaticAlgorithmName()
1990                {return COFACTOR_OPTION::ToEnum() == INCOMPATIBLE_COFACTOR_MULTIPLICTION ? "DHC" : "DH";}
1991
1992        Element AgreeWithEphemeralPrivateKey(const DL_GroupParameters<Element> &params, const DL_FixedBasePrecomputation<Element> &publicPrecomputation, const Integer &privateExponent) const
1993        {
1994                return publicPrecomputation.Exponentiate(params.GetGroupPrecomputation(),
1995                        COFACTOR_OPTION::ToEnum() == INCOMPATIBLE_COFACTOR_MULTIPLICTION ? privateExponent*params.GetCofactor() : privateExponent);
1996        }
1997
1998        Element AgreeWithStaticPrivateKey(const DL_GroupParameters<Element> &params, const Element &publicElement, bool validateOtherPublicKey, const Integer &privateExponent) const
1999        {
2000                if (COFACTOR_OPTION::ToEnum() == COMPATIBLE_COFACTOR_MULTIPLICTION)
2001                {
2002                        const Integer &k = params.GetCofactor();
2003                        return params.ExponentiateElement(publicElement,
2004                                ModularArithmetic(params.GetSubgroupOrder()).Divide(privateExponent, k)*k);
2005                }
2006                else if (COFACTOR_OPTION::ToEnum() == INCOMPATIBLE_COFACTOR_MULTIPLICTION)
2007                        return params.ExponentiateElement(publicElement, privateExponent*params.GetCofactor());
2008                else
2009                {
2010                        CRYPTOPP_ASSERT(COFACTOR_OPTION::ToEnum() == NO_COFACTOR_MULTIPLICTION);
2011
2012                        if (!validateOtherPublicKey)
2013                                return params.ExponentiateElement(publicElement, privateExponent);
2014
2015                        if (params.FastSubgroupCheckAvailable())
2016                        {
2017                                if (!params.ValidateElement(2, publicElement, NULL))
2018                                        throw DL_BadElement();
2019                                return params.ExponentiateElement(publicElement, privateExponent);
2020                        }
2021                        else
2022                        {
2023                                const Integer e[2] = {params.GetSubgroupOrder(), privateExponent};
2024                                Element r[2];
2025                                params.SimultaneousExponentiate(r, publicElement, e, 2);
2026                                if (!params.IsIdentity(r[0]))
2027                                        throw DL_BadElement();
2028                                return r[1];
2029                        }
2030                }
2031        }
2032};
2033
2034// ********************************************************
2035
2036//! \brief Template implementing constructors for public key algorithm classes
2037template <class BASE>
2038class CRYPTOPP_NO_VTABLE PK_FinalTemplate : public BASE
2039{
2040public:
2041        PK_FinalTemplate() {}
2042
2043        PK_FinalTemplate(const CryptoMaterial &key)
2044                {this->AccessKey().AssignFrom(key);}
2045
2046        PK_FinalTemplate(BufferedTransformation &bt)
2047                {this->AccessKey().BERDecode(bt);}
2048
2049        PK_FinalTemplate(const AsymmetricAlgorithm &algorithm)
2050                {this->AccessKey().AssignFrom(algorithm.GetMaterial());}
2051
2052        PK_FinalTemplate(const Integer &v1)
2053                {this->AccessKey().Initialize(v1);}
2054
2055#if (defined(_MSC_VER) && _MSC_VER < 1300)
2056
2057        template <class T1, class T2>
2058        PK_FinalTemplate(T1 &v1, T2 &v2)
2059                {this->AccessKey().Initialize(v1, v2);}
2060
2061        template <class T1, class T2, class T3>
2062        PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3)
2063                {this->AccessKey().Initialize(v1, v2, v3);}
2064
2065        template <class T1, class T2, class T3, class T4>
2066        PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4)
2067                {this->AccessKey().Initialize(v1, v2, v3, v4);}
2068
2069        template <class T1, class T2, class T3, class T4, class T5>
2070        PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5)
2071                {this->AccessKey().Initialize(v1, v2, v3, v4, v5);}
2072
2073        template <class T1, class T2, class T3, class T4, class T5, class T6>
2074        PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5, T6 &v6)
2075                {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6);}
2076
2077        template <class T1, class T2, class T3, class T4, class T5, class T6, class T7>
2078        PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5, T6 &v6, T7 &v7)
2079                {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7);}
2080
2081        template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
2082        PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5, T6 &v6, T7 &v7, T8 &v8)
2083                {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7, v8);}
2084
2085#else
2086
2087        template <class T1, class T2>
2088        PK_FinalTemplate(const T1 &v1, const T2 &v2)
2089                {this->AccessKey().Initialize(v1, v2);}
2090
2091        template <class T1, class T2, class T3>
2092        PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3)
2093                {this->AccessKey().Initialize(v1, v2, v3);}
2094
2095        template <class T1, class T2, class T3, class T4>
2096        PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4)
2097                {this->AccessKey().Initialize(v1, v2, v3, v4);}
2098
2099        template <class T1, class T2, class T3, class T4, class T5>
2100        PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5)
2101                {this->AccessKey().Initialize(v1, v2, v3, v4, v5);}
2102
2103        template <class T1, class T2, class T3, class T4, class T5, class T6>
2104        PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6)
2105                {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6);}
2106
2107        template <class T1, class T2, class T3, class T4, class T5, class T6, class T7>
2108        PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7)
2109                {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7);}
2110
2111        template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
2112        PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7, const T8 &v8)
2113                {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7, v8);}
2114
2115        template <class T1, class T2>
2116        PK_FinalTemplate(T1 &v1, const T2 &v2)
2117                {this->AccessKey().Initialize(v1, v2);}
2118
2119        template <class T1, class T2, class T3>
2120        PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3)
2121                {this->AccessKey().Initialize(v1, v2, v3);}
2122
2123        template <class T1, class T2, class T3, class T4>
2124        PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4)
2125                {this->AccessKey().Initialize(v1, v2, v3, v4);}
2126
2127        template <class T1, class T2, class T3, class T4, class T5>
2128        PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5)
2129                {this->AccessKey().Initialize(v1, v2, v3, v4, v5);}
2130
2131        template <class T1, class T2, class T3, class T4, class T5, class T6>
2132        PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6)
2133                {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6);}
2134
2135        template <class T1, class T2, class T3, class T4, class T5, class T6, class T7>
2136        PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7)
2137                {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7);}
2138
2139        template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
2140        PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7, const T8 &v8)
2141                {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7, v8);}
2142
2143#endif
2144};
2145
2146//! \brief Base class for public key encryption standard classes.
2147//! \details These classes are used to select from variants of algorithms.
2148//!   Not all standards apply to all algorithms.
2149struct EncryptionStandard {};
2150
2151//! \brief Base class for public key signature standard classes.
2152//! \details These classes are used to select from variants of algorithms.
2153//!   Not all standards apply to all algorithms.
2154struct SignatureStandard {};
2155
2156//! \brief Trapdoor Function (TF) encryption scheme
2157//! \tparam STANDARD standard
2158//! \tparam KEYS keys used in the encryption scheme
2159//! \tparam ALG_INFO algorithm information
2160template <class STANDARD, class KEYS, class ALG_INFO>
2161class TF_ES;
2162
2163template <class STANDARD, class KEYS, class ALG_INFO = TF_ES<STANDARD, KEYS, int> >
2164class TF_ES : public KEYS
2165{
2166        typedef typename STANDARD::EncryptionMessageEncodingMethod MessageEncodingMethod;
2167
2168public:
2169        //! see EncryptionStandard for a list of standards
2170        typedef STANDARD Standard;
2171        typedef TF_CryptoSchemeOptions<ALG_INFO, KEYS, MessageEncodingMethod> SchemeOptions;
2172
2173        static std::string CRYPTOPP_API StaticAlgorithmName() {return std::string(KEYS::StaticAlgorithmName()) + "/" + MessageEncodingMethod::StaticAlgorithmName();}
2174
2175        //! implements PK_Decryptor interface
2176        typedef PK_FinalTemplate<TF_DecryptorImpl<SchemeOptions> > Decryptor;
2177        //! implements PK_Encryptor interface
2178        typedef PK_FinalTemplate<TF_EncryptorImpl<SchemeOptions> > Encryptor;
2179};
2180
2181//! \class TF_SS
2182//! \brief Trapdoor Function (TF) Signature Scheme
2183//! \tparam STANDARD standard
2184//! \tparam H hash function
2185//! \tparam KEYS keys used in the signature scheme
2186//! \tparam ALG_INFO algorithm information
2187template <class STANDARD, class H, class KEYS, class ALG_INFO>  // VC60 workaround: doesn't work if KEYS is first parameter
2188class TF_SS;
2189
2190template <class STANDARD, class H, class KEYS, class ALG_INFO = TF_SS<STANDARD, H, KEYS, int> > // VC60 workaround: doesn't work if KEYS is first parameter
2191class TF_SS : public KEYS
2192{
2193public:
2194        //! see SignatureStandard for a list of standards
2195        typedef STANDARD Standard;
2196        typedef typename Standard::SignatureMessageEncodingMethod MessageEncodingMethod;
2197        typedef TF_SignatureSchemeOptions<ALG_INFO, KEYS, MessageEncodingMethod, H> SchemeOptions;
2198
2199        static std::string CRYPTOPP_API StaticAlgorithmName() {return std::string(KEYS::StaticAlgorithmName()) + "/" + MessageEncodingMethod::StaticAlgorithmName() + "(" + H::StaticAlgorithmName() + ")";}
2200
2201        //! implements PK_Signer interface
2202        typedef PK_FinalTemplate<TF_SignerImpl<SchemeOptions> > Signer;
2203        //! implements PK_Verifier interface
2204        typedef PK_FinalTemplate<TF_VerifierImpl<SchemeOptions> > Verifier;
2205};
2206
2207//! \class DL_SS
2208//! \brief Discrete Log (DL) signature scheme
2209//! \tparam KEYS keys used in the signature scheme
2210//! \tparam SA signature algorithm
2211//! \tparam MEM message encoding method
2212//! \tparam H hash function
2213//! \tparam ALG_INFO algorithm information
2214template <class KEYS, class SA, class MEM, class H, class ALG_INFO>
2215class DL_SS;
2216
2217template <class KEYS, class SA, class MEM, class H, class ALG_INFO = DL_SS<KEYS, SA, MEM, H, int> >
2218class DL_SS : public KEYS
2219{
2220        typedef DL_SignatureSchemeOptions<ALG_INFO, KEYS, SA, MEM, H> SchemeOptions;
2221
2222public:
2223        static std::string StaticAlgorithmName() {return SA::StaticAlgorithmName() + std::string("/EMSA1(") + H::StaticAlgorithmName() + ")";}
2224
2225        //! implements PK_Signer interface
2226        typedef PK_FinalTemplate<DL_SignerImpl<SchemeOptions> > Signer;
2227        //! implements PK_Verifier interface
2228        typedef PK_FinalTemplate<DL_VerifierImpl<SchemeOptions> > Verifier;
2229};
2230
2231//! \brief Discrete Log (DL) encryption scheme
2232//! \tparam KEYS keys used in the encryption scheme
2233//! \tparam AA key agreement algorithm
2234//! \tparam DA key derivation algorithm
2235//! \tparam EA encryption algorithm
2236//! \tparam ALG_INFO algorithm information
2237template <class KEYS, class AA, class DA, class EA, class ALG_INFO>
2238class DL_ES : public KEYS
2239{
2240        typedef DL_CryptoSchemeOptions<ALG_INFO, KEYS, AA, DA, EA> SchemeOptions;
2241
2242public:
2243        //! implements PK_Decryptor interface
2244        typedef PK_FinalTemplate<DL_DecryptorImpl<SchemeOptions> > Decryptor;
2245        //! implements PK_Encryptor interface
2246        typedef PK_FinalTemplate<DL_EncryptorImpl<SchemeOptions> > Encryptor;
2247};
2248
2249NAMESPACE_END
2250
2251#if CRYPTOPP_MSC_VERSION
2252# pragma warning(pop)
2253#endif
2254
2255#endif
Note: See TracBrowser for help on using the repository browser.