Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:55:07

0001 // pubkey.h - originally written and placed in the public domain by Wei Dai

0002 
0003 /// \file pubkey.h

0004 /// \brief This file contains helper classes/functions for implementing public key algorithms.

0005 /// \details The class hierarchies in this header file tend to look like this:

0006 ///

0007 /// <pre>

0008 ///                   x1

0009 ///                  +--+

0010 ///                  |  |

0011 ///                 y1  z1

0012 ///                  |  |

0013 ///             x2<y1>  x2<z1>

0014 ///                  |  |

0015 ///                 y2  z2

0016 ///                  |  |

0017 ///             x3<y2>  x3<z2>

0018 ///                  |  |

0019 ///                 y3  z3

0020 /// </pre>

0021 ///

0022 /// <ul>

0023 ///  <li>x1, y1, z1 are abstract interface classes defined in cryptlib.h

0024 ///  <li>x2, y2, z2 are implementations of the interfaces using "abstract policies", which

0025 ///      are pure virtual functions that should return interfaces to interchangeable algorithms.

0026 ///      These classes have Base suffixes.

0027 ///  <li>x3, y3, z3 hold actual algorithms and implement those virtual functions.

0028 ///      These classes have Impl suffixes.

0029 /// </ul>

0030 ///

0031 /// \details The TF_ prefix means an implementation using trapdoor functions on integers.

0032 /// \details The DL_ prefix means an implementation using group operations in groups where discrete log is hard.

0033 
0034 #ifndef CRYPTOPP_PUBKEY_H
0035 #define CRYPTOPP_PUBKEY_H
0036 
0037 #include "config.h"
0038 
0039 #if CRYPTOPP_MSC_VERSION
0040 # pragma warning(push)
0041 # pragma warning(disable: 4702)
0042 #endif
0043 
0044 #include "cryptlib.h"
0045 #include "integer.h"
0046 #include "algebra.h"
0047 #include "modarith.h"
0048 #include "filters.h"
0049 #include "eprecomp.h"
0050 #include "fips140.h"
0051 #include "argnames.h"
0052 #include "smartptr.h"
0053 #include "stdcpp.h"
0054 
0055 #if defined(__SUNPRO_CC)
0056 # define MAYBE_RETURN(x) return x
0057 #else
0058 # define MAYBE_RETURN(x) CRYPTOPP_UNUSED(x)
0059 #endif
0060 
0061 NAMESPACE_BEGIN(CryptoPP)
0062 
0063 /// \brief Provides range for plaintext and ciphertext lengths

0064 /// \details A trapdoor function is a function that is easy to compute in one direction,

0065 ///  but difficult to compute in the opposite direction without special knowledge.

0066 ///  The special knowledge is usually the private key.

0067 /// \details Trapdoor functions only handle messages of a limited length or size.

0068 ///  MaxPreimage is the plaintext's maximum length, and MaxImage is the

0069 ///  ciphertext's maximum length.

0070 /// \sa TrapdoorFunctionBounds(), RandomizedTrapdoorFunction(), TrapdoorFunction(),

0071 ///  RandomizedTrapdoorFunctionInverse() and TrapdoorFunctionInverse()

0072 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TrapdoorFunctionBounds
0073 {
0074 public:
0075     virtual ~TrapdoorFunctionBounds() {}
0076 
0077     /// \brief Returns the maximum size of a message before the trapdoor function is applied

0078     /// \return the maximum size of a message before the trapdoor function is applied

0079     /// \details Derived classes must implement PreimageBound().

0080     virtual Integer PreimageBound() const =0;
0081     /// \brief Returns the maximum size of a representation after the trapdoor function is applied

0082     /// \return the maximum size of a representation after the trapdoor function is applied

0083     /// \details Derived classes must implement ImageBound().

0084     virtual Integer ImageBound() const =0;
0085     /// \brief Returns the maximum size of a message before the trapdoor function is applied bound to a public key

0086     /// \return the maximum size of a message before the trapdoor function is applied bound to a public key

0087     /// \details The default implementation returns <tt>PreimageBound() - 1</tt>.

0088     virtual Integer MaxPreimage() const {return --PreimageBound();}
0089     /// \brief Returns the maximum size of a representation after the trapdoor function is applied bound to a public key

0090     /// \return the maximum size of a representation after the trapdoor function is applied bound to a public key

0091     /// \details The default implementation returns <tt>ImageBound() - 1</tt>.

0092     virtual Integer MaxImage() const {return --ImageBound();}
0093 };
0094 
0095 /// \brief Applies the trapdoor function, using random data if required

0096 /// \details ApplyFunction() is the foundation for encrypting a message under a public key.

0097 ///  Derived classes will override it at some point.

0098 /// \sa TrapdoorFunctionBounds(), RandomizedTrapdoorFunction(), TrapdoorFunction(),

0099 ///  RandomizedTrapdoorFunctionInverse() and TrapdoorFunctionInverse()

0100 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE RandomizedTrapdoorFunction : public TrapdoorFunctionBounds
0101 {
0102 public:
0103     virtual ~RandomizedTrapdoorFunction() {}
0104 
0105     /// \brief Applies the trapdoor function, using random data if required

0106     /// \param rng a RandomNumberGenerator derived class

0107     /// \param x the message on which the encryption function is applied

0108     /// \return the message x encrypted under the public key

0109     /// \details ApplyRandomizedFunction is a generalization of encryption under a public key

0110     ///  cryptosystem. The RandomNumberGenerator may (or may not) be required.

0111     ///  Derived classes must implement it.

0112     virtual Integer ApplyRandomizedFunction(RandomNumberGenerator &rng, const Integer &x) const =0;
0113 
0114     /// \brief Determines if the encryption algorithm is randomized

0115     /// \return true if the encryption algorithm is randomized, false otherwise

0116     /// \details If IsRandomized() returns false, then NullRNG() can be used.

0117     virtual bool IsRandomized() const {return true;}
0118 };
0119 
0120 /// \brief Applies the trapdoor function

0121 /// \details ApplyFunction() is the foundation for encrypting a message under a public key.

0122 ///  Derived classes will override it at some point.

0123 /// \sa TrapdoorFunctionBounds(), RandomizedTrapdoorFunction(), TrapdoorFunction(),

0124 ///  RandomizedTrapdoorFunctionInverse() and TrapdoorFunctionInverse()

0125 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TrapdoorFunction : public RandomizedTrapdoorFunction
0126 {
0127 public:
0128     virtual ~TrapdoorFunction() {}
0129 
0130     /// \brief Applies the trapdoor function

0131     /// \param rng a RandomNumberGenerator derived class

0132     /// \param x the message on which the encryption function is applied

0133     /// \details ApplyRandomizedFunction is a generalization of encryption under a public key

0134     ///  cryptosystem. The RandomNumberGenerator may (or may not) be required.

0135     /// \details Internally, ApplyRandomizedFunction() calls ApplyFunction()

0136     ///  without the RandomNumberGenerator.

0137     Integer ApplyRandomizedFunction(RandomNumberGenerator &rng, const Integer &x) const
0138         {CRYPTOPP_UNUSED(rng); return ApplyFunction(x);}
0139     bool IsRandomized() const {return false;}
0140 
0141     /// \brief Applies the trapdoor

0142     /// \param x the message on which the encryption function is applied

0143     /// \return the message x encrypted under the public key

0144     /// \details ApplyFunction is a generalization of encryption under a public key

0145     ///  cryptosystem. Derived classes must implement it.

0146     virtual Integer ApplyFunction(const Integer &x) const =0;
0147 };
0148 
0149 /// \brief Applies the inverse of the trapdoor function, using random data if required

0150 /// \details CalculateInverse() is the foundation for decrypting a message under a private key

0151 ///  in a public key cryptosystem. Derived classes will override it at some point.

0152 /// \sa TrapdoorFunctionBounds(), RandomizedTrapdoorFunction(), TrapdoorFunction(),

0153 ///  RandomizedTrapdoorFunctionInverse() and TrapdoorFunctionInverse()

0154 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE RandomizedTrapdoorFunctionInverse
0155 {
0156 public:
0157     virtual ~RandomizedTrapdoorFunctionInverse() {}
0158 
0159     /// \brief Applies the inverse of the trapdoor function, using random data if required

0160     /// \param rng a RandomNumberGenerator derived class

0161     /// \param x the message on which the decryption function is applied

0162     /// \return the message x decrypted under the private key

0163     /// \details CalculateRandomizedInverse is a generalization of decryption using the private key

0164     ///  The RandomNumberGenerator may (or may not) be required. Derived classes must implement it.

0165     virtual Integer CalculateRandomizedInverse(RandomNumberGenerator &rng, const Integer &x) const =0;
0166 
0167     /// \brief Determines if the decryption algorithm is randomized

0168     /// \return true if the decryption algorithm is randomized, false otherwise

0169     /// \details If IsRandomized() returns false, then NullRNG() can be used.

0170     virtual bool IsRandomized() const {return true;}
0171 };
0172 
0173 /// \brief Applies the inverse of the trapdoor function

0174 /// \details CalculateInverse() is the foundation for decrypting a message under a private key

0175 ///  in a public key cryptosystem. Derived classes will override it at some point.

0176 /// \sa TrapdoorFunctionBounds(), RandomizedTrapdoorFunction(), TrapdoorFunction(),

0177 ///  RandomizedTrapdoorFunctionInverse() and TrapdoorFunctionInverse()

0178 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TrapdoorFunctionInverse : public RandomizedTrapdoorFunctionInverse
0179 {
0180 public:
0181     virtual ~TrapdoorFunctionInverse() {}
0182 
0183     /// \brief Applies the inverse of the trapdoor function

0184     /// \param rng a RandomNumberGenerator derived class

0185     /// \param x the message on which the decryption function is applied

0186     /// \return the message x decrypted under the private key

0187     /// \details CalculateRandomizedInverse is a generalization of decryption using the private key

0188     /// \details Internally, CalculateRandomizedInverse() calls CalculateInverse()

0189     ///  without the RandomNumberGenerator.

0190     Integer CalculateRandomizedInverse(RandomNumberGenerator &rng, const Integer &x) const
0191         {return CalculateInverse(rng, x);}
0192 
0193     /// \brief Determines if the decryption algorithm is randomized

0194     /// \return true if the decryption algorithm is randomized, false otherwise

0195     /// \details If IsRandomized() returns false, then NullRNG() can be used.

0196     bool IsRandomized() const {return false;}
0197 
0198     /// \brief Calculates the inverse of an element

0199     /// \param rng a RandomNumberGenerator derived class

0200     /// \param x the element

0201     /// \return the inverse of the element in the group

0202     virtual Integer CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const =0;
0203 };
0204 
0205 // ********************************************************

0206 
0207 /// \brief Message encoding method for public key encryption

0208 class CRYPTOPP_NO_VTABLE PK_EncryptionMessageEncodingMethod
0209 {
0210 public:
0211     virtual ~PK_EncryptionMessageEncodingMethod() {}
0212 
0213     virtual bool ParameterSupported(const char *name) const
0214         {CRYPTOPP_UNUSED(name); return false;}
0215 
0216     /// max size of unpadded message in bytes, given max size of padded message in bits (1 less than size of modulus)

0217     virtual size_t MaxUnpaddedLength(size_t paddedLength) const =0;
0218 
0219     virtual void Pad(RandomNumberGenerator &rng, const byte *raw, size_t inputLength, byte *padded, size_t paddedBitLength, const NameValuePairs &parameters) const =0;
0220 
0221     virtual DecodingResult Unpad(const byte *padded, size_t paddedBitLength, byte *raw, const NameValuePairs &parameters) const =0;
0222 };
0223 
0224 // ********************************************************

0225 
0226 /// \brief The base for trapdoor based cryptosystems

0227 /// \tparam TFI trapdoor function interface derived class

0228 /// \tparam MEI message encoding interface derived class

0229 template <class TFI, class MEI>
0230 class CRYPTOPP_NO_VTABLE TF_Base
0231 {
0232 protected:
0233     virtual ~TF_Base() {}
0234 
0235     virtual const TrapdoorFunctionBounds & GetTrapdoorFunctionBounds() const =0;
0236 
0237     typedef TFI TrapdoorFunctionInterface;
0238     virtual const TrapdoorFunctionInterface & GetTrapdoorFunctionInterface() const =0;
0239 
0240     typedef MEI MessageEncodingInterface;
0241     virtual const MessageEncodingInterface & GetMessageEncodingInterface() const =0;
0242 };
0243 
0244 // ********************************************************

0245 
0246 /// \brief Public key trapdoor function default implementation

0247 /// \tparam BASE public key cryptosystem with a fixed length

0248 template <class BASE>
0249 class CRYPTOPP_NO_VTABLE PK_FixedLengthCryptoSystemImpl : public BASE
0250 {
0251 public:
0252     virtual ~PK_FixedLengthCryptoSystemImpl() {}
0253 
0254     size_t MaxPlaintextLength(size_t ciphertextLength) const
0255         {return ciphertextLength == FixedCiphertextLength() ? FixedMaxPlaintextLength() : 0;}
0256     size_t CiphertextLength(size_t plaintextLength) const
0257         {return plaintextLength <= FixedMaxPlaintextLength() ? FixedCiphertextLength() : 0;}
0258 
0259     virtual size_t FixedMaxPlaintextLength() const =0;
0260     virtual size_t FixedCiphertextLength() const =0;
0261 };
0262 
0263 /// \brief Trapdoor function cryptosystem base class

0264 /// \tparam INTFACE public key cryptosystem base interface

0265 /// \tparam BASE public key cryptosystem implementation base

0266 template <class INTFACE, class BASE>
0267 class CRYPTOPP_NO_VTABLE TF_CryptoSystemBase : public PK_FixedLengthCryptoSystemImpl<INTFACE>, protected BASE
0268 {
0269 public:
0270     virtual ~TF_CryptoSystemBase() {}
0271 
0272     bool ParameterSupported(const char *name) const {return this->GetMessageEncodingInterface().ParameterSupported(name);}
0273     size_t FixedMaxPlaintextLength() const {return this->GetMessageEncodingInterface().MaxUnpaddedLength(PaddedBlockBitLength());}
0274     size_t FixedCiphertextLength() const {return this->GetTrapdoorFunctionBounds().MaxImage().ByteCount();}
0275 
0276 protected:
0277     size_t PaddedBlockByteLength() const {return BitsToBytes(PaddedBlockBitLength());}
0278     // Coverity finding on potential overflow/underflow.

0279     size_t PaddedBlockBitLength() const {return SaturatingSubtract(this->GetTrapdoorFunctionBounds().PreimageBound().BitCount(),1U);}
0280 };
0281 
0282 /// \brief Trapdoor function cryptosystems decryption base class

0283 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_DecryptorBase : public TF_CryptoSystemBase<PK_Decryptor, TF_Base<TrapdoorFunctionInverse, PK_EncryptionMessageEncodingMethod> >
0284 {
0285 public:
0286     virtual ~TF_DecryptorBase() {}
0287 
0288     DecodingResult Decrypt(RandomNumberGenerator &rng, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs &parameters = g_nullNameValuePairs) const;
0289 };
0290 
0291 /// \brief Trapdoor function cryptosystems encryption base class

0292 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_EncryptorBase : public TF_CryptoSystemBase<PK_Encryptor, TF_Base<RandomizedTrapdoorFunction, PK_EncryptionMessageEncodingMethod> >
0293 {
0294 public:
0295     virtual ~TF_EncryptorBase() {}
0296 
0297     void Encrypt(RandomNumberGenerator &rng, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs &parameters = g_nullNameValuePairs) const;
0298 };
0299 
0300 // ********************************************************

0301 
0302 // Typedef change due to Clang, http://github.com/weidai11/cryptopp/issues/300

0303 typedef std::pair<const byte *, unsigned int> HashIdentifier;
0304 
0305 /// \brief Interface for message encoding method for public key signature schemes.

0306 /// \details PK_SignatureMessageEncodingMethod provides interfaces for message

0307 ///  encoding method for public key signature schemes. The methods support both

0308 ///  trapdoor functions (<tt>TF_*</tt>) and discrete logarithm (<tt>DL_*</tt>)

0309 ///  based schemes.

0310 class CRYPTOPP_NO_VTABLE PK_SignatureMessageEncodingMethod
0311 {
0312 public:
0313     virtual ~PK_SignatureMessageEncodingMethod() {}
0314 
0315     virtual size_t MinRepresentativeBitLength(size_t hashIdentifierLength, size_t digestLength) const
0316         {CRYPTOPP_UNUSED(hashIdentifierLength); CRYPTOPP_UNUSED(digestLength); return 0;}
0317     virtual size_t MaxRecoverableLength(size_t representativeBitLength, size_t hashIdentifierLength, size_t digestLength) const
0318         {CRYPTOPP_UNUSED(representativeBitLength); CRYPTOPP_UNUSED(representativeBitLength); CRYPTOPP_UNUSED(hashIdentifierLength); CRYPTOPP_UNUSED(digestLength); return 0;}
0319 
0320     /// \brief Determines whether an encoding method requires a random number generator

0321     /// \return true if the encoding method requires a RandomNumberGenerator()

0322     /// \details if IsProbabilistic() returns false, then NullRNG() can be passed to functions that take

0323     ///  RandomNumberGenerator().

0324     /// \sa Bellare and Rogaway<a href="http://grouper.ieee.org/groups/1363/P1363a/contributions/pss-submission.pdf">PSS:

0325     ///  Provably Secure Encoding Method for Digital Signatures</a>

0326     bool IsProbabilistic() const
0327         {return true;}
0328     bool AllowNonrecoverablePart() const
0329         {throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");}
0330     virtual bool RecoverablePartFirst() const
0331         {throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");}
0332 
0333     // for verification, DL

0334     virtual void ProcessSemisignature(HashTransformation &hash, const byte *semisignature, size_t semisignatureLength) const
0335         {CRYPTOPP_UNUSED(hash); CRYPTOPP_UNUSED(semisignature); CRYPTOPP_UNUSED(semisignatureLength);}
0336 
0337     // for signature

0338     virtual void ProcessRecoverableMessage(HashTransformation &hash,
0339         const byte *recoverableMessage, size_t recoverableMessageLength,
0340         const byte *presignature, size_t presignatureLength,
0341         SecByteBlock &semisignature) const
0342     {
0343         CRYPTOPP_UNUSED(hash);CRYPTOPP_UNUSED(recoverableMessage); CRYPTOPP_UNUSED(recoverableMessageLength);
0344         CRYPTOPP_UNUSED(presignature); CRYPTOPP_UNUSED(presignatureLength); CRYPTOPP_UNUSED(semisignature);
0345         if (RecoverablePartFirst())
0346             CRYPTOPP_ASSERT(!"ProcessRecoverableMessage() not implemented");
0347     }
0348 
0349     virtual void ComputeMessageRepresentative(RandomNumberGenerator &rng,
0350         const byte *recoverableMessage, size_t recoverableMessageLength,
0351         HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
0352         byte *representative, size_t representativeBitLength) const =0;
0353 
0354     virtual bool VerifyMessageRepresentative(
0355         HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
0356         byte *representative, size_t representativeBitLength) const =0;
0357 
0358     virtual DecodingResult RecoverMessageFromRepresentative(    // for TF

0359         HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
0360         byte *representative, size_t representativeBitLength,
0361         byte *recoveredMessage) const
0362         {CRYPTOPP_UNUSED(hash);CRYPTOPP_UNUSED(hashIdentifier); CRYPTOPP_UNUSED(messageEmpty);
0363         CRYPTOPP_UNUSED(representative); CRYPTOPP_UNUSED(representativeBitLength); CRYPTOPP_UNUSED(recoveredMessage);
0364         throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");}
0365 
0366     virtual DecodingResult RecoverMessageFromSemisignature(     // for DL

0367         HashTransformation &hash, HashIdentifier hashIdentifier,
0368         const byte *presignature, size_t presignatureLength,
0369         const byte *semisignature, size_t semisignatureLength,
0370         byte *recoveredMessage) const
0371         {CRYPTOPP_UNUSED(hash);CRYPTOPP_UNUSED(hashIdentifier); CRYPTOPP_UNUSED(presignature); CRYPTOPP_UNUSED(presignatureLength);
0372         CRYPTOPP_UNUSED(semisignature); CRYPTOPP_UNUSED(semisignatureLength); CRYPTOPP_UNUSED(recoveredMessage);
0373         throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");}
0374 
0375     // VC60 workaround

0376     struct HashIdentifierLookup
0377     {
0378         template <class H> struct HashIdentifierLookup2
0379         {
0380             static HashIdentifier CRYPTOPP_API Lookup()
0381             {
0382                 return HashIdentifier(static_cast<const byte *>(NULLPTR), 0);
0383             }
0384         };
0385     };
0386 };
0387 
0388 /// \brief Interface for message encoding method for public key signature schemes.

0389 /// \details PK_DeterministicSignatureMessageEncodingMethod provides interfaces

0390 ///  for message encoding method for public key signature schemes.

0391 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_DeterministicSignatureMessageEncodingMethod : public PK_SignatureMessageEncodingMethod
0392 {
0393 public:
0394     bool VerifyMessageRepresentative(
0395         HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
0396         byte *representative, size_t representativeBitLength) const;
0397 };
0398 
0399 /// \brief Interface for message encoding method for public key signature schemes.

0400 /// \details PK_RecoverableSignatureMessageEncodingMethod provides interfaces

0401 ///  for message encoding method for public key signature schemes.

0402 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_RecoverableSignatureMessageEncodingMethod : public PK_SignatureMessageEncodingMethod
0403 {
0404 public:
0405     bool VerifyMessageRepresentative(
0406         HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
0407         byte *representative, size_t representativeBitLength) const;
0408 };
0409 
0410 /// \brief Interface for message encoding method for public key signature schemes.

0411 /// \details DL_SignatureMessageEncodingMethod_DSA provides interfaces

0412 ///  for message encoding method for DSA.

0413 class CRYPTOPP_DLL DL_SignatureMessageEncodingMethod_DSA : public PK_DeterministicSignatureMessageEncodingMethod
0414 {
0415 public:
0416     void ComputeMessageRepresentative(RandomNumberGenerator &rng,
0417         const byte *recoverableMessage, size_t recoverableMessageLength,
0418         HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
0419         byte *representative, size_t representativeBitLength) const;
0420 };
0421 
0422 /// \brief Interface for message encoding method for public key signature schemes.

0423 /// \details DL_SignatureMessageEncodingMethod_NR provides interfaces

0424 ///  for message encoding method for Nyberg-Rueppel.

0425 class CRYPTOPP_DLL DL_SignatureMessageEncodingMethod_NR : public PK_DeterministicSignatureMessageEncodingMethod
0426 {
0427 public:
0428     void ComputeMessageRepresentative(RandomNumberGenerator &rng,
0429         const byte *recoverableMessage, size_t recoverableMessageLength,
0430         HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
0431         byte *representative, size_t representativeBitLength) const;
0432 };
0433 
0434 #if 0
0435 /// \brief Interface for message encoding method for public key signature schemes.

0436 /// \details DL_SignatureMessageEncodingMethod_SM2 provides interfaces

0437 ///  for message encoding method for SM2.

0438 class CRYPTOPP_DLL DL_SignatureMessageEncodingMethod_SM2 : public PK_DeterministicSignatureMessageEncodingMethod
0439 {
0440 public:
0441     void ComputeMessageRepresentative(RandomNumberGenerator &rng,
0442         const byte *recoverableMessage, size_t recoverableMessageLength,
0443         HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
0444         byte *representative, size_t representativeBitLength) const;
0445 };
0446 #endif
0447 
0448 /// \brief Interface for message encoding method for public key signature schemes.

0449 /// \details PK_MessageAccumulatorBase provides interfaces

0450 ///  for message encoding method.

0451 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_MessageAccumulatorBase : public PK_MessageAccumulator
0452 {
0453 public:
0454     PK_MessageAccumulatorBase() : m_empty(true) {}
0455 
0456     virtual HashTransformation & AccessHash() =0;
0457 
0458     void Update(const byte *input, size_t length)
0459     {
0460         AccessHash().Update(input, length);
0461         m_empty = m_empty && length == 0;
0462     }
0463 
0464     SecByteBlock m_recoverableMessage, m_representative, m_presignature, m_semisignature;
0465     Integer m_k, m_s;
0466     bool m_empty;
0467 };
0468 
0469 /// \brief Interface for message encoding method for public key signature schemes.

0470 /// \details PK_MessageAccumulatorBase provides interfaces

0471 ///  for message encoding method.

0472 template <class HASH_ALGORITHM>
0473 class PK_MessageAccumulatorImpl : public PK_MessageAccumulatorBase, protected ObjectHolder<HASH_ALGORITHM>
0474 {
0475 public:
0476     HashTransformation & AccessHash() {return this->m_object;}
0477 };
0478 
0479 /// \brief Trapdoor Function (TF) Signature Scheme base class

0480 /// \tparam INTFACE interface

0481 /// \tparam BASE base class

0482 template <class INTFACE, class BASE>
0483 class CRYPTOPP_NO_VTABLE TF_SignatureSchemeBase : public INTFACE, protected BASE
0484 {
0485 public:
0486     virtual ~TF_SignatureSchemeBase() {}
0487 
0488     size_t SignatureLength() const
0489         {return this->GetTrapdoorFunctionBounds().MaxPreimage().ByteCount();}
0490     size_t MaxRecoverableLength() const
0491         {return this->GetMessageEncodingInterface().MaxRecoverableLength(MessageRepresentativeBitLength(), GetHashIdentifier().second, GetDigestSize());}
0492     size_t MaxRecoverableLengthFromSignatureLength(size_t signatureLength) const
0493         {CRYPTOPP_UNUSED(signatureLength); return this->MaxRecoverableLength();}
0494 
0495     bool IsProbabilistic() const
0496         {return this->GetTrapdoorFunctionInterface().IsRandomized() || this->GetMessageEncodingInterface().IsProbabilistic();}
0497     bool AllowNonrecoverablePart() const
0498         {return this->GetMessageEncodingInterface().AllowNonrecoverablePart();}
0499     bool RecoverablePartFirst() const
0500         {return this->GetMessageEncodingInterface().RecoverablePartFirst();}
0501 
0502 protected:
0503     size_t MessageRepresentativeLength() const {return BitsToBytes(MessageRepresentativeBitLength());}
0504     // Coverity finding on potential overflow/underflow.

0505     size_t MessageRepresentativeBitLength() const {return SaturatingSubtract(this->GetTrapdoorFunctionBounds().ImageBound().BitCount(),1U);}
0506     virtual HashIdentifier GetHashIdentifier() const =0;
0507     virtual size_t GetDigestSize() const =0;
0508 };
0509 
0510 /// \brief Trapdoor Function (TF) Signer base class

0511 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_SignerBase : public TF_SignatureSchemeBase<PK_Signer, TF_Base<RandomizedTrapdoorFunctionInverse, PK_SignatureMessageEncodingMethod> >
0512 {
0513 public:
0514     virtual ~TF_SignerBase() {}
0515 
0516     void InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, size_t recoverableMessageLength) const;
0517     size_t SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart=true) const;
0518 };
0519 
0520 /// \brief Trapdoor Function (TF) Verifier base class

0521 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_VerifierBase : public TF_SignatureSchemeBase<PK_Verifier, TF_Base<TrapdoorFunction, PK_SignatureMessageEncodingMethod> >
0522 {
0523 public:
0524     virtual ~TF_VerifierBase() {}
0525 
0526     void InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, size_t signatureLength) const;
0527     bool VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const;
0528     DecodingResult RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &recoveryAccumulator) const;
0529 };
0530 
0531 // ********************************************************

0532 
0533 /// \brief Trapdoor Function (TF) scheme options

0534 /// \tparam T1 algorithm info class

0535 /// \tparam T2 keys class with public and private key

0536 /// \tparam T3 message encoding class

0537 template <class T1, class T2, class T3>
0538 struct TF_CryptoSchemeOptions
0539 {
0540     typedef T1 AlgorithmInfo;
0541     typedef T2 Keys;
0542     typedef typename Keys::PrivateKey PrivateKey;
0543     typedef typename Keys::PublicKey PublicKey;
0544     typedef T3 MessageEncodingMethod;
0545 };
0546 
0547 /// \brief Trapdoor Function (TF) signature scheme options

0548 /// \tparam T1 algorithm info class

0549 /// \tparam T2 keys class with public and private key

0550 /// \tparam T3 message encoding class

0551 /// \tparam T4 HashTransformation class

0552 template <class T1, class T2, class T3, class T4>
0553 struct TF_SignatureSchemeOptions : public TF_CryptoSchemeOptions<T1, T2, T3>
0554 {
0555     typedef T4 HashFunction;
0556 };
0557 
0558 /// \brief Trapdoor Function (TF) base implementation

0559 /// \tparam BASE base class

0560 /// \tparam SCHEME_OPTIONS scheme options class

0561 /// \tparam KEY_CLASS key class

0562 template <class BASE, class SCHEME_OPTIONS, class KEY_CLASS>
0563 class CRYPTOPP_NO_VTABLE TF_ObjectImplBase : public AlgorithmImpl<BASE, typename SCHEME_OPTIONS::AlgorithmInfo>
0564 {
0565 public:
0566     typedef SCHEME_OPTIONS SchemeOptions;
0567     typedef KEY_CLASS KeyClass;
0568 
0569     virtual ~TF_ObjectImplBase() {}
0570 
0571     PublicKey & AccessPublicKey() {return AccessKey();}
0572     const PublicKey & GetPublicKey() const {return GetKey();}
0573 
0574     PrivateKey & AccessPrivateKey() {return AccessKey();}
0575     const PrivateKey & GetPrivateKey() const {return GetKey();}
0576 
0577     virtual const KeyClass & GetKey() const =0;
0578     virtual KeyClass & AccessKey() =0;
0579 
0580     const KeyClass & GetTrapdoorFunction() const {return GetKey();}
0581 
0582     PK_MessageAccumulator * NewSignatureAccumulator(RandomNumberGenerator &rng) const
0583     {
0584         CRYPTOPP_UNUSED(rng);
0585         return new PK_MessageAccumulatorImpl<typename SCHEME_OPTIONS::HashFunction>;
0586     }
0587     PK_MessageAccumulator * NewVerificationAccumulator() const
0588     {
0589         return new PK_MessageAccumulatorImpl<typename SCHEME_OPTIONS::HashFunction>;
0590     }
0591 
0592 protected:
0593     const typename BASE::MessageEncodingInterface & GetMessageEncodingInterface() const
0594         {return Singleton<typename SCHEME_OPTIONS::MessageEncodingMethod>().Ref();}
0595     const TrapdoorFunctionBounds & GetTrapdoorFunctionBounds() const
0596         {return GetKey();}
0597     const typename BASE::TrapdoorFunctionInterface & GetTrapdoorFunctionInterface() const
0598         {return GetKey();}
0599 
0600     // for signature scheme

0601     HashIdentifier GetHashIdentifier() const
0602     {
0603         typedef typename SchemeOptions::MessageEncodingMethod::HashIdentifierLookup::template HashIdentifierLookup2<typename SchemeOptions::HashFunction> L;
0604         return L::Lookup();
0605     }
0606     size_t GetDigestSize() const
0607     {
0608         typedef typename SchemeOptions::HashFunction H;
0609         return H::DIGESTSIZE;
0610     }
0611 };
0612 
0613 /// \brief Trapdoor Function (TF) signature with external reference

0614 /// \tparam BASE base class

0615 /// \tparam SCHEME_OPTIONS scheme options class

0616 /// \tparam KEY key class

0617 /// \details TF_ObjectImplExtRef() holds a pointer to an external key structure

0618 template <class BASE, class SCHEME_OPTIONS, class KEY>
0619 class TF_ObjectImplExtRef : public TF_ObjectImplBase<BASE, SCHEME_OPTIONS, KEY>
0620 {
0621 public:
0622     virtual ~TF_ObjectImplExtRef() {}
0623 
0624     TF_ObjectImplExtRef(const KEY *pKey = NULLPTR) : m_pKey(pKey) {}
0625     void SetKeyPtr(const KEY *pKey) {m_pKey = pKey;}
0626 
0627     const KEY & GetKey() const {return *m_pKey;}
0628     KEY & AccessKey() {throw NotImplemented("TF_ObjectImplExtRef: cannot modify refererenced key");}
0629 
0630 private:
0631     const KEY * m_pKey;
0632 };
0633 
0634 /// \brief Trapdoor Function (TF) signature scheme options

0635 /// \tparam BASE base class

0636 /// \tparam SCHEME_OPTIONS scheme options class

0637 /// \tparam KEY_CLASS key class

0638 /// \details TF_ObjectImpl() holds a reference to a trapdoor function

0639 template <class BASE, class SCHEME_OPTIONS, class KEY_CLASS>
0640 class CRYPTOPP_NO_VTABLE TF_ObjectImpl : public TF_ObjectImplBase<BASE, SCHEME_OPTIONS, KEY_CLASS>
0641 {
0642 public:
0643     typedef KEY_CLASS KeyClass;
0644 
0645     virtual ~TF_ObjectImpl() {}
0646 
0647     const KeyClass & GetKey() const {return m_trapdoorFunction;}
0648     KeyClass & AccessKey() {return m_trapdoorFunction;}
0649 
0650 private:
0651     KeyClass m_trapdoorFunction;
0652 };
0653 
0654 /// \brief Trapdoor Function (TF) decryptor options

0655 /// \tparam SCHEME_OPTIONS scheme options class

0656 template <class SCHEME_OPTIONS>
0657 class TF_DecryptorImpl : public TF_ObjectImpl<TF_DecryptorBase, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PrivateKey>
0658 {
0659 };
0660 
0661 /// \brief Trapdoor Function (TF) encryptor options

0662 /// \tparam SCHEME_OPTIONS scheme options class

0663 template <class SCHEME_OPTIONS>
0664 class TF_EncryptorImpl : public TF_ObjectImpl<TF_EncryptorBase, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PublicKey>
0665 {
0666 };
0667 
0668 /// \brief Trapdoor Function (TF) encryptor options

0669 /// \tparam SCHEME_OPTIONS scheme options class

0670 template <class SCHEME_OPTIONS>
0671 class TF_SignerImpl : public TF_ObjectImpl<TF_SignerBase, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PrivateKey>
0672 {
0673 };
0674 
0675 /// \brief Trapdoor Function (TF) encryptor options

0676 /// \tparam SCHEME_OPTIONS scheme options class

0677 template <class SCHEME_OPTIONS>
0678 class TF_VerifierImpl : public TF_ObjectImpl<TF_VerifierBase, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PublicKey>
0679 {
0680 };
0681 
0682 // ********************************************************

0683 
0684 /// \brief Mask generation function interface

0685 /// \sa P1363_KDF2, P1363_MGF1

0686 /// \since Crypto++ 2.0

0687 class CRYPTOPP_NO_VTABLE MaskGeneratingFunction
0688 {
0689 public:
0690     virtual ~MaskGeneratingFunction() {}
0691 
0692     /// \brief Generate and apply mask

0693     /// \param hash HashTransformation derived class

0694     /// \param output the destination byte array

0695     /// \param outputLength the size of the destination byte array

0696     /// \param input the message to hash

0697     /// \param inputLength the size of the message

0698     /// \param mask flag indicating whether to apply the mask

0699     virtual void GenerateAndMask(HashTransformation &hash, byte *output, size_t outputLength, const byte *input, size_t inputLength, bool mask = true) const =0;
0700 };
0701 
0702 /// \fn P1363_MGF1KDF2_Common

0703 /// \brief P1363 mask generation function

0704 /// \param hash HashTransformation derived class

0705 /// \param output the destination byte array

0706 /// \param outputLength the size of the destination byte array

0707 /// \param input the message to hash

0708 /// \param inputLength the size of the message

0709 /// \param derivationParams additional derivation parameters

0710 /// \param derivationParamsLength the size of the additional derivation parameters

0711 /// \param mask flag indicating whether to apply the mask

0712 /// \param counterStart starting counter value used in generation function

0713 CRYPTOPP_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);
0714 
0715 /// \brief P1363 mask generation function

0716 /// \sa P1363_KDF2, MaskGeneratingFunction

0717 /// \since Crypto++ 2.0

0718 class P1363_MGF1 : public MaskGeneratingFunction
0719 {
0720 public:
0721     /// \brief The algorithm name

0722     /// \return the algorithm name

0723     /// \details StaticAlgorithmName returns the algorithm's name as a static

0724     ///  member function.

0725     CRYPTOPP_STATIC_CONSTEXPR const char* CRYPTOPP_API StaticAlgorithmName() {return "MGF1";}
0726 
0727     /// \brief P1363 mask generation function

0728     /// \param hash HashTransformation derived class

0729     /// \param output the destination byte array

0730     /// \param outputLength the size of the destination byte array

0731     /// \param input the message to hash

0732     /// \param inputLength the size of the message

0733     /// \param mask flag indicating whether to apply the mask

0734     void GenerateAndMask(HashTransformation &hash, byte *output, size_t outputLength, const byte *input, size_t inputLength, bool mask = true) const
0735     {
0736         P1363_MGF1KDF2_Common(hash, output, outputLength, input, inputLength, NULLPTR, 0, mask, 0);
0737     }
0738 };
0739 
0740 // ********************************************************

0741 
0742 /// \brief P1363 key derivation function

0743 /// \tparam H hash function used in the derivation

0744 /// \sa P1363_MGF1, KeyDerivationFunction, <A

0745 ///  HREF="https://www.cryptopp.com/wiki/P1363_KDF2">P1363_KDF2</A>

0746 ///  on the Crypto++ wiki

0747 /// \since Crypto++ 2.0

0748 template <class H>
0749 class P1363_KDF2
0750 {
0751 public:
0752     /// \brief P1363 key derivation function

0753     /// \param output the destination byte array

0754     /// \param outputLength the size of the destination byte array

0755     /// \param input the message to hash

0756     /// \param inputLength the size of the message

0757     /// \param derivationParams additional derivation parameters

0758     /// \param derivationParamsLength the size of the additional derivation parameters

0759     /// \details DeriveKey calls P1363_MGF1KDF2_Common

0760     static void CRYPTOPP_API DeriveKey(byte *output, size_t outputLength, const byte *input, size_t inputLength, const byte *derivationParams, size_t derivationParamsLength)
0761     {
0762         H h;
0763         P1363_MGF1KDF2_Common(h, output, outputLength, input, inputLength, derivationParams, derivationParamsLength, false, 1);
0764     }
0765 };
0766 
0767 // ********************************************************

0768 
0769 /// \brief Exception thrown when an invalid group element is encountered

0770 /// \details Thrown by DecodeElement and AgreeWithStaticPrivateKey

0771 class DL_BadElement : public InvalidDataFormat
0772 {
0773 public:
0774     DL_BadElement() : InvalidDataFormat("CryptoPP: invalid group element") {}
0775 };
0776 
0777 /// \brief Interface for Discrete Log (DL) group parameters

0778 /// \tparam T element in the group

0779 /// \details The element is usually an Integer, \ref ECP "ECP::Point" or \ref EC2N "EC2N::Point"

0780 template <class T>
0781 class CRYPTOPP_NO_VTABLE DL_GroupParameters : public CryptoParameters
0782 {
0783     typedef DL_GroupParameters<T> ThisClass;
0784 
0785 public:
0786     typedef T Element;
0787 
0788     virtual ~DL_GroupParameters() {}
0789 
0790     DL_GroupParameters() : m_validationLevel(0) {}
0791 
0792     // CryptoMaterial

0793     bool Validate(RandomNumberGenerator &rng, unsigned int level) const
0794     {
0795         if (!GetBasePrecomputation().IsInitialized())
0796             return false;
0797 
0798         if (m_validationLevel > level)
0799             return true;
0800 
0801         CRYPTOPP_ASSERT(ValidateGroup(rng, level));
0802         bool pass = ValidateGroup(rng, level);
0803         CRYPTOPP_ASSERT(ValidateElement(level, GetSubgroupGenerator(), &GetBasePrecomputation()));
0804         pass = pass && ValidateElement(level, GetSubgroupGenerator(), &GetBasePrecomputation());
0805 
0806         m_validationLevel = pass ? level+1 : 0;
0807 
0808         return pass;
0809     }
0810 
0811     bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
0812     {
0813         return GetValueHelper(this, name, valueType, pValue)
0814             CRYPTOPP_GET_FUNCTION_ENTRY(SubgroupOrder)
0815             CRYPTOPP_GET_FUNCTION_ENTRY(SubgroupGenerator)
0816             ;
0817     }
0818 
0819     /// \brief Determines whether the object supports precomputation

0820     /// \return true if the object supports precomputation, false otherwise

0821     /// \sa Precompute()

0822     bool SupportsPrecomputation() const {return true;}
0823 
0824     /// \brief Perform precomputation

0825     /// \param precomputationStorage the suggested number of objects for the precompute table

0826     /// \throw NotImplemented

0827     /// \details The exact semantics of Precompute() varies, but it typically means calculate

0828     ///  a table of n objects that can be used later to speed up computation.

0829     /// \details If a derived class does not override Precompute(), then the base class throws

0830     ///  NotImplemented.

0831     /// \sa SupportsPrecomputation(), LoadPrecomputation(), SavePrecomputation()

0832     void Precompute(unsigned int precomputationStorage=16)
0833     {
0834         AccessBasePrecomputation().Precompute(GetGroupPrecomputation(), GetSubgroupOrder().BitCount(), precomputationStorage);
0835     }
0836 
0837     /// \brief Retrieve previously saved precomputation

0838     /// \param storedPrecomputation BufferedTransformation with the saved precomputation

0839     /// \throw NotImplemented

0840     /// \sa SupportsPrecomputation(), Precompute()

0841     void LoadPrecomputation(BufferedTransformation &storedPrecomputation)
0842     {
0843         AccessBasePrecomputation().Load(GetGroupPrecomputation(), storedPrecomputation);
0844         m_validationLevel = 0;
0845     }
0846 
0847     /// \brief Save precomputation for later use

0848     /// \param storedPrecomputation BufferedTransformation to write the precomputation

0849     /// \throw NotImplemented

0850     /// \sa SupportsPrecomputation(), Precompute()

0851     void SavePrecomputation(BufferedTransformation &storedPrecomputation) const
0852     {
0853         GetBasePrecomputation().Save(GetGroupPrecomputation(), storedPrecomputation);
0854     }
0855 
0856     /// \brief Retrieves the subgroup generator

0857     /// \return the subgroup generator

0858     /// \details The subgroup generator is retrieved from the base precomputation

0859     virtual const Element & GetSubgroupGenerator() const {return GetBasePrecomputation().GetBase(GetGroupPrecomputation());}
0860 
0861     /// \brief Sets the subgroup generator

0862     /// \param base the new subgroup generator

0863     /// \details The subgroup generator is set in the base precomputation

0864     virtual void SetSubgroupGenerator(const Element &base) {AccessBasePrecomputation().SetBase(GetGroupPrecomputation(), base);}
0865 
0866     /// \brief Exponentiates the base

0867     /// \return the element after exponentiation

0868     /// \details ExponentiateBase() calls GetBasePrecomputation() and then exponentiates.

0869     virtual Element ExponentiateBase(const Integer &exponent) const
0870     {
0871         return GetBasePrecomputation().Exponentiate(GetGroupPrecomputation(), exponent);
0872     }
0873 
0874     /// \brief Exponentiates an element

0875     /// \param base the base element

0876     /// \param exponent the exponent to raise the base

0877     /// \return the result of the exponentiation

0878     /// \details Internally, ExponentiateElement() calls SimultaneousExponentiate().

0879     virtual Element ExponentiateElement(const Element &base, const Integer &exponent) const
0880     {
0881         Element result;
0882         SimultaneousExponentiate(&result, base, &exponent, 1);
0883         return result;
0884     }
0885 
0886     /// \brief Retrieves the group precomputation

0887     /// \return a const reference to the group precomputation

0888     virtual const DL_GroupPrecomputation<Element> & GetGroupPrecomputation() const =0;
0889 
0890     /// \brief Retrieves the group precomputation

0891     /// \return a const reference to the group precomputation using a fixed base

0892     virtual const DL_FixedBasePrecomputation<Element> & GetBasePrecomputation() const =0;
0893 
0894     /// \brief Retrieves the group precomputation

0895     /// \return a non-const reference to the group precomputation using a fixed base

0896     virtual DL_FixedBasePrecomputation<Element> & AccessBasePrecomputation() =0;
0897 
0898     /// \brief Retrieves the subgroup order

0899     /// \return the order of subgroup generated by the base element

0900     virtual const Integer & GetSubgroupOrder() const =0;
0901 
0902     /// \brief Retrieves the maximum exponent for the group

0903     /// \return the maximum exponent for the group

0904     virtual Integer GetMaxExponent() const =0;
0905 
0906     /// \brief Retrieves the order of the group

0907     /// \return the order of the group

0908     /// \details Either GetGroupOrder() or GetCofactor() must be overridden in a derived class.

0909     virtual Integer GetGroupOrder() const {return GetSubgroupOrder()*GetCofactor();}
0910 
0911     /// \brief Retrieves the cofactor

0912     /// \return the cofactor

0913     /// \details Either GetGroupOrder() or GetCofactor() must be overridden in a derived class.

0914     virtual Integer GetCofactor() const {return GetGroupOrder()/GetSubgroupOrder();}
0915 
0916     /// \brief Retrieves the encoded element's size

0917     /// \param reversible flag indicating the encoding format

0918     /// \return encoded element's size, in bytes

0919     /// \details The format of the encoded element varies by the underlying type of the element and the

0920     ///  reversible flag. GetEncodedElementSize() must be implemented in a derived class.

0921     /// \sa GetEncodedElementSize(), EncodeElement(), DecodeElement()

0922     virtual unsigned int GetEncodedElementSize(bool reversible) const =0;
0923 
0924     /// \brief Encodes the element

0925     /// \param reversible flag indicating the encoding format

0926     /// \param element reference to the element to encode

0927     /// \param encoded destination byte array for the encoded element

0928     /// \details EncodeElement() must be implemented in a derived class.

0929     /// \pre <tt>COUNTOF(encoded) == GetEncodedElementSize()</tt>

0930     virtual void EncodeElement(bool reversible, const Element &element, byte *encoded) const =0;
0931 
0932     /// \brief Decodes the element

0933     /// \param encoded byte array with the encoded element

0934     /// \param checkForGroupMembership flag indicating if the element should be validated

0935     /// \return Element after decoding

0936     /// \details DecodeElement() must be implemented in a derived class.

0937     /// \pre <tt>COUNTOF(encoded) == GetEncodedElementSize()</tt>

0938     virtual Element DecodeElement(const byte *encoded, bool checkForGroupMembership) const =0;
0939 
0940     /// \brief Converts an element to an Integer

0941     /// \param element the element to convert to an Integer

0942     /// \return Element after converting to an Integer

0943     /// \details ConvertElementToInteger() must be implemented in a derived class.

0944     virtual Integer ConvertElementToInteger(const Element &element) const =0;
0945 
0946     /// \brief Check the group for errors

0947     /// \param rng RandomNumberGenerator for objects which use randomized testing

0948     /// \param level level of thoroughness

0949     /// \return true if the tests succeed, false otherwise

0950     /// \details There are four levels of thoroughness:

0951     ///  <ul>

0952     ///  <li>0 - using this object won't cause a crash or exception

0953     ///  <li>1 - this object will probably function, and encrypt, sign, other operations correctly

0954     ///  <li>2 - ensure this object will function correctly, and perform reasonable security checks

0955     ///  <li>3 - perform reasonable security checks, and do checks that may take a long time

0956     ///  </ul>

0957     /// \details Level 0 does not require a RandomNumberGenerator. A NullRNG() can be used for level 0.

0958     ///  Level 1 may not check for weak keys and such. Levels 2 and 3 are recommended.

0959     /// \details ValidateGroup() must be implemented in a derived class.

0960     virtual bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const =0;
0961 
0962     /// \brief Check the element for errors

0963     /// \param level level of thoroughness

0964     /// \param element element to check

0965     /// \param precomp optional pointer to DL_FixedBasePrecomputation

0966     /// \return true if the tests succeed, false otherwise

0967     /// \details There are four levels of thoroughness:

0968     ///  <ul>

0969     ///  <li>0 - using this object won't cause a crash or exception

0970     ///  <li>1 - this object will probably function, and encrypt, sign, other operations correctly

0971     ///  <li>2 - ensure this object will function correctly, and perform reasonable security checks

0972     ///  <li>3 - perform reasonable security checks, and do checks that may take a long time

0973     ///  </ul>

0974     /// \details Level 0 performs group membership checks. Level 1 may not check for weak keys and such.

0975     ///  Levels 2 and 3 are recommended.

0976     /// \details ValidateElement() must be implemented in a derived class.

0977     virtual bool ValidateElement(unsigned int level, const Element &element, const DL_FixedBasePrecomputation<Element> *precomp) const =0;
0978 
0979     virtual bool FastSubgroupCheckAvailable() const =0;
0980 
0981     /// \brief Determines if an element is an identity

0982     /// \param element element to check

0983     /// \return true if the element is an identity, false otherwise

0984     /// \details The identity element or or neutral element is a special element in a group that leaves

0985     ///  other elements unchanged when combined with it.

0986     /// \details IsIdentity() must be implemented in a derived class.

0987     virtual bool IsIdentity(const Element &element) const =0;
0988 
0989     /// \brief Exponentiates a base to multiple exponents

0990     /// \param results an array of Elements

0991     /// \param base the base to raise to the exponents

0992     /// \param exponents an array of exponents

0993     /// \param exponentsCount the number of exponents in the array

0994     /// \details SimultaneousExponentiate() raises the base to each exponent in the exponents array and stores the

0995     ///  result at the respective position in the results array.

0996     /// \details SimultaneousExponentiate() must be implemented in a derived class.

0997     /// \pre <tt>COUNTOF(results) == exponentsCount</tt>

0998     /// \pre <tt>COUNTOF(exponents) == exponentsCount</tt>

0999     virtual void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const =0;
1000 
1001 protected:
1002     void ParametersChanged() {m_validationLevel = 0;}
1003 
1004 private:
1005     mutable unsigned int m_validationLevel;
1006 };
1007 
1008 /// \brief Base implementation of Discrete Log (DL) group parameters

1009 /// \tparam GROUP_PRECOMP group precomputation class

1010 /// \tparam BASE_PRECOMP fixed base precomputation class

1011 /// \tparam BASE class or type of an element

1012 template <class GROUP_PRECOMP, class BASE_PRECOMP = DL_FixedBasePrecomputationImpl<typename GROUP_PRECOMP::Element>, class BASE = DL_GroupParameters<typename GROUP_PRECOMP::Element> >
1013 class DL_GroupParametersImpl : public BASE
1014 {
1015 public:
1016     typedef GROUP_PRECOMP GroupPrecomputation;
1017     typedef typename GROUP_PRECOMP::Element Element;
1018     typedef BASE_PRECOMP BasePrecomputation;
1019 
1020     virtual ~DL_GroupParametersImpl() {}
1021 
1022     /// \brief Retrieves the group precomputation

1023     /// \return a const reference to the group precomputation

1024     const DL_GroupPrecomputation<Element> & GetGroupPrecomputation() const {return m_groupPrecomputation;}
1025 
1026     /// \brief Retrieves the group precomputation

1027     /// \return a const reference to the group precomputation using a fixed base

1028     const DL_FixedBasePrecomputation<Element> & GetBasePrecomputation() const {return m_gpc;}
1029 
1030     /// \brief Retrieves the group precomputation

1031     /// \return a non-const reference to the group precomputation using a fixed base

1032     DL_FixedBasePrecomputation<Element> & AccessBasePrecomputation() {return m_gpc;}
1033 
1034 protected:
1035     GROUP_PRECOMP m_groupPrecomputation;
1036     BASE_PRECOMP m_gpc;
1037 };
1038 
1039 /// \brief Base class for a Discrete Log (DL) key

1040 /// \tparam T class or type of an element

1041 /// \details The element is usually an Integer, \ref ECP "ECP::Point" or \ref EC2N "EC2N::Point"

1042 template <class T>
1043 class CRYPTOPP_NO_VTABLE DL_Key
1044 {
1045 public:
1046     virtual ~DL_Key() {}
1047 
1048     /// \brief Retrieves abstract group parameters

1049     /// \return a const reference to the group parameters

1050     virtual const DL_GroupParameters<T> & GetAbstractGroupParameters() const =0;
1051     /// \brief Retrieves abstract group parameters

1052     /// \return a non-const reference to the group parameters

1053     virtual DL_GroupParameters<T> & AccessAbstractGroupParameters() =0;
1054 };
1055 
1056 /// \brief Interface for Discrete Log (DL) public keys

1057 template <class T>
1058 class CRYPTOPP_NO_VTABLE DL_PublicKey : public DL_Key<T>
1059 {
1060     typedef DL_PublicKey<T> ThisClass;
1061 
1062 public:
1063     typedef T Element;
1064 
1065     virtual ~DL_PublicKey();
1066 
1067     /// \brief Get a named value

1068     /// \param name the name of the object or value to retrieve

1069     /// \param valueType reference to a variable that receives the value

1070     /// \param pValue void pointer to a variable that receives the value

1071     /// \return true if the value was retrieved, false otherwise

1072     /// \details GetVoidValue() retrieves the value of name if it exists.

1073     /// \note GetVoidValue() is an internal function and should be implemented

1074     ///  by derived classes. Users should use one of the other functions instead.

1075     /// \sa GetValue(), GetValueWithDefault(), GetIntValue(), GetIntValueWithDefault(),

1076     ///  GetRequiredParameter() and GetRequiredIntParameter()

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(PublicElement);
1081     }
1082 
1083     /// \brief Initialize or reinitialize this key

1084     /// \param source NameValuePairs to assign

1085     void AssignFrom(const NameValuePairs &source);
1086 
1087     /// \brief Retrieves the public element

1088     /// \return the public element

1089     virtual const Element & GetPublicElement() const {return GetPublicPrecomputation().GetBase(this->GetAbstractGroupParameters().GetGroupPrecomputation());}
1090 
1091     /// \brief Sets the public element

1092     /// \param y the public element

1093     virtual void SetPublicElement(const Element &y) {AccessPublicPrecomputation().SetBase(this->GetAbstractGroupParameters().GetGroupPrecomputation(), y);}
1094 
1095     /// \brief Exponentiates this element

1096     /// \param exponent the exponent to raise the base

1097     /// \return the public element raised to the exponent

1098     virtual Element ExponentiatePublicElement(const Integer &exponent) const
1099     {
1100         const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
1101         return GetPublicPrecomputation().Exponentiate(params.GetGroupPrecomputation(), exponent);
1102     }
1103 
1104     /// \brief Exponentiates an element

1105     /// \param baseExp the first exponent

1106     /// \param publicExp the second exponent

1107     /// \return the public element raised to the exponent

1108     /// \details CascadeExponentiateBaseAndPublicElement raises the public element to

1109     ///  the base element and precomputation.

1110     virtual Element CascadeExponentiateBaseAndPublicElement(const Integer &baseExp, const Integer &publicExp) const
1111     {
1112         const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
1113         return params.GetBasePrecomputation().CascadeExponentiate(params.GetGroupPrecomputation(), baseExp, GetPublicPrecomputation(), publicExp);
1114     }
1115 
1116     /// \brief Accesses the public precomputation

1117     /// \details GetPublicPrecomputation returns a const reference, while

1118     ///  AccessPublicPrecomputation returns a non-const reference. Must be

1119     ///  overridden in derived classes.

1120     virtual const DL_FixedBasePrecomputation<T> & GetPublicPrecomputation() const =0;
1121 
1122     /// \brief Accesses the public precomputation

1123     /// \details GetPublicPrecomputation returns a const reference, while

1124     ///  AccessPublicPrecomputation returns a non-const reference. Must be

1125     ///  overridden in derived classes.

1126     virtual DL_FixedBasePrecomputation<T> & AccessPublicPrecomputation() =0;
1127 };
1128 
1129 // Out-of-line dtor due to AIX and GCC, http://github.com/weidai11/cryptopp/issues/499

1130 template<class T>
1131 DL_PublicKey<T>::~DL_PublicKey() {}
1132 
1133 /// \brief Interface for Discrete Log (DL) private keys

1134 template <class T>
1135 class CRYPTOPP_NO_VTABLE DL_PrivateKey : public DL_Key<T>
1136 {
1137     typedef DL_PrivateKey<T> ThisClass;
1138 
1139 public:
1140     typedef T Element;
1141 
1142     virtual ~DL_PrivateKey();
1143 
1144     /// \brief Initializes a public key from this key

1145     /// \param pub reference to a public key

1146     void MakePublicKey(DL_PublicKey<T> &pub) const
1147     {
1148         pub.AccessAbstractGroupParameters().AssignFrom(this->GetAbstractGroupParameters());
1149         pub.SetPublicElement(this->GetAbstractGroupParameters().ExponentiateBase(GetPrivateExponent()));
1150     }
1151 
1152     /// \brief Get a named value

1153     /// \param name the name of the object or value to retrieve

1154     /// \param valueType reference to a variable that receives the value

1155     /// \param pValue void pointer to a variable that receives the value

1156     /// \return true if the value was retrieved, false otherwise

1157     /// \details GetVoidValue() retrieves the value of name if it exists.

1158     /// \note GetVoidValue() is an internal function and should be implemented

1159     ///  by derived classes. Users should use one of the other functions instead.

1160     /// \sa GetValue(), GetValueWithDefault(), GetIntValue(), GetIntValueWithDefault(),

1161     ///  GetRequiredParameter() and GetRequiredIntParameter()

1162     bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
1163     {
1164         return GetValueHelper(this, name, valueType, pValue, &this->GetAbstractGroupParameters())
1165                 CRYPTOPP_GET_FUNCTION_ENTRY(PrivateExponent);
1166     }
1167 
1168     /// \brief Initialize or reinitialize this key

1169     /// \param source NameValuePairs to assign

1170     void AssignFrom(const NameValuePairs &source)
1171     {
1172         this->AccessAbstractGroupParameters().AssignFrom(source);
1173         AssignFromHelper(this, source)
1174             CRYPTOPP_SET_FUNCTION_ENTRY(PrivateExponent);
1175     }
1176 
1177     /// \brief Retrieves the private exponent

1178     /// \return the private exponent

1179     /// \details Must be overridden in derived classes.

1180     virtual const Integer & GetPrivateExponent() const =0;
1181     /// \brief Sets the private exponent

1182     /// \param x the private exponent

1183     /// \details Must be overridden in derived classes.

1184     virtual void SetPrivateExponent(const Integer &x) =0;
1185 };
1186 
1187 // Out-of-line dtor due to AIX and GCC, http://github.com/weidai11/cryptopp/issues/499

1188 template<class T>
1189 DL_PrivateKey<T>::~DL_PrivateKey() {}
1190 
1191 template <class T>
1192 void DL_PublicKey<T>::AssignFrom(const NameValuePairs &source)
1193 {
1194     DL_PrivateKey<T> *pPrivateKey = NULLPTR;
1195     if (source.GetThisPointer(pPrivateKey))
1196         pPrivateKey->MakePublicKey(*this);
1197     else
1198     {
1199         this->AccessAbstractGroupParameters().AssignFrom(source);
1200         AssignFromHelper(this, source)
1201             CRYPTOPP_SET_FUNCTION_ENTRY(PublicElement);
1202     }
1203 }
1204 
1205 class OID;
1206 
1207 /// \brief Discrete Log (DL) key base implementation

1208 /// \tparam PK Key class

1209 /// \tparam GP GroupParameters class

1210 /// \tparam O OID class

1211 template <class PK, class GP, class O = OID>
1212 class DL_KeyImpl : public PK
1213 {
1214 public:
1215     typedef GP GroupParameters;
1216 
1217     virtual ~DL_KeyImpl() {}
1218 
1219     O GetAlgorithmID() const {return GetGroupParameters().GetAlgorithmID();}
1220     bool BERDecodeAlgorithmParameters(BufferedTransformation &bt)
1221         {AccessGroupParameters().BERDecode(bt); return true;}
1222     bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const
1223         {GetGroupParameters().DEREncode(bt); return true;}
1224 
1225     const GP & GetGroupParameters() const {return m_groupParameters;}
1226     GP & AccessGroupParameters() {return m_groupParameters;}
1227 
1228 private:
1229     GP m_groupParameters;
1230 };
1231 
1232 class X509PublicKey;
1233 class PKCS8PrivateKey;
1234 
1235 /// \brief Discrete Log (DL) private key base implementation

1236 /// \tparam GP GroupParameters class

1237 template <class GP>
1238 class DL_PrivateKeyImpl : public DL_PrivateKey<typename GP::Element>, public DL_KeyImpl<PKCS8PrivateKey, GP>
1239 {
1240 public:
1241     typedef typename GP::Element Element;
1242 
1243     virtual ~DL_PrivateKeyImpl() {}
1244 
1245     // GeneratableCryptoMaterial

1246     bool Validate(RandomNumberGenerator &rng, unsigned int level) const
1247     {
1248         CRYPTOPP_ASSERT(GetAbstractGroupParameters().Validate(rng, level));
1249         bool pass = GetAbstractGroupParameters().Validate(rng, level);
1250 
1251         const Integer &q = GetAbstractGroupParameters().GetSubgroupOrder();
1252         const Integer &x = GetPrivateExponent();
1253 
1254         CRYPTOPP_ASSERT(x.IsPositive());
1255         CRYPTOPP_ASSERT(x < q);
1256         pass = pass && x.IsPositive() && x < q;
1257 
1258         if (level >= 1)
1259         {
1260             CRYPTOPP_ASSERT(Integer::Gcd(x, q) == Integer::One());
1261             pass = pass && Integer::Gcd(x, q) == Integer::One();
1262         }
1263         return pass;
1264     }
1265 
1266     bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
1267     {
1268         return GetValueHelper<DL_PrivateKey<Element> >(this, name, valueType, pValue).Assignable();
1269     }
1270 
1271     void AssignFrom(const NameValuePairs &source)
1272     {
1273         AssignFromHelper<DL_PrivateKey<Element> >(this, source);
1274     }
1275 
1276     void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &params)
1277     {
1278         if (!params.GetThisObject(this->AccessGroupParameters()))
1279             this->AccessGroupParameters().GenerateRandom(rng, params);
1280         Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent());
1281         SetPrivateExponent(x);
1282     }
1283 
1284     bool SupportsPrecomputation() const {return true;}
1285 
1286     void Precompute(unsigned int precomputationStorage=16)
1287         {AccessAbstractGroupParameters().Precompute(precomputationStorage);}
1288 
1289     void LoadPrecomputation(BufferedTransformation &storedPrecomputation)
1290         {AccessAbstractGroupParameters().LoadPrecomputation(storedPrecomputation);}
1291 
1292     void SavePrecomputation(BufferedTransformation &storedPrecomputation) const
1293         {GetAbstractGroupParameters().SavePrecomputation(storedPrecomputation);}
1294 
1295     // DL_Key

1296     const DL_GroupParameters<Element> & GetAbstractGroupParameters() const {return this->GetGroupParameters();}
1297     DL_GroupParameters<Element> & AccessAbstractGroupParameters() {return this->AccessGroupParameters();}
1298 
1299     // DL_PrivateKey

1300     const Integer & GetPrivateExponent() const {return m_x;}
1301     void SetPrivateExponent(const Integer &x) {m_x = x;}
1302 
1303     // PKCS8PrivateKey

1304     void BERDecodePrivateKey(BufferedTransformation &bt, bool, size_t)
1305         {m_x.BERDecode(bt);}
1306     void DEREncodePrivateKey(BufferedTransformation &bt) const
1307         {m_x.DEREncode(bt);}
1308 
1309 private:
1310     Integer m_x;
1311 };
1312 
1313 template <class BASE, class SIGNATURE_SCHEME>
1314 class DL_PrivateKey_WithSignaturePairwiseConsistencyTest : public BASE
1315 {
1316 public:
1317     virtual ~DL_PrivateKey_WithSignaturePairwiseConsistencyTest() {}
1318 
1319     void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &params)
1320     {
1321         BASE::GenerateRandom(rng, params);
1322 
1323         if (FIPS_140_2_ComplianceEnabled())
1324         {
1325             typename SIGNATURE_SCHEME::Signer signer(*this);
1326             typename SIGNATURE_SCHEME::Verifier verifier(signer);
1327             SignaturePairwiseConsistencyTest_FIPS_140_Only(signer, verifier);
1328         }
1329     }
1330 };
1331 
1332 /// \brief Discrete Log (DL) public key base implementation

1333 /// \tparam GP GroupParameters class

1334 template <class GP>
1335 class DL_PublicKeyImpl : public DL_PublicKey<typename GP::Element>, public DL_KeyImpl<X509PublicKey, GP>
1336 {
1337 public:
1338     typedef typename GP::Element Element;
1339 
1340     virtual ~DL_PublicKeyImpl();
1341 
1342     // CryptoMaterial

1343     bool Validate(RandomNumberGenerator &rng, unsigned int level) const
1344     {
1345         CRYPTOPP_ASSERT(GetAbstractGroupParameters().Validate(rng, level));
1346         bool pass = GetAbstractGroupParameters().Validate(rng, level);
1347         CRYPTOPP_ASSERT(GetAbstractGroupParameters().ValidateElement(level, this->GetPublicElement(), &GetPublicPrecomputation()));
1348         pass = pass && GetAbstractGroupParameters().ValidateElement(level, this->GetPublicElement(), &GetPublicPrecomputation());
1349         return pass;
1350     }
1351 
1352     bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
1353     {
1354         return GetValueHelper<DL_PublicKey<Element> >(this, name, valueType, pValue).Assignable();
1355     }
1356 
1357     void AssignFrom(const NameValuePairs &source)
1358     {
1359         AssignFromHelper<DL_PublicKey<Element> >(this, source);
1360     }
1361 
1362     bool SupportsPrecomputation() const {return true;}
1363 
1364     void Precompute(unsigned int precomputationStorage=16)
1365     {
1366         AccessAbstractGroupParameters().Precompute(precomputationStorage);
1367         AccessPublicPrecomputation().Precompute(GetAbstractGroupParameters().GetGroupPrecomputation(), GetAbstractGroupParameters().GetSubgroupOrder().BitCount(), precomputationStorage);
1368     }
1369 
1370     void LoadPrecomputation(BufferedTransformation &storedPrecomputation)
1371     {
1372         AccessAbstractGroupParameters().LoadPrecomputation(storedPrecomputation);
1373         AccessPublicPrecomputation().Load(GetAbstractGroupParameters().GetGroupPrecomputation(), storedPrecomputation);
1374     }
1375 
1376     void SavePrecomputation(BufferedTransformation &storedPrecomputation) const
1377     {
1378         GetAbstractGroupParameters().SavePrecomputation(storedPrecomputation);
1379         GetPublicPrecomputation().Save(GetAbstractGroupParameters().GetGroupPrecomputation(), storedPrecomputation);
1380     }
1381 
1382     // DL_Key

1383     const DL_GroupParameters<Element> & GetAbstractGroupParameters() const {return this->GetGroupParameters();}
1384     DL_GroupParameters<Element> & AccessAbstractGroupParameters() {return this->AccessGroupParameters();}
1385 
1386     // DL_PublicKey

1387     const DL_FixedBasePrecomputation<Element> & GetPublicPrecomputation() const {return m_ypc;}
1388     DL_FixedBasePrecomputation<Element> & AccessPublicPrecomputation() {return m_ypc;}
1389 
1390     // non-inherited

1391     bool operator==(const DL_PublicKeyImpl<GP> &rhs) const
1392         {return this->GetGroupParameters() == rhs.GetGroupParameters() && this->GetPublicElement() == rhs.GetPublicElement();}
1393 
1394 private:
1395     typename GP::BasePrecomputation m_ypc;
1396 };
1397 
1398 // Out-of-line dtor due to AIX and GCC, http://github.com/weidai11/cryptopp/issues/499

1399 template<class GP>
1400 DL_PublicKeyImpl<GP>::~DL_PublicKeyImpl() {}
1401 
1402 /// \brief Interface for Elgamal-like signature algorithms

1403 /// \tparam T Field element type or class

1404 /// \details Field element <tt>T</tt> can be Integer, ECP or EC2N.

1405 template <class T>
1406 class CRYPTOPP_NO_VTABLE DL_ElgamalLikeSignatureAlgorithm
1407 {
1408 public:
1409     virtual ~DL_ElgamalLikeSignatureAlgorithm() {}
1410 
1411     /// \brief Sign a message using a private key

1412     /// \param params GroupParameters

1413     /// \param privateKey private key

1414     /// \param k signing exponent

1415     /// \param e encoded message

1416     /// \param r r part of signature

1417     /// \param s s part of signature

1418     virtual void Sign(const DL_GroupParameters<T> &params, const Integer &privateKey, const Integer &k, const Integer &e, Integer &r, Integer &s) const =0;
1419 
1420     /// \brief Verify a message using a public key

1421     /// \param params GroupParameters

1422     /// \param publicKey public key

1423     /// \param e encoded message

1424     /// \param r r part of signature

1425     /// \param s s part of signature

1426     virtual bool Verify(const DL_GroupParameters<T> &params, const DL_PublicKey<T> &publicKey, const Integer &e, const Integer &r, const Integer &s) const =0;
1427 
1428     /// \brief Recover a Presignature

1429     /// \param params GroupParameters

1430     /// \param publicKey public key

1431     /// \param r r part of signature

1432     /// \param s s part of signature

1433     virtual Integer RecoverPresignature(const DL_GroupParameters<T> &params, const DL_PublicKey<T> &publicKey, const Integer &r, const Integer &s) const
1434     {
1435         CRYPTOPP_UNUSED(params); CRYPTOPP_UNUSED(publicKey); CRYPTOPP_UNUSED(r); CRYPTOPP_UNUSED(s);
1436         throw NotImplemented("DL_ElgamalLikeSignatureAlgorithm: this signature scheme does not support message recovery");
1437         MAYBE_RETURN(Integer::Zero());
1438     }
1439 
1440     /// \brief Retrieve R length

1441     /// \param params GroupParameters

1442     virtual size_t RLen(const DL_GroupParameters<T> &params) const
1443         {return params.GetSubgroupOrder().ByteCount();}
1444 
1445     /// \brief Retrieve S length

1446     /// \param params GroupParameters

1447     virtual size_t SLen(const DL_GroupParameters<T> &params) const
1448         {return params.GetSubgroupOrder().ByteCount();}
1449 
1450     /// \brief Signature scheme flag

1451     /// \return true if the signature scheme is deterministic, false otherwise

1452     /// \details IsDeterministic() is provided for DL signers. It is used by RFC 6979 signature schemes.

1453     virtual bool IsDeterministic() const
1454         {return false;}
1455 };
1456 
1457 /// \brief Interface for deterministic signers

1458 /// \details RFC 6979 signers which generate k based on the encoded message and private key

1459 class CRYPTOPP_NO_VTABLE DeterministicSignatureAlgorithm
1460 {
1461 public:
1462     virtual ~DeterministicSignatureAlgorithm() {}
1463 
1464     /// \brief Generate k

1465     /// \param x private key

1466     /// \param q subgroup generator

1467     /// \param e encoded message

1468     virtual Integer GenerateRandom(const Integer &x, const Integer &q, const Integer &e) const =0;
1469 };
1470 
1471 /// \brief Interface for DL key agreement algorithms

1472 /// \tparam T Field element type or class

1473 /// \details Field element <tt>T</tt> can be Integer, ECP or EC2N.

1474 /// \sa DLIES, ECIES, ECIES_P1363

1475 template <class T>
1476 class CRYPTOPP_NO_VTABLE DL_KeyAgreementAlgorithm
1477 {
1478 public:
1479     typedef T Element;
1480 
1481     virtual ~DL_KeyAgreementAlgorithm() {}
1482 
1483     virtual Element AgreeWithEphemeralPrivateKey(const DL_GroupParameters<Element> &params, const DL_FixedBasePrecomputation<Element> &publicPrecomputation, const Integer &privateExponent) const =0;
1484     virtual Element AgreeWithStaticPrivateKey(const DL_GroupParameters<Element> &params, const Element &publicElement, bool validateOtherPublicKey, const Integer &privateExponent) const =0;
1485 };
1486 
1487 /// \brief Interface for key derivation algorithms used in DL cryptosystems

1488 /// \tparam T Field element type or class

1489 /// \details Field element <tt>T</tt> can be Integer, ECP or EC2N.

1490 /// \sa DLIES, ECIES, ECIES_P1363

1491 template <class T>
1492 class CRYPTOPP_NO_VTABLE DL_KeyDerivationAlgorithm
1493 {
1494 public:
1495     virtual ~DL_KeyDerivationAlgorithm() {}
1496 
1497     virtual bool ParameterSupported(const char *name) const
1498         {CRYPTOPP_UNUSED(name); return false;}
1499     virtual void Derive(const DL_GroupParameters<T> &groupParams, byte *derivedKey, size_t derivedLength, const T &agreedElement, const T &ephemeralPublicKey, const NameValuePairs &derivationParams) const =0;
1500 };
1501 
1502 /// \brief Interface for symmetric encryption algorithms used in DL cryptosystems

1503 /// \sa DLIES, ECIES, ECIES_P1363

1504 class CRYPTOPP_NO_VTABLE DL_SymmetricEncryptionAlgorithm
1505 {
1506 public:
1507     virtual ~DL_SymmetricEncryptionAlgorithm() {}
1508 
1509     virtual bool ParameterSupported(const char *name) const
1510         {CRYPTOPP_UNUSED(name); return false;}
1511     virtual size_t GetSymmetricKeyLength(size_t plaintextLength) const =0;
1512     virtual size_t GetSymmetricCiphertextLength(size_t plaintextLength) const =0;
1513     virtual size_t GetMaxSymmetricPlaintextLength(size_t ciphertextLength) const =0;
1514     virtual void SymmetricEncrypt(RandomNumberGenerator &rng, const byte *key, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs &parameters) const =0;
1515     virtual DecodingResult SymmetricDecrypt(const byte *key, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs &parameters) const =0;
1516 };
1517 
1518 /// \brief Discrete Log (DL) base interface

1519 /// \tparam KI public or private key interface

1520 template <class KI>
1521 class CRYPTOPP_NO_VTABLE DL_Base
1522 {
1523 protected:
1524     typedef KI KeyInterface;
1525     typedef typename KI::Element Element;
1526 
1527     virtual ~DL_Base() {}
1528 
1529     const DL_GroupParameters<Element> & GetAbstractGroupParameters() const {return GetKeyInterface().GetAbstractGroupParameters();}
1530     DL_GroupParameters<Element> & AccessAbstractGroupParameters() {return AccessKeyInterface().AccessAbstractGroupParameters();}
1531 
1532     virtual KeyInterface & AccessKeyInterface() =0;
1533     virtual const KeyInterface & GetKeyInterface() const =0;
1534 };
1535 
1536 /// \brief Discrete Log (DL) signature scheme base implementation

1537 /// \tparam INTFACE PK_Signer or PK_Verifier derived class

1538 /// \tparam KEY_INTFACE DL_Base key base used in the scheme

1539 /// \details DL_SignatureSchemeBase provides common functions for signers and verifiers.

1540 ///  DL_Base<DL_PrivateKey> is used for signers, and DL_Base<DL_PublicKey> is used for verifiers.

1541 template <class INTFACE, class KEY_INTFACE>
1542 class CRYPTOPP_NO_VTABLE DL_SignatureSchemeBase : public INTFACE, public DL_Base<KEY_INTFACE>
1543 {
1544 public:
1545     virtual ~DL_SignatureSchemeBase() {}
1546 
1547     /// \brief Provides the signature length

1548     /// \return signature length, in bytes

1549     /// \details SignatureLength returns the size required for <tt>r+s</tt>.

1550     size_t SignatureLength() const
1551     {
1552         return GetSignatureAlgorithm().RLen(this->GetAbstractGroupParameters())
1553             + GetSignatureAlgorithm().SLen(this->GetAbstractGroupParameters());
1554     }
1555 
1556     /// \brief Provides the maximum recoverable length

1557     /// \return maximum recoverable length, in bytes

1558     size_t MaxRecoverableLength() const
1559         {return GetMessageEncodingInterface().MaxRecoverableLength(0, GetHashIdentifier().second, GetDigestSize());}
1560 
1561     /// \brief Provides the maximum recoverable length

1562     /// \param signatureLength the size of the signature

1563     /// \return maximum recoverable length based on signature length, in bytes

1564     /// \details this function is not implemented and always returns 0.

1565     size_t MaxRecoverableLengthFromSignatureLength(size_t signatureLength) const
1566         {CRYPTOPP_UNUSED(signatureLength); CRYPTOPP_ASSERT(false); return 0;}   // TODO

1567 
1568     /// \brief Determines if the scheme is probabilistic

1569     /// \return true if the scheme is probabilistic, false otherwise

1570     bool IsProbabilistic() const
1571         {return true;}
1572 
1573     /// \brief Determines if the scheme has non-recoverable part

1574     /// \return true if the message encoding has a non-recoverable part, false otherwise.

1575     bool AllowNonrecoverablePart() const
1576         {return GetMessageEncodingInterface().AllowNonrecoverablePart();}
1577 
1578     /// \brief Determines if the scheme allows recoverable part first

1579     /// \return true if the message encoding allows the recoverable part, false otherwise.

1580     bool RecoverablePartFirst() const
1581         {return GetMessageEncodingInterface().RecoverablePartFirst();}
1582 
1583 protected:
1584     size_t MessageRepresentativeLength() const {return BitsToBytes(MessageRepresentativeBitLength());}
1585     size_t MessageRepresentativeBitLength() const {return this->GetAbstractGroupParameters().GetSubgroupOrder().BitCount();}
1586 
1587     // true if the scheme conforms to RFC 6979

1588     virtual bool IsDeterministic() const {return false;}
1589 
1590     virtual const DL_ElgamalLikeSignatureAlgorithm<typename KEY_INTFACE::Element> & GetSignatureAlgorithm() const =0;
1591     virtual const PK_SignatureMessageEncodingMethod & GetMessageEncodingInterface() const =0;
1592     virtual HashIdentifier GetHashIdentifier() const =0;
1593     virtual size_t GetDigestSize() const =0;
1594 };
1595 
1596 /// \brief Discrete Log (DL) signature scheme signer base implementation

1597 /// \tparam T Field element type or class

1598 /// \details Field element <tt>T</tt> can be Integer, ECP or EC2N.

1599 template <class T>
1600 class CRYPTOPP_NO_VTABLE DL_SignerBase : public DL_SignatureSchemeBase<PK_Signer, DL_PrivateKey<T> >
1601 {
1602 public:
1603     virtual ~DL_SignerBase() {}
1604 
1605     /// \brief Testing interface

1606     /// \param k Integer

1607     /// \param e Integer

1608     /// \param r Integer

1609     /// \param s Integer

1610     void RawSign(const Integer &k, const Integer &e, Integer &r, Integer &s) const
1611     {
1612         const DL_ElgamalLikeSignatureAlgorithm<T> &alg = this->GetSignatureAlgorithm();
1613         const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
1614         const DL_PrivateKey<T> &key = this->GetKeyInterface();
1615 
1616         r = params.ConvertElementToInteger(params.ExponentiateBase(k));
1617         alg.Sign(params, key.GetPrivateExponent(), k, e, r, s);
1618     }
1619 
1620     void InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, size_t recoverableMessageLength) const
1621     {
1622         PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
1623         ma.m_recoverableMessage.Assign(recoverableMessage, recoverableMessageLength);
1624         this->GetMessageEncodingInterface().ProcessRecoverableMessage(ma.AccessHash(),
1625             recoverableMessage, recoverableMessageLength,
1626             ma.m_presignature, ma.m_presignature.size(),
1627             ma.m_semisignature);
1628     }
1629 
1630     size_t SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart) const
1631     {
1632         this->GetMaterial().DoQuickSanityCheck();
1633 
1634         PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
1635         const DL_ElgamalLikeSignatureAlgorithm<T> &alg = this->GetSignatureAlgorithm();
1636         const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
1637         const DL_PrivateKey<T> &key = this->GetKeyInterface();
1638 
1639         SecByteBlock representative(this->MessageRepresentativeLength());
1640         this->GetMessageEncodingInterface().ComputeMessageRepresentative(
1641             rng,
1642             ma.m_recoverableMessage, ma.m_recoverableMessage.size(),
1643             ma.AccessHash(), this->GetHashIdentifier(), ma.m_empty,
1644             representative, this->MessageRepresentativeBitLength());
1645         ma.m_empty = true;
1646         Integer e(representative, representative.size());
1647 
1648         // hash message digest into random number k to prevent reusing the same k on

1649         // different messages after virtual machine rollback

1650         if (rng.CanIncorporateEntropy())
1651             rng.IncorporateEntropy(representative, representative.size());
1652 
1653         Integer k, ks;
1654         const Integer& q = params.GetSubgroupOrder();
1655         if (alg.IsDeterministic())
1656         {
1657             const Integer& x = key.GetPrivateExponent();
1658             const DeterministicSignatureAlgorithm& det = dynamic_cast<const DeterministicSignatureAlgorithm&>(alg);
1659             k = det.GenerateRandom(x, q, e);
1660         }
1661         else
1662         {
1663             k.Randomize(rng, 1, params.GetSubgroupOrder()-1);
1664         }
1665 
1666         // Due to timing attack on nonce length by Jancar

1667         // https://github.com/weidai11/cryptopp/issues/869

1668         ks = k + q;
1669         if (ks.BitCount() == q.BitCount()) {
1670             ks += q;
1671         }
1672 
1673         Integer r, s;
1674         r = params.ConvertElementToInteger(params.ExponentiateBase(ks));
1675         alg.Sign(params, key.GetPrivateExponent(), k, e, r, s);
1676 
1677         /*

1678         Integer r, s;

1679         if (this->MaxRecoverableLength() > 0)

1680             r.Decode(ma.m_semisignature, ma.m_semisignature.size());

1681         else

1682             r.Decode(ma.m_presignature, ma.m_presignature.size());

1683         alg.Sign(params, key.GetPrivateExponent(), ma.m_k, e, r, s);

1684         */
1685 
1686         const size_t rLen = alg.RLen(params);
1687         r.Encode(signature, rLen);
1688         s.Encode(signature+rLen, alg.SLen(params));
1689 
1690         if (restart)
1691             RestartMessageAccumulator(rng, ma);
1692 
1693         return this->SignatureLength();
1694     }
1695 
1696 protected:
1697     void RestartMessageAccumulator(RandomNumberGenerator &rng, PK_MessageAccumulatorBase &ma) const
1698     {
1699         // k needs to be generated before hashing for signature schemes with recovery

1700         // but to defend against VM rollbacks we need to generate k after hashing.

1701         // so this code is commented out, since no DL-based signature scheme with recovery

1702         // has been implemented in Crypto++ anyway

1703         /*

1704         const DL_ElgamalLikeSignatureAlgorithm<T> &alg = this->GetSignatureAlgorithm();

1705         const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();

1706         ma.m_k.Randomize(rng, 1, params.GetSubgroupOrder()-1);

1707         ma.m_presignature.New(params.GetEncodedElementSize(false));

1708         params.ConvertElementToInteger(params.ExponentiateBase(ma.m_k)).Encode(ma.m_presignature, ma.m_presignature.size());

1709         */
1710         CRYPTOPP_UNUSED(rng); CRYPTOPP_UNUSED(ma);
1711     }
1712 };
1713 
1714 /// \brief Discret Log (DL) Verifier base class

1715 /// \tparam T Field element type or class

1716 /// \details Field element <tt>T</tt> can be Integer, ECP or EC2N.

1717 template <class T>
1718 class CRYPTOPP_NO_VTABLE DL_VerifierBase : public DL_SignatureSchemeBase<PK_Verifier, DL_PublicKey<T> >
1719 {
1720 public:
1721     virtual ~DL_VerifierBase() {}
1722 
1723     void InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, size_t signatureLength) const
1724     {
1725         PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
1726         const DL_ElgamalLikeSignatureAlgorithm<T> &alg = this->GetSignatureAlgorithm();
1727         const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
1728 
1729         // Validation due to https://github.com/weidai11/cryptopp/issues/981

1730         // We allow a caller to provide R and S in oversized buffer. R and S

1731         // are read based on the field element size, and not the buffer size.

1732         const size_t rLen = alg.RLen(params);
1733         const size_t sLen = alg.SLen(params);
1734         CRYPTOPP_ASSERT(signatureLength >= rLen + sLen);
1735         if (signatureLength < rLen + sLen)
1736             throw InvalidDataFormat("DL_VerifierBase: signature length is not valid.");
1737 
1738         ma.m_semisignature.Assign(signature, rLen);
1739         ma.m_s.Decode(signature+rLen, sLen);
1740 
1741         this->GetMessageEncodingInterface().ProcessSemisignature(ma.AccessHash(), ma.m_semisignature, ma.m_semisignature.size());
1742     }
1743 
1744     bool VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const
1745     {
1746         this->GetMaterial().DoQuickSanityCheck();
1747 
1748         PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
1749         const DL_ElgamalLikeSignatureAlgorithm<T> &alg = this->GetSignatureAlgorithm();
1750         const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
1751         const DL_PublicKey<T> &key = this->GetKeyInterface();
1752 
1753         SecByteBlock representative(this->MessageRepresentativeLength());
1754         this->GetMessageEncodingInterface().ComputeMessageRepresentative(NullRNG(), ma.m_recoverableMessage, ma.m_recoverableMessage.size(),
1755             ma.AccessHash(), this->GetHashIdentifier(), ma.m_empty,
1756             representative, this->MessageRepresentativeBitLength());
1757         ma.m_empty = true;
1758         Integer e(representative, representative.size());
1759 
1760         Integer r(ma.m_semisignature, ma.m_semisignature.size());
1761         return alg.Verify(params, key, e, r, ma.m_s);
1762     }
1763 
1764     DecodingResult RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &messageAccumulator) const
1765     {
1766         this->GetMaterial().DoQuickSanityCheck();
1767 
1768         PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
1769         const DL_ElgamalLikeSignatureAlgorithm<T> &alg = this->GetSignatureAlgorithm();
1770         const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
1771         const DL_PublicKey<T> &key = this->GetKeyInterface();
1772 
1773         SecByteBlock representative(this->MessageRepresentativeLength());
1774         this->GetMessageEncodingInterface().ComputeMessageRepresentative(
1775             NullRNG(),
1776             ma.m_recoverableMessage, ma.m_recoverableMessage.size(),
1777             ma.AccessHash(), this->GetHashIdentifier(), ma.m_empty,
1778             representative, this->MessageRepresentativeBitLength());
1779         ma.m_empty = true;
1780         Integer e(representative, representative.size());
1781 
1782         ma.m_presignature.New(params.GetEncodedElementSize(false));
1783         Integer r(ma.m_semisignature, ma.m_semisignature.size());
1784         alg.RecoverPresignature(params, key, r, ma.m_s).Encode(ma.m_presignature, ma.m_presignature.size());
1785 
1786         return this->GetMessageEncodingInterface().RecoverMessageFromSemisignature(
1787             ma.AccessHash(), this->GetHashIdentifier(),
1788             ma.m_presignature, ma.m_presignature.size(),
1789             ma.m_semisignature, ma.m_semisignature.size(),
1790             recoveredMessage);
1791     }
1792 };
1793 
1794 /// \brief Discrete Log (DL) cryptosystem base implementation

1795 /// \tparam PK field element type

1796 /// \tparam KI public or private key interface

1797 template <class PK, class KI>
1798 class CRYPTOPP_NO_VTABLE DL_CryptoSystemBase : public PK, public DL_Base<KI>
1799 {
1800 public:
1801     typedef typename DL_Base<KI>::Element Element;
1802 
1803     virtual ~DL_CryptoSystemBase() {}
1804 
1805     size_t MaxPlaintextLength(size_t ciphertextLength) const
1806     {
1807         unsigned int minLen = this->GetAbstractGroupParameters().GetEncodedElementSize(true);
1808         return ciphertextLength < minLen ? 0 : GetSymmetricEncryptionAlgorithm().GetMaxSymmetricPlaintextLength(ciphertextLength - minLen);
1809     }
1810 
1811     size_t CiphertextLength(size_t plaintextLength) const
1812     {
1813         size_t len = GetSymmetricEncryptionAlgorithm().GetSymmetricCiphertextLength(plaintextLength);
1814         return len == 0 ? 0 : this->GetAbstractGroupParameters().GetEncodedElementSize(true) + len;
1815     }
1816 
1817     bool ParameterSupported(const char *name) const
1818         {return GetKeyDerivationAlgorithm().ParameterSupported(name) || GetSymmetricEncryptionAlgorithm().ParameterSupported(name);}
1819 
1820 protected:
1821     virtual const DL_KeyAgreementAlgorithm<Element> & GetKeyAgreementAlgorithm() const =0;
1822     virtual const DL_KeyDerivationAlgorithm<Element> & GetKeyDerivationAlgorithm() const =0;
1823     virtual const DL_SymmetricEncryptionAlgorithm & GetSymmetricEncryptionAlgorithm() const =0;
1824 };
1825 
1826 /// \brief Discrete Log (DL) decryptor base implementation

1827 /// \tparam T Field element type or class

1828 /// \details Field element <tt>T</tt> can be Integer, ECP or EC2N.

1829 template <class T>
1830 class CRYPTOPP_NO_VTABLE DL_DecryptorBase : public DL_CryptoSystemBase<PK_Decryptor, DL_PrivateKey<T> >
1831 {
1832 public:
1833     typedef T Element;
1834 
1835     virtual ~DL_DecryptorBase() {}
1836 
1837     DecodingResult Decrypt(RandomNumberGenerator &rng, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs &parameters = g_nullNameValuePairs) const
1838     {
1839         try
1840         {
1841             CRYPTOPP_UNUSED(rng);
1842             const DL_KeyAgreementAlgorithm<T> &agreeAlg = this->GetKeyAgreementAlgorithm();
1843             const DL_KeyDerivationAlgorithm<T> &derivAlg = this->GetKeyDerivationAlgorithm();
1844             const DL_SymmetricEncryptionAlgorithm &encAlg = this->GetSymmetricEncryptionAlgorithm();
1845             const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
1846             const DL_PrivateKey<T> &key = this->GetKeyInterface();
1847 
1848             Element q = params.DecodeElement(ciphertext, true);
1849             size_t elementSize = params.GetEncodedElementSize(true);
1850             ciphertext += elementSize;
1851             ciphertextLength -= elementSize;
1852 
1853             Element z = agreeAlg.AgreeWithStaticPrivateKey(params, q, true, key.GetPrivateExponent());
1854 
1855             SecByteBlock derivedKey(encAlg.GetSymmetricKeyLength(encAlg.GetMaxSymmetricPlaintextLength(ciphertextLength)));
1856             derivAlg.Derive(params, derivedKey, derivedKey.size(), z, q, parameters);
1857 
1858             return encAlg.SymmetricDecrypt(derivedKey, ciphertext, ciphertextLength, plaintext, parameters);
1859         }
1860         catch (DL_BadElement &)
1861         {
1862             return DecodingResult();
1863         }
1864     }
1865 };
1866 
1867 /// \brief Discrete Log (DL) encryptor base implementation

1868 /// \tparam T Field element type or class

1869 /// \details Field element <tt>T</tt> can be Integer, ECP or EC2N.

1870 template <class T>
1871 class CRYPTOPP_NO_VTABLE DL_EncryptorBase : public DL_CryptoSystemBase<PK_Encryptor, DL_PublicKey<T> >
1872 {
1873 public:
1874     typedef T Element;
1875 
1876     virtual ~DL_EncryptorBase() {}
1877 
1878     void Encrypt(RandomNumberGenerator &rng, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs &parameters = g_nullNameValuePairs) const
1879     {
1880         const DL_KeyAgreementAlgorithm<T> &agreeAlg = this->GetKeyAgreementAlgorithm();
1881         const DL_KeyDerivationAlgorithm<T> &derivAlg = this->GetKeyDerivationAlgorithm();
1882         const DL_SymmetricEncryptionAlgorithm &encAlg = this->GetSymmetricEncryptionAlgorithm();
1883         const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
1884         const DL_PublicKey<T> &key = this->GetKeyInterface();
1885 
1886         Integer x(rng, Integer::One(), params.GetMaxExponent());
1887         Element q = params.ExponentiateBase(x);
1888         params.EncodeElement(true, q, ciphertext);
1889         unsigned int elementSize = params.GetEncodedElementSize(true);
1890         ciphertext += elementSize;
1891 
1892         Element z = agreeAlg.AgreeWithEphemeralPrivateKey(params, key.GetPublicPrecomputation(), x);
1893 
1894         SecByteBlock derivedKey(encAlg.GetSymmetricKeyLength(plaintextLength));
1895         derivAlg.Derive(params, derivedKey, derivedKey.size(), z, q, parameters);
1896 
1897         encAlg.SymmetricEncrypt(rng, derivedKey, plaintext, plaintextLength, ciphertext, parameters);
1898     }
1899 };
1900 
1901 /// \brief Discrete Log (DL) scheme options

1902 /// \tparam T1 algorithm information

1903 /// \tparam T2 group parameters for the scheme

1904 template <class T1, class T2>
1905 struct DL_SchemeOptionsBase
1906 {
1907     typedef T1 AlgorithmInfo;
1908     typedef T2 GroupParameters;
1909     typedef typename GroupParameters::Element Element;
1910 };
1911 
1912 /// \brief Discrete Log (DL) key options

1913 /// \tparam T1 algorithm information

1914 /// \tparam T2 keys used in the scheme

1915 template <class T1, class T2>
1916 struct DL_KeyedSchemeOptions : public DL_SchemeOptionsBase<T1, typename T2::PublicKey::GroupParameters>
1917 {
1918     typedef T2 Keys;
1919     typedef typename Keys::PrivateKey PrivateKey;
1920     typedef typename Keys::PublicKey PublicKey;
1921 };
1922 
1923 /// \brief Discrete Log (DL) signature scheme options

1924 /// \tparam T1 algorithm information

1925 /// \tparam T2 keys used in the scheme

1926 /// \tparam T3 signature algorithm

1927 /// \tparam T4 message encoding method

1928 /// \tparam T5 hash function

1929 template <class T1, class T2, class T3, class T4, class T5>
1930 struct DL_SignatureSchemeOptions : public DL_KeyedSchemeOptions<T1, T2>
1931 {
1932     typedef T3 SignatureAlgorithm;
1933     typedef T4 MessageEncodingMethod;
1934     typedef T5 HashFunction;
1935 };
1936 
1937 /// \brief Discrete Log (DL) crypto scheme options

1938 /// \tparam T1 algorithm information

1939 /// \tparam T2 keys used in the scheme

1940 /// \tparam T3 key agreement algorithm

1941 /// \tparam T4 key derivation algorithm

1942 /// \tparam T5 symmetric encryption algorithm

1943 template <class T1, class T2, class T3, class T4, class T5>
1944 struct DL_CryptoSchemeOptions : public DL_KeyedSchemeOptions<T1, T2>
1945 {
1946     typedef T3 KeyAgreementAlgorithm;
1947     typedef T4 KeyDerivationAlgorithm;
1948     typedef T5 SymmetricEncryptionAlgorithm;
1949 };
1950 
1951 /// \brief Discrete Log (DL) base object implementation

1952 /// \tparam BASE TODO

1953 /// \tparam SCHEME_OPTIONS options for the scheme

1954 /// \tparam KEY key used in the scheme

1955 template <class BASE, class SCHEME_OPTIONS, class KEY>
1956 class CRYPTOPP_NO_VTABLE DL_ObjectImplBase : public AlgorithmImpl<BASE, typename SCHEME_OPTIONS::AlgorithmInfo>
1957 {
1958 public:
1959     typedef SCHEME_OPTIONS SchemeOptions;
1960     typedef typename KEY::Element Element;
1961 
1962     virtual ~DL_ObjectImplBase() {}
1963 
1964     PrivateKey & AccessPrivateKey() {return m_key;}
1965     PublicKey & AccessPublicKey() {return m_key;}
1966 
1967     // KeyAccessor

1968     const KEY & GetKey() const {return m_key;}
1969     KEY & AccessKey() {return m_key;}
1970 
1971 protected:
1972     typename BASE::KeyInterface & AccessKeyInterface() {return m_key;}
1973     const typename BASE::KeyInterface & GetKeyInterface() const {return m_key;}
1974 
1975     // for signature scheme

1976     HashIdentifier GetHashIdentifier() const
1977     {
1978         typedef typename SchemeOptions::MessageEncodingMethod::HashIdentifierLookup HashLookup;
1979         return HashLookup::template HashIdentifierLookup2<typename SchemeOptions::HashFunction>::Lookup();
1980     }
1981     size_t GetDigestSize() const
1982     {
1983         typedef typename SchemeOptions::HashFunction H;
1984         return H::DIGESTSIZE;
1985     }
1986 
1987 private:
1988     KEY m_key;
1989 };
1990 
1991 /// \brief Discrete Log (DL) object implementation

1992 /// \tparam BASE TODO

1993 /// \tparam SCHEME_OPTIONS options for the scheme

1994 /// \tparam KEY key used in the scheme

1995 template <class BASE, class SCHEME_OPTIONS, class KEY>
1996 class CRYPTOPP_NO_VTABLE DL_ObjectImpl : public DL_ObjectImplBase<BASE, SCHEME_OPTIONS, KEY>
1997 {
1998 public:
1999     typedef typename KEY::Element Element;
2000 
2001     virtual ~DL_ObjectImpl() {}
2002 
2003 protected:
2004     const DL_ElgamalLikeSignatureAlgorithm<Element> & GetSignatureAlgorithm() const
2005         {return Singleton<typename SCHEME_OPTIONS::SignatureAlgorithm>().Ref();}
2006     const DL_KeyAgreementAlgorithm<Element> & GetKeyAgreementAlgorithm() const
2007         {return Singleton<typename SCHEME_OPTIONS::KeyAgreementAlgorithm>().Ref();}
2008     const DL_KeyDerivationAlgorithm<Element> & GetKeyDerivationAlgorithm() const
2009         {return Singleton<typename SCHEME_OPTIONS::KeyDerivationAlgorithm>().Ref();}
2010     const DL_SymmetricEncryptionAlgorithm & GetSymmetricEncryptionAlgorithm() const
2011         {return Singleton<typename SCHEME_OPTIONS::SymmetricEncryptionAlgorithm>().Ref();}
2012     HashIdentifier GetHashIdentifier() const
2013         {return HashIdentifier();}
2014     const PK_SignatureMessageEncodingMethod & GetMessageEncodingInterface() const
2015         {return Singleton<typename SCHEME_OPTIONS::MessageEncodingMethod>().Ref();}
2016 };
2017 
2018 /// \brief Discrete Log (DL) signer implementation

2019 /// \tparam SCHEME_OPTIONS options for the scheme

2020 template <class SCHEME_OPTIONS>
2021 class DL_SignerImpl : public DL_ObjectImpl<DL_SignerBase<typename SCHEME_OPTIONS::Element>, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PrivateKey>
2022 {
2023 public:
2024     PK_MessageAccumulator * NewSignatureAccumulator(RandomNumberGenerator &rng) const
2025     {
2026         member_ptr<PK_MessageAccumulatorBase> p(new PK_MessageAccumulatorImpl<typename SCHEME_OPTIONS::HashFunction>);
2027         this->RestartMessageAccumulator(rng, *p);
2028         return p.release();
2029     }
2030 };
2031 
2032 /// \brief Discrete Log (DL) verifier implementation

2033 /// \tparam SCHEME_OPTIONS options for the scheme

2034 template <class SCHEME_OPTIONS>
2035 class DL_VerifierImpl : public DL_ObjectImpl<DL_VerifierBase<typename SCHEME_OPTIONS::Element>, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PublicKey>
2036 {
2037 public:
2038     PK_MessageAccumulator * NewVerificationAccumulator() const
2039     {
2040         return new PK_MessageAccumulatorImpl<typename SCHEME_OPTIONS::HashFunction>;
2041     }
2042 };
2043 
2044 /// \brief Discrete Log (DL) encryptor implementation

2045 /// \tparam SCHEME_OPTIONS options for the scheme

2046 template <class SCHEME_OPTIONS>
2047 class DL_EncryptorImpl : public DL_ObjectImpl<DL_EncryptorBase<typename SCHEME_OPTIONS::Element>, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PublicKey>
2048 {
2049 };
2050 
2051 /// \brief Discrete Log (DL) decryptor implementation

2052 /// \tparam SCHEME_OPTIONS options for the scheme

2053 template <class SCHEME_OPTIONS>
2054 class DL_DecryptorImpl : public DL_ObjectImpl<DL_DecryptorBase<typename SCHEME_OPTIONS::Element>, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PrivateKey>
2055 {
2056 };
2057 
2058 // ********************************************************

2059 
2060 /// \brief Discrete Log (DL) simple key agreement base implementation

2061 /// \tparam T class or type

2062 template <class T>
2063 class CRYPTOPP_NO_VTABLE DL_SimpleKeyAgreementDomainBase : public SimpleKeyAgreementDomain
2064 {
2065 public:
2066     typedef T Element;
2067 
2068     virtual ~DL_SimpleKeyAgreementDomainBase() {}
2069 
2070     CryptoParameters & AccessCryptoParameters() {return AccessAbstractGroupParameters();}
2071     unsigned int AgreedValueLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(false);}
2072     unsigned int PrivateKeyLength() const {return GetAbstractGroupParameters().GetSubgroupOrder().ByteCount();}
2073     unsigned int PublicKeyLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(true);}
2074 
2075     void GeneratePrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
2076     {
2077         Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent());
2078         x.Encode(privateKey, PrivateKeyLength());
2079     }
2080 
2081     void GeneratePublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
2082     {
2083         CRYPTOPP_UNUSED(rng);
2084         const DL_GroupParameters<T> &params = GetAbstractGroupParameters();
2085         Integer x(privateKey, PrivateKeyLength());
2086         Element y = params.ExponentiateBase(x);
2087         params.EncodeElement(true, y, publicKey);
2088     }
2089 
2090     bool Agree(byte *agreedValue, const byte *privateKey, const byte *otherPublicKey, bool validateOtherPublicKey=true) const
2091     {
2092         try
2093         {
2094             const DL_GroupParameters<T> &params = GetAbstractGroupParameters();
2095             Integer x(privateKey, PrivateKeyLength());
2096             Element w = params.DecodeElement(otherPublicKey, validateOtherPublicKey);
2097 
2098             Element z = GetKeyAgreementAlgorithm().AgreeWithStaticPrivateKey(
2099                 GetAbstractGroupParameters(), w, validateOtherPublicKey, x);
2100             params.EncodeElement(false, z, agreedValue);
2101         }
2102         catch (DL_BadElement &)
2103         {
2104             return false;
2105         }
2106         return true;
2107     }
2108 
2109     /// \brief Retrieves a reference to the group generator

2110     /// \return const reference to the group generator

2111     const Element &GetGenerator() const {return GetAbstractGroupParameters().GetSubgroupGenerator();}
2112 
2113 protected:
2114     virtual const DL_KeyAgreementAlgorithm<Element> & GetKeyAgreementAlgorithm() const =0;
2115     virtual DL_GroupParameters<Element> & AccessAbstractGroupParameters() =0;
2116     const DL_GroupParameters<Element> & GetAbstractGroupParameters() const {return const_cast<DL_SimpleKeyAgreementDomainBase<Element> *>(this)->AccessAbstractGroupParameters();}
2117 };
2118 
2119 /// \brief Methods for avoiding "Small-Subgroup" attacks on Diffie-Hellman Key Agreement

2120 /// \details Additional methods exist and include public key validation and choice of prime p.

2121 /// \sa <A HREF="http://tools.ietf.org/html/rfc2785">Methods for Avoiding the "Small-Subgroup" Attacks on the

2122 ///  Diffie-Hellman Key Agreement Method for S/MIME</A>

2123 enum CofactorMultiplicationOption {
2124     /// \brief No cofactor multiplication applied

2125     NO_COFACTOR_MULTIPLICTION,
2126     /// \brief Cofactor multiplication compatible with ordinary Diffie-Hellman

2127     /// \details Modifies the computation of ZZ by including j (the cofactor) in the computations and is

2128     ///  compatible with ordinary Diffie-Hellman.

2129     COMPATIBLE_COFACTOR_MULTIPLICTION,
2130     /// \brief Cofactor multiplication incompatible with ordinary Diffie-Hellman

2131     /// \details Modifies the computation of ZZ by including j (the cofactor) in the computations but is

2132     ///  not compatible with ordinary Diffie-Hellman.

2133     INCOMPATIBLE_COFACTOR_MULTIPLICTION};
2134 
2135 typedef EnumToType<CofactorMultiplicationOption, NO_COFACTOR_MULTIPLICTION> NoCofactorMultiplication;
2136 typedef EnumToType<CofactorMultiplicationOption, COMPATIBLE_COFACTOR_MULTIPLICTION> CompatibleCofactorMultiplication;
2137 typedef EnumToType<CofactorMultiplicationOption, INCOMPATIBLE_COFACTOR_MULTIPLICTION> IncompatibleCofactorMultiplication;
2138 
2139 /// \brief Diffie-Hellman key agreement algorithm

2140 template <class ELEMENT, class COFACTOR_OPTION>
2141 class DL_KeyAgreementAlgorithm_DH : public DL_KeyAgreementAlgorithm<ELEMENT>
2142 {
2143 public:
2144     typedef ELEMENT Element;
2145 
2146     CRYPTOPP_STATIC_CONSTEXPR const char* CRYPTOPP_API StaticAlgorithmName()
2147         {return COFACTOR_OPTION::ToEnum() == INCOMPATIBLE_COFACTOR_MULTIPLICTION ? "DHC" : "DH";}
2148 
2149     virtual ~DL_KeyAgreementAlgorithm_DH() {}
2150 
2151     Element AgreeWithEphemeralPrivateKey(const DL_GroupParameters<Element> &params, const DL_FixedBasePrecomputation<Element> &publicPrecomputation, const Integer &privateExponent) const
2152     {
2153         return publicPrecomputation.Exponentiate(params.GetGroupPrecomputation(),
2154             COFACTOR_OPTION::ToEnum() == INCOMPATIBLE_COFACTOR_MULTIPLICTION ? privateExponent*params.GetCofactor() : privateExponent);
2155     }
2156 
2157     Element AgreeWithStaticPrivateKey(const DL_GroupParameters<Element> &params, const Element &publicElement, bool validateOtherPublicKey, const Integer &privateExponent) const
2158     {
2159         if (COFACTOR_OPTION::ToEnum() == COMPATIBLE_COFACTOR_MULTIPLICTION)
2160         {
2161             const Integer &k = params.GetCofactor();
2162             return params.ExponentiateElement(publicElement,
2163                 ModularArithmetic(params.GetSubgroupOrder()).Divide(privateExponent, k)*k);
2164         }
2165         else if (COFACTOR_OPTION::ToEnum() == INCOMPATIBLE_COFACTOR_MULTIPLICTION)
2166             return params.ExponentiateElement(publicElement, privateExponent*params.GetCofactor());
2167         else
2168         {
2169             CRYPTOPP_ASSERT(COFACTOR_OPTION::ToEnum() == NO_COFACTOR_MULTIPLICTION);
2170 
2171             if (!validateOtherPublicKey)
2172                 return params.ExponentiateElement(publicElement, privateExponent);
2173 
2174             if (params.FastSubgroupCheckAvailable())
2175             {
2176                 if (!params.ValidateElement(2, publicElement, NULLPTR))
2177                     throw DL_BadElement();
2178                 return params.ExponentiateElement(publicElement, privateExponent);
2179             }
2180             else
2181             {
2182                 const Integer e[2] = {params.GetSubgroupOrder(), privateExponent};
2183                 Element r[2];
2184                 params.SimultaneousExponentiate(r, publicElement, e, 2);
2185                 if (!params.IsIdentity(r[0]))
2186                     throw DL_BadElement();
2187                 return r[1];
2188             }
2189         }
2190     }
2191 };
2192 
2193 // ********************************************************

2194 
2195 /// \brief Template implementing constructors for public key algorithm classes

2196 template <class BASE>
2197 class CRYPTOPP_NO_VTABLE PK_FinalTemplate : public BASE
2198 {
2199 public:
2200     PK_FinalTemplate() {}
2201 
2202     PK_FinalTemplate(const CryptoMaterial &key)
2203         {this->AccessKey().AssignFrom(key);}
2204 
2205     PK_FinalTemplate(BufferedTransformation &bt)
2206         {this->AccessKey().BERDecode(bt);}
2207 
2208     PK_FinalTemplate(const AsymmetricAlgorithm &algorithm)
2209         {this->AccessKey().AssignFrom(algorithm.GetMaterial());}
2210 
2211     PK_FinalTemplate(const Integer &v1)
2212         {this->AccessKey().Initialize(v1);}
2213 
2214     template <class T1, class T2>
2215     PK_FinalTemplate(const T1 &v1, const T2 &v2)
2216         {this->AccessKey().Initialize(v1, v2);}
2217 
2218     template <class T1, class T2, class T3>
2219     PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3)
2220         {this->AccessKey().Initialize(v1, v2, v3);}
2221 
2222     template <class T1, class T2, class T3, class T4>
2223     PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4)
2224         {this->AccessKey().Initialize(v1, v2, v3, v4);}
2225 
2226     template <class T1, class T2, class T3, class T4, class T5>
2227     PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5)
2228         {this->AccessKey().Initialize(v1, v2, v3, v4, v5);}
2229 
2230     template <class T1, class T2, class T3, class T4, class T5, class T6>
2231     PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6)
2232         {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6);}
2233 
2234     template <class T1, class T2, class T3, class T4, class T5, class T6, class T7>
2235     PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7)
2236         {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7);}
2237 
2238     template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
2239     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)
2240         {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7, v8);}
2241 
2242     template <class T1, class T2>
2243     PK_FinalTemplate(T1 &v1, const T2 &v2)
2244         {this->AccessKey().Initialize(v1, v2);}
2245 
2246     template <class T1, class T2, class T3>
2247     PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3)
2248         {this->AccessKey().Initialize(v1, v2, v3);}
2249 
2250     template <class T1, class T2, class T3, class T4>
2251     PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4)
2252         {this->AccessKey().Initialize(v1, v2, v3, v4);}
2253 
2254     template <class T1, class T2, class T3, class T4, class T5>
2255     PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5)
2256         {this->AccessKey().Initialize(v1, v2, v3, v4, v5);}
2257 
2258     template <class T1, class T2, class T3, class T4, class T5, class T6>
2259     PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6)
2260         {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6);}
2261 
2262     template <class T1, class T2, class T3, class T4, class T5, class T6, class T7>
2263     PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7)
2264         {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7);}
2265 
2266     template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
2267     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)
2268         {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7, v8);}
2269 };
2270 
2271 /// \brief Base class for public key encryption standard classes.

2272 /// \details These classes are used to select from variants of algorithms.

2273 ///  Not all standards apply to all algorithms.

2274 struct EncryptionStandard {};
2275 
2276 /// \brief Base class for public key signature standard classes.

2277 /// \details These classes are used to select from variants of algorithms.

2278 ///  Not all standards apply to all algorithms.

2279 struct SignatureStandard {};
2280 
2281 /// \brief Trapdoor Function (TF) encryption scheme

2282 /// \tparam STANDARD standard

2283 /// \tparam KEYS keys used in the encryption scheme

2284 /// \tparam ALG_INFO algorithm information

2285 template <class KEYS, class STANDARD, class ALG_INFO>
2286 class TF_ES;
2287 
2288 template <class KEYS, class STANDARD, class ALG_INFO = TF_ES<KEYS, STANDARD, int> >
2289 class TF_ES : public KEYS
2290 {
2291     typedef typename STANDARD::EncryptionMessageEncodingMethod MessageEncodingMethod;
2292 
2293 public:
2294     /// see EncryptionStandard for a list of standards

2295     typedef STANDARD Standard;
2296     typedef TF_CryptoSchemeOptions<ALG_INFO, KEYS, MessageEncodingMethod> SchemeOptions;
2297 
2298     static std::string CRYPTOPP_API StaticAlgorithmName() {return std::string(KEYS::StaticAlgorithmName()) + "/" + MessageEncodingMethod::StaticAlgorithmName();}
2299 
2300     /// implements PK_Decryptor interface

2301     typedef PK_FinalTemplate<TF_DecryptorImpl<SchemeOptions> > Decryptor;
2302     /// implements PK_Encryptor interface

2303     typedef PK_FinalTemplate<TF_EncryptorImpl<SchemeOptions> > Encryptor;
2304 };
2305 
2306 /// \brief Trapdoor Function (TF) Signature Scheme

2307 /// \tparam STANDARD standard

2308 /// \tparam H hash function

2309 /// \tparam KEYS keys used in the signature scheme

2310 /// \tparam ALG_INFO algorithm information

2311 template <class KEYS, class STANDARD, class H, class ALG_INFO>
2312 class TF_SS;
2313 
2314 template <class KEYS, class STANDARD, class H, class ALG_INFO = TF_SS<KEYS, STANDARD, H, int> >
2315 class TF_SS : public KEYS
2316 {
2317 public:
2318     /// see SignatureStandard for a list of standards

2319     typedef STANDARD Standard;
2320     typedef typename Standard::SignatureMessageEncodingMethod MessageEncodingMethod;
2321     typedef TF_SignatureSchemeOptions<ALG_INFO, KEYS, MessageEncodingMethod, H> SchemeOptions;
2322 
2323     static std::string CRYPTOPP_API StaticAlgorithmName() {return std::string(KEYS::StaticAlgorithmName()) + "/" + MessageEncodingMethod::StaticAlgorithmName() + "(" + H::StaticAlgorithmName() + ")";}
2324 
2325     /// implements PK_Signer interface

2326     typedef PK_FinalTemplate<TF_SignerImpl<SchemeOptions> > Signer;
2327     /// implements PK_Verifier interface

2328     typedef PK_FinalTemplate<TF_VerifierImpl<SchemeOptions> > Verifier;
2329 };
2330 
2331 /// \brief Discrete Log (DL) signature scheme

2332 /// \tparam KEYS keys used in the signature scheme

2333 /// \tparam SA signature algorithm

2334 /// \tparam MEM message encoding method

2335 /// \tparam H hash function

2336 /// \tparam ALG_INFO algorithm information

2337 template <class KEYS, class SA, class MEM, class H, class ALG_INFO>
2338 class DL_SS;
2339 
2340 template <class KEYS, class SA, class MEM, class H, class ALG_INFO = DL_SS<KEYS, SA, MEM, H, int> >
2341 class DL_SS : public KEYS
2342 {
2343     typedef DL_SignatureSchemeOptions<ALG_INFO, KEYS, SA, MEM, H> SchemeOptions;
2344 
2345 public:
2346     static std::string StaticAlgorithmName() {return SA::StaticAlgorithmName() + std::string("/EMSA1(") + H::StaticAlgorithmName() + ")";}
2347 
2348     /// implements PK_Signer interface

2349     typedef PK_FinalTemplate<DL_SignerImpl<SchemeOptions> > Signer;
2350     /// implements PK_Verifier interface

2351     typedef PK_FinalTemplate<DL_VerifierImpl<SchemeOptions> > Verifier;
2352 };
2353 
2354 /// \brief Discrete Log (DL) encryption scheme

2355 /// \tparam KEYS keys used in the encryption scheme

2356 /// \tparam AA key agreement algorithm

2357 /// \tparam DA key derivation algorithm

2358 /// \tparam EA encryption algorithm

2359 /// \tparam ALG_INFO algorithm information

2360 template <class KEYS, class AA, class DA, class EA, class ALG_INFO>
2361 class DL_ES : public KEYS
2362 {
2363     typedef DL_CryptoSchemeOptions<ALG_INFO, KEYS, AA, DA, EA> SchemeOptions;
2364 
2365 public:
2366     /// implements PK_Decryptor interface

2367     typedef PK_FinalTemplate<DL_DecryptorImpl<SchemeOptions> > Decryptor;
2368     /// implements PK_Encryptor interface

2369     typedef PK_FinalTemplate<DL_EncryptorImpl<SchemeOptions> > Encryptor;
2370 };
2371 
2372 NAMESPACE_END
2373 
2374 #if CRYPTOPP_MSC_VERSION
2375 # pragma warning(pop)
2376 #endif
2377 
2378 #endif