1// pubkey.h - written and placed in the public domain by Wei Dai
2
3#ifndef CRYPTOPP_PUBKEY_H
4#define CRYPTOPP_PUBKEY_H
5
6/** \file
7
8	This file contains helper classes/functions for implementing public key algorithms.
9
10	The class hierachies in this .h file tend to look like this:
11<pre>
12                  x1
13                 / \
14                y1  z1
15                 |  |
16            x2<y1>  x2<z1>
17                 |  |
18                y2  z2
19                 |  |
20            x3<y2>  x3<z2>
21                 |  |
22                y3  z3
23</pre>
24	- x1, y1, z1 are abstract interface classes defined in cryptlib.h
25	- x2, y2, z2 are implementations of the interfaces using "abstract policies", which
26	  are pure virtual functions that should return interfaces to interchangeable algorithms.
27	  These classes have "Base" suffixes.
28	- x3, y3, z3 hold actual algorithms and implement those virtual functions.
29	  These classes have "Impl" suffixes.
30
31	The "TF_" prefix means an implementation using trapdoor functions on integers.
32	The "DL_" prefix means an implementation using group operations (in groups where discrete log is hard).
33*/
34
35#include "modarith.h"
36#include "filters.h"
37#include "eprecomp.h"
38#include "fips140.h"
39#include "argnames.h"
40#include <memory>
41
42// VC60 workaround: this macro is defined in shlobj.h and conflicts with a template parameter used in this file
43#undef INTERFACE
44
45NAMESPACE_BEGIN(CryptoPP)
46
47//! _
48class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TrapdoorFunctionBounds
49{
50public:
51	virtual ~TrapdoorFunctionBounds() {}
52
53	virtual Integer PreimageBound() const =0;
54	virtual Integer ImageBound() const =0;
55	virtual Integer MaxPreimage() const {return --PreimageBound();}
56	virtual Integer MaxImage() const {return --ImageBound();}
57};
58
59//! _
60class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE RandomizedTrapdoorFunction : public TrapdoorFunctionBounds
61{
62public:
63	virtual Integer ApplyRandomizedFunction(RandomNumberGenerator &rng, const Integer &x) const =0;
64	virtual bool IsRandomized() const {return true;}
65};
66
67//! _
68class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TrapdoorFunction : public RandomizedTrapdoorFunction
69{
70public:
71	Integer ApplyRandomizedFunction(RandomNumberGenerator &rng, const Integer &x) const
72		{return ApplyFunction(x);}
73	bool IsRandomized() const {return false;}
74
75	virtual Integer ApplyFunction(const Integer &x) const =0;
76};
77
78//! _
79class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE RandomizedTrapdoorFunctionInverse
80{
81public:
82	virtual ~RandomizedTrapdoorFunctionInverse() {}
83
84	virtual Integer CalculateRandomizedInverse(RandomNumberGenerator &rng, const Integer &x) const =0;
85	virtual bool IsRandomized() const {return true;}
86};
87
88//! _
89class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TrapdoorFunctionInverse : public RandomizedTrapdoorFunctionInverse
90{
91public:
92	virtual ~TrapdoorFunctionInverse() {}
93
94	Integer CalculateRandomizedInverse(RandomNumberGenerator &rng, const Integer &x) const
95		{return CalculateInverse(rng, x);}
96	bool IsRandomized() const {return false;}
97
98	virtual Integer CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const =0;
99};
100
101// ********************************************************
102
103//! message encoding method for public key encryption
104class CRYPTOPP_NO_VTABLE PK_EncryptionMessageEncodingMethod
105{
106public:
107	virtual ~PK_EncryptionMessageEncodingMethod() {}
108
109	virtual bool ParameterSupported(const char *name) const {return false;}
110
111	//! max size of unpadded message in bytes, given max size of padded message in bits (1 less than size of modulus)
112	virtual size_t MaxUnpaddedLength(size_t paddedLength) const =0;
113
114	virtual void Pad(RandomNumberGenerator &rng, const byte *raw, size_t inputLength, byte *padded, size_t paddedBitLength, const NameValuePairs &parameters) const =0;
115
116	virtual DecodingResult Unpad(const byte *padded, size_t paddedBitLength, byte *raw, const NameValuePairs &parameters) const =0;
117};
118
119// ********************************************************
120
121//! _
122template <class TFI, class MEI>
123class CRYPTOPP_NO_VTABLE TF_Base
124{
125protected:
126	virtual const TrapdoorFunctionBounds & GetTrapdoorFunctionBounds() const =0;
127
128	typedef TFI TrapdoorFunctionInterface;
129	virtual const TrapdoorFunctionInterface & GetTrapdoorFunctionInterface() const =0;
130
131	typedef MEI MessageEncodingInterface;
132	virtual const MessageEncodingInterface & GetMessageEncodingInterface() const =0;
133};
134
135// ********************************************************
136
137//! _
138template <class BASE>
139class CRYPTOPP_NO_VTABLE PK_FixedLengthCryptoSystemImpl : public BASE
140{
141public:
142	size_t MaxPlaintextLength(size_t ciphertextLength) const
143		{return ciphertextLength == FixedCiphertextLength() ? FixedMaxPlaintextLength() : 0;}
144	size_t CiphertextLength(size_t plaintextLength) const
145		{return plaintextLength <= FixedMaxPlaintextLength() ? FixedCiphertextLength() : 0;}
146
147	virtual size_t FixedMaxPlaintextLength() const =0;
148	virtual size_t FixedCiphertextLength() const =0;
149};
150
151//! _
152template <class INTERFACE, class BASE>
153class CRYPTOPP_NO_VTABLE TF_CryptoSystemBase : public PK_FixedLengthCryptoSystemImpl<INTERFACE>, protected BASE
154{
155public:
156	bool ParameterSupported(const char *name) const {return this->GetMessageEncodingInterface().ParameterSupported(name);}
157	size_t FixedMaxPlaintextLength() const {return this->GetMessageEncodingInterface().MaxUnpaddedLength(PaddedBlockBitLength());}
158	size_t FixedCiphertextLength() const {return this->GetTrapdoorFunctionBounds().MaxImage().ByteCount();}
159
160protected:
161	size_t PaddedBlockByteLength() const {return BitsToBytes(PaddedBlockBitLength());}
162	size_t PaddedBlockBitLength() const {return this->GetTrapdoorFunctionBounds().PreimageBound().BitCount()-1;}
163};
164
165//! _
166class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_DecryptorBase : public TF_CryptoSystemBase<PK_Decryptor, TF_Base<TrapdoorFunctionInverse, PK_EncryptionMessageEncodingMethod> >
167{
168public:
169	DecodingResult Decrypt(RandomNumberGenerator &rng, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs &parameters = g_nullNameValuePairs) const;
170};
171
172//! _
173class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_EncryptorBase : public TF_CryptoSystemBase<PK_Encryptor, TF_Base<RandomizedTrapdoorFunction, PK_EncryptionMessageEncodingMethod> >
174{
175public:
176	void Encrypt(RandomNumberGenerator &rng, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs &parameters = g_nullNameValuePairs) const;
177};
178
179// ********************************************************
180
181typedef std::pair<const byte *, size_t> HashIdentifier;
182
183//! interface for message encoding method for public key signature schemes
184class CRYPTOPP_NO_VTABLE PK_SignatureMessageEncodingMethod
185{
186public:
187	virtual ~PK_SignatureMessageEncodingMethod() {}
188
189	virtual size_t MinRepresentativeBitLength(size_t hashIdentifierLength, size_t digestLength) const
190		{return 0;}
191	virtual size_t MaxRecoverableLength(size_t representativeBitLength, size_t hashIdentifierLength, size_t digestLength) const
192		{return 0;}
193
194	bool IsProbabilistic() const
195		{return true;}
196	bool AllowNonrecoverablePart() const
197		{throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");}
198	virtual bool RecoverablePartFirst() const
199		{throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");}
200
201	// for verification, DL
202	virtual void ProcessSemisignature(HashTransformation &hash, const byte *semisignature, size_t semisignatureLength) const {}
203
204	// for signature
205	virtual void ProcessRecoverableMessage(HashTransformation &hash,
206		const byte *recoverableMessage, size_t recoverableMessageLength,
207		const byte *presignature, size_t presignatureLength,
208		SecByteBlock &semisignature) const
209	{
210		if (RecoverablePartFirst())
211			assert(!"ProcessRecoverableMessage() not implemented");
212	}
213
214	virtual void ComputeMessageRepresentative(RandomNumberGenerator &rng,
215		const byte *recoverableMessage, size_t recoverableMessageLength,
216		HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
217		byte *representative, size_t representativeBitLength) const =0;
218
219	virtual bool VerifyMessageRepresentative(
220		HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
221		byte *representative, size_t representativeBitLength) const =0;
222
223	virtual DecodingResult RecoverMessageFromRepresentative(	// for TF
224		HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
225		byte *representative, size_t representativeBitLength,
226		byte *recoveredMessage) const
227		{throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");}
228
229	virtual DecodingResult RecoverMessageFromSemisignature(		// for DL
230		HashTransformation &hash, HashIdentifier hashIdentifier,
231		const byte *presignature, size_t presignatureLength,
232		const byte *semisignature, size_t semisignatureLength,
233		byte *recoveredMessage) const
234		{throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");}
235
236	// VC60 workaround
237	struct HashIdentifierLookup
238	{
239		template <class H> struct HashIdentifierLookup2
240		{
241			static HashIdentifier CRYPTOPP_API Lookup()
242			{
243				return HashIdentifier(NULL, 0);
244			}
245		};
246	};
247};
248
249class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_DeterministicSignatureMessageEncodingMethod : public PK_SignatureMessageEncodingMethod
250{
251public:
252	bool VerifyMessageRepresentative(
253		HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
254		byte *representative, size_t representativeBitLength) const;
255};
256
257class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_RecoverableSignatureMessageEncodingMethod : public PK_SignatureMessageEncodingMethod
258{
259public:
260	bool VerifyMessageRepresentative(
261		HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
262		byte *representative, size_t representativeBitLength) const;
263};
264
265class CRYPTOPP_DLL DL_SignatureMessageEncodingMethod_DSA : public PK_DeterministicSignatureMessageEncodingMethod
266{
267public:
268	void ComputeMessageRepresentative(RandomNumberGenerator &rng,
269		const byte *recoverableMessage, size_t recoverableMessageLength,
270		HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
271		byte *representative, size_t representativeBitLength) const;
272};
273
274class CRYPTOPP_DLL DL_SignatureMessageEncodingMethod_NR : public PK_DeterministicSignatureMessageEncodingMethod
275{
276public:
277	void ComputeMessageRepresentative(RandomNumberGenerator &rng,
278		const byte *recoverableMessage, size_t recoverableMessageLength,
279		HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
280		byte *representative, size_t representativeBitLength) const;
281};
282
283class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_MessageAccumulatorBase : public PK_MessageAccumulator
284{
285public:
286	PK_MessageAccumulatorBase() : m_empty(true) {}
287
288	virtual HashTransformation & AccessHash() =0;
289
290	void Update(const byte *input, size_t length)
291	{
292		AccessHash().Update(input, length);
293		m_empty = m_empty && length == 0;
294	}
295
296	SecByteBlock m_recoverableMessage, m_representative, m_presignature, m_semisignature;
297	Integer m_k, m_s;
298	bool m_empty;
299};
300
301template <class HASH_ALGORITHM>
302class PK_MessageAccumulatorImpl : public PK_MessageAccumulatorBase, protected ObjectHolder<HASH_ALGORITHM>
303{
304public:
305	HashTransformation & AccessHash() {return this->m_object;}
306};
307
308//! _
309template <class INTERFACE, class BASE>
310class CRYPTOPP_NO_VTABLE TF_SignatureSchemeBase : public INTERFACE, protected BASE
311{
312public:
313	size_t SignatureLength() const
314		{return this->GetTrapdoorFunctionBounds().MaxPreimage().ByteCount();}
315	size_t MaxRecoverableLength() const
316		{return this->GetMessageEncodingInterface().MaxRecoverableLength(MessageRepresentativeBitLength(), GetHashIdentifier().second, GetDigestSize());}
317	size_t MaxRecoverableLengthFromSignatureLength(size_t signatureLength) const
318		{return this->MaxRecoverableLength();}
319
320	bool IsProbabilistic() const
321		{return this->GetTrapdoorFunctionInterface().IsRandomized() || this->GetMessageEncodingInterface().IsProbabilistic();}
322	bool AllowNonrecoverablePart() const
323		{return this->GetMessageEncodingInterface().AllowNonrecoverablePart();}
324	bool RecoverablePartFirst() const
325		{return this->GetMessageEncodingInterface().RecoverablePartFirst();}
326
327protected:
328	size_t MessageRepresentativeLength() const {return BitsToBytes(MessageRepresentativeBitLength());}
329	size_t MessageRepresentativeBitLength() const {return this->GetTrapdoorFunctionBounds().ImageBound().BitCount()-1;}
330	virtual HashIdentifier GetHashIdentifier() const =0;
331	virtual size_t GetDigestSize() const =0;
332};
333
334//! _
335class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_SignerBase : public TF_SignatureSchemeBase<PK_Signer, TF_Base<RandomizedTrapdoorFunctionInverse, PK_SignatureMessageEncodingMethod> >
336{
337public:
338	void InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, size_t recoverableMessageLength) const;
339	size_t SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart=true) const;
340};
341
342//! _
343class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_VerifierBase : public TF_SignatureSchemeBase<PK_Verifier, TF_Base<TrapdoorFunction, PK_SignatureMessageEncodingMethod> >
344{
345public:
346	void InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, size_t signatureLength) const;
347	bool VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const;
348	DecodingResult RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &recoveryAccumulator) const;
349};
350
351// ********************************************************
352
353//! _
354template <class T1, class T2, class T3>
355struct TF_CryptoSchemeOptions
356{
357	typedef T1 AlgorithmInfo;
358	typedef T2 Keys;
359	typedef typename Keys::PrivateKey PrivateKey;
360	typedef typename Keys::PublicKey PublicKey;
361	typedef T3 MessageEncodingMethod;
362};
363
364//! _
365template <class T1, class T2, class T3, class T4>
366struct TF_SignatureSchemeOptions : public TF_CryptoSchemeOptions<T1, T2, T3>
367{
368	typedef T4 HashFunction;
369};
370
371//! _
372template <class BASE, class SCHEME_OPTIONS, class KEY_CLASS>
373class CRYPTOPP_NO_VTABLE TF_ObjectImplBase : public AlgorithmImpl<BASE, typename SCHEME_OPTIONS::AlgorithmInfo>
374{
375public:
376	typedef SCHEME_OPTIONS SchemeOptions;
377	typedef KEY_CLASS KeyClass;
378
379	PublicKey & AccessPublicKey() {return AccessKey();}
380	const PublicKey & GetPublicKey() const {return GetKey();}
381
382	PrivateKey & AccessPrivateKey() {return AccessKey();}
383	const PrivateKey & GetPrivateKey() const {return GetKey();}
384
385	virtual const KeyClass & GetKey() const =0;
386	virtual KeyClass & AccessKey() =0;
387
388	const KeyClass & GetTrapdoorFunction() const {return GetKey();}
389
390	PK_MessageAccumulator * NewSignatureAccumulator(RandomNumberGenerator &rng) const
391	{
392		return new PK_MessageAccumulatorImpl<CPP_TYPENAME SCHEME_OPTIONS::HashFunction>;
393	}
394	PK_MessageAccumulator * NewVerificationAccumulator() const
395	{
396		return new PK_MessageAccumulatorImpl<CPP_TYPENAME SCHEME_OPTIONS::HashFunction>;
397	}
398
399protected:
400	const typename BASE::MessageEncodingInterface & GetMessageEncodingInterface() const
401		{return Singleton<CPP_TYPENAME SCHEME_OPTIONS::MessageEncodingMethod>().Ref();}
402	const TrapdoorFunctionBounds & GetTrapdoorFunctionBounds() const
403		{return GetKey();}
404	const typename BASE::TrapdoorFunctionInterface & GetTrapdoorFunctionInterface() const
405		{return GetKey();}
406
407	// for signature scheme
408	HashIdentifier GetHashIdentifier() const
409	{
410        typedef CPP_TYPENAME SchemeOptions::MessageEncodingMethod::HashIdentifierLookup::template HashIdentifierLookup2<CPP_TYPENAME SchemeOptions::HashFunction> L;
411        return L::Lookup();
412	}
413	size_t GetDigestSize() const
414	{
415		typedef CPP_TYPENAME SchemeOptions::HashFunction H;
416		return H::DIGESTSIZE;
417	}
418};
419
420//! _
421template <class BASE, class SCHEME_OPTIONS, class KEY>
422class TF_ObjectImplExtRef : public TF_ObjectImplBase<BASE, SCHEME_OPTIONS, KEY>
423{
424public:
425	TF_ObjectImplExtRef(const KEY *pKey = NULL) : m_pKey(pKey) {}
426	void SetKeyPtr(const KEY *pKey) {m_pKey = pKey;}
427
428	const KEY & GetKey() const {return *m_pKey;}
429	KEY & AccessKey() {throw NotImplemented("TF_ObjectImplExtRef: cannot modify refererenced key");}
430
431private:
432	const KEY * m_pKey;
433};
434
435//! _
436template <class BASE, class SCHEME_OPTIONS, class KEY_CLASS>
437class CRYPTOPP_NO_VTABLE TF_ObjectImpl : public TF_ObjectImplBase<BASE, SCHEME_OPTIONS, KEY_CLASS>
438{
439public:
440	typedef KEY_CLASS KeyClass;
441
442	const KeyClass & GetKey() const {return m_trapdoorFunction;}
443	KeyClass & AccessKey() {return m_trapdoorFunction;}
444
445private:
446	KeyClass m_trapdoorFunction;
447};
448
449//! _
450template <class SCHEME_OPTIONS>
451class TF_DecryptorImpl : public TF_ObjectImpl<TF_DecryptorBase, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PrivateKey>
452{
453};
454
455//! _
456template <class SCHEME_OPTIONS>
457class TF_EncryptorImpl : public TF_ObjectImpl<TF_EncryptorBase, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PublicKey>
458{
459};
460
461//! _
462template <class SCHEME_OPTIONS>
463class TF_SignerImpl : public TF_ObjectImpl<TF_SignerBase, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PrivateKey>
464{
465};
466
467//! _
468template <class SCHEME_OPTIONS>
469class TF_VerifierImpl : public TF_ObjectImpl<TF_VerifierBase, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PublicKey>
470{
471};
472
473// ********************************************************
474
475//! _
476class CRYPTOPP_NO_VTABLE MaskGeneratingFunction
477{
478public:
479	virtual ~MaskGeneratingFunction() {}
480	virtual void GenerateAndMask(HashTransformation &hash, byte *output, size_t outputLength, const byte *input, size_t inputLength, bool mask = true) const =0;
481};
482
483CRYPTOPP_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);
484
485//! _
486class P1363_MGF1 : public MaskGeneratingFunction
487{
488public:
489	static const char * CRYPTOPP_API StaticAlgorithmName() {return "MGF1";}
490	void GenerateAndMask(HashTransformation &hash, byte *output, size_t outputLength, const byte *input, size_t inputLength, bool mask = true) const
491	{
492		P1363_MGF1KDF2_Common(hash, output, outputLength, input, inputLength, NULL, 0, mask, 0);
493	}
494};
495
496// ********************************************************
497
498//! _
499template <class H>
500class P1363_KDF2
501{
502public:
503	static void CRYPTOPP_API DeriveKey(byte *output, size_t outputLength, const byte *input, size_t inputLength, const byte *derivationParams, size_t derivationParamsLength)
504	{
505		H h;
506		P1363_MGF1KDF2_Common(h, output, outputLength, input, inputLength, derivationParams, derivationParamsLength, false, 1);
507	}
508};
509
510// ********************************************************
511
512//! to be thrown by DecodeElement and AgreeWithStaticPrivateKey
513class DL_BadElement : public InvalidDataFormat
514{
515public:
516	DL_BadElement() : InvalidDataFormat("CryptoPP: invalid group element") {}
517};
518
519//! interface for DL group parameters
520template <class T>
521class CRYPTOPP_NO_VTABLE DL_GroupParameters : public CryptoParameters
522{
523	typedef DL_GroupParameters<T> ThisClass;
524
525public:
526	typedef T Element;
527
528	DL_GroupParameters() : m_validationLevel(0) {}
529
530	// CryptoMaterial
531	bool Validate(RandomNumberGenerator &rng, unsigned int level) const
532	{
533		if (!GetBasePrecomputation().IsInitialized())
534			return false;
535
536		if (m_validationLevel > level)
537			return true;
538
539		bool pass = ValidateGroup(rng, level);
540		pass = pass && ValidateElement(level, GetSubgroupGenerator(), &GetBasePrecomputation());
541
542		m_validationLevel = pass ? level+1 : 0;
543
544		return pass;
545	}
546
547	bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
548	{
549		return GetValueHelper(this, name, valueType, pValue)
550			CRYPTOPP_GET_FUNCTION_ENTRY(SubgroupOrder)
551			CRYPTOPP_GET_FUNCTION_ENTRY(SubgroupGenerator)
552			;
553	}
554
555	bool SupportsPrecomputation() const {return true;}
556
557	void Precompute(unsigned int precomputationStorage=16)
558	{
559		AccessBasePrecomputation().Precompute(GetGroupPrecomputation(), GetSubgroupOrder().BitCount(), precomputationStorage);
560	}
561
562	void LoadPrecomputation(BufferedTransformation &storedPrecomputation)
563	{
564		AccessBasePrecomputation().Load(GetGroupPrecomputation(), storedPrecomputation);
565		m_validationLevel = 0;
566	}
567
568	void SavePrecomputation(BufferedTransformation &storedPrecomputation) const
569	{
570		GetBasePrecomputation().Save(GetGroupPrecomputation(), storedPrecomputation);
571	}
572
573	// non-inherited
574	virtual const Element & GetSubgroupGenerator() const {return GetBasePrecomputation().GetBase(GetGroupPrecomputation());}
575	virtual void SetSubgroupGenerator(const Element &base) {AccessBasePrecomputation().SetBase(GetGroupPrecomputation(), base);}
576	virtual Element ExponentiateBase(const Integer &exponent) const
577	{
578		return GetBasePrecomputation().Exponentiate(GetGroupPrecomputation(), exponent);
579	}
580	virtual Element ExponentiateElement(const Element &base, const Integer &exponent) const
581	{
582		Element result;
583		SimultaneousExponentiate(&result, base, &exponent, 1);
584		return result;
585	}
586
587	virtual const DL_GroupPrecomputation<Element> & GetGroupPrecomputation() const =0;
588	virtual const DL_FixedBasePrecomputation<Element> & GetBasePrecomputation() const =0;
589	virtual DL_FixedBasePrecomputation<Element> & AccessBasePrecomputation() =0;
590	virtual const Integer & GetSubgroupOrder() const =0;	// order of subgroup generated by base element
591	virtual Integer GetMaxExponent() const =0;
592	virtual Integer GetGroupOrder() const {return GetSubgroupOrder()*GetCofactor();}	// one of these two needs to be overriden
593	virtual Integer GetCofactor() const {return GetGroupOrder()/GetSubgroupOrder();}
594	virtual unsigned int GetEncodedElementSize(bool reversible) const =0;
595	virtual void EncodeElement(bool reversible, const Element &element, byte *encoded) const =0;
596	virtual Element DecodeElement(const byte *encoded, bool checkForGroupMembership) const =0;
597	virtual Integer ConvertElementToInteger(const Element &element) const =0;
598	virtual bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const =0;
599	virtual bool ValidateElement(unsigned int level, const Element &element, const DL_FixedBasePrecomputation<Element> *precomp) const =0;
600	virtual bool FastSubgroupCheckAvailable() const =0;
601	virtual bool IsIdentity(const Element &element) const =0;
602	virtual void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const =0;
603
604protected:
605	void ParametersChanged() {m_validationLevel = 0;}
606
607private:
608	mutable unsigned int m_validationLevel;
609};
610
611//! _
612template <class GROUP_PRECOMP, class BASE_PRECOMP = DL_FixedBasePrecomputationImpl<CPP_TYPENAME GROUP_PRECOMP::Element>, class BASE = DL_GroupParameters<CPP_TYPENAME GROUP_PRECOMP::Element> >
613class DL_GroupParametersImpl : public BASE
614{
615public:
616	typedef GROUP_PRECOMP GroupPrecomputation;
617	typedef typename GROUP_PRECOMP::Element Element;
618	typedef BASE_PRECOMP BasePrecomputation;
619
620	const DL_GroupPrecomputation<Element> & GetGroupPrecomputation() const {return m_groupPrecomputation;}
621	const DL_FixedBasePrecomputation<Element> & GetBasePrecomputation() const {return m_gpc;}
622	DL_FixedBasePrecomputation<Element> & AccessBasePrecomputation() {return m_gpc;}
623
624protected:
625	GROUP_PRECOMP m_groupPrecomputation;
626	BASE_PRECOMP m_gpc;
627};
628
629//! _
630template <class T>
631class CRYPTOPP_NO_VTABLE DL_Key
632{
633public:
634	virtual const DL_GroupParameters<T> & GetAbstractGroupParameters() const =0;
635	virtual DL_GroupParameters<T> & AccessAbstractGroupParameters() =0;
636};
637
638//! interface for DL public keys
639template <class T>
640class CRYPTOPP_NO_VTABLE DL_PublicKey : public DL_Key<T>
641{
642	typedef DL_PublicKey<T> ThisClass;
643
644public:
645	typedef T Element;
646
647	bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
648	{
649		return GetValueHelper(this, name, valueType, pValue, &this->GetAbstractGroupParameters())
650				CRYPTOPP_GET_FUNCTION_ENTRY(PublicElement);
651	}
652
653	void AssignFrom(const NameValuePairs &source);
654
655	// non-inherited
656	virtual const Element & GetPublicElement() const {return GetPublicPrecomputation().GetBase(this->GetAbstractGroupParameters().GetGroupPrecomputation());}
657	virtual void SetPublicElement(const Element &y) {AccessPublicPrecomputation().SetBase(this->GetAbstractGroupParameters().GetGroupPrecomputation(), y);}
658	virtual Element ExponentiatePublicElement(const Integer &exponent) const
659	{
660		const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
661		return GetPublicPrecomputation().Exponentiate(params.GetGroupPrecomputation(), exponent);
662	}
663	virtual Element CascadeExponentiateBaseAndPublicElement(const Integer &baseExp, const Integer &publicExp) const
664	{
665		const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
666		return params.GetBasePrecomputation().CascadeExponentiate(params.GetGroupPrecomputation(), baseExp, GetPublicPrecomputation(), publicExp);
667	}
668
669	virtual const DL_FixedBasePrecomputation<T> & GetPublicPrecomputation() const =0;
670	virtual DL_FixedBasePrecomputation<T> & AccessPublicPrecomputation() =0;
671};
672
673//! interface for DL private keys
674template <class T>
675class CRYPTOPP_NO_VTABLE DL_PrivateKey : public DL_Key<T>
676{
677	typedef DL_PrivateKey<T> ThisClass;
678
679public:
680	typedef T Element;
681
682	void MakePublicKey(DL_PublicKey<T> &pub) const
683	{
684		pub.AccessAbstractGroupParameters().AssignFrom(this->GetAbstractGroupParameters());
685		pub.SetPublicElement(this->GetAbstractGroupParameters().ExponentiateBase(GetPrivateExponent()));
686	}
687
688	bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
689	{
690		return GetValueHelper(this, name, valueType, pValue, &this->GetAbstractGroupParameters())
691				CRYPTOPP_GET_FUNCTION_ENTRY(PrivateExponent);
692	}
693
694	void AssignFrom(const NameValuePairs &source)
695	{
696		this->AccessAbstractGroupParameters().AssignFrom(source);
697		AssignFromHelper(this, source)
698			CRYPTOPP_SET_FUNCTION_ENTRY(PrivateExponent);
699	}
700
701	virtual const Integer & GetPrivateExponent() const =0;
702	virtual void SetPrivateExponent(const Integer &x) =0;
703};
704
705template <class T>
706void DL_PublicKey<T>::AssignFrom(const NameValuePairs &source)
707{
708	DL_PrivateKey<T> *pPrivateKey = NULL;
709	if (source.GetThisPointer(pPrivateKey))
710		pPrivateKey->MakePublicKey(*this);
711	else
712	{
713		this->AccessAbstractGroupParameters().AssignFrom(source);
714		AssignFromHelper(this, source)
715			CRYPTOPP_SET_FUNCTION_ENTRY(PublicElement);
716	}
717}
718
719class OID;
720
721//! _
722template <class PK, class GP, class O = OID>
723class DL_KeyImpl : public PK
724{
725public:
726	typedef GP GroupParameters;
727
728	O GetAlgorithmID() const {return GetGroupParameters().GetAlgorithmID();}
729//	void BERDecode(BufferedTransformation &bt)
730//		{PK::BERDecode(bt);}
731//	void DEREncode(BufferedTransformation &bt) const
732//		{PK::DEREncode(bt);}
733	bool BERDecodeAlgorithmParameters(BufferedTransformation &bt)
734		{AccessGroupParameters().BERDecode(bt); return true;}
735	bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const
736		{GetGroupParameters().DEREncode(bt); return true;}
737
738	const GP & GetGroupParameters() const {return m_groupParameters;}
739	GP & AccessGroupParameters() {return m_groupParameters;}
740
741private:
742	GP m_groupParameters;
743};
744
745class X509PublicKey;
746class PKCS8PrivateKey;
747
748//! _
749template <class GP>
750class DL_PrivateKeyImpl : public DL_PrivateKey<CPP_TYPENAME GP::Element>, public DL_KeyImpl<PKCS8PrivateKey, GP>
751{
752public:
753	typedef typename GP::Element Element;
754
755	// GeneratableCryptoMaterial
756	bool Validate(RandomNumberGenerator &rng, unsigned int level) const
757	{
758		bool pass = GetAbstractGroupParameters().Validate(rng, level);
759
760		const Integer &q = GetAbstractGroupParameters().GetSubgroupOrder();
761		const Integer &x = GetPrivateExponent();
762
763		pass = pass && x.IsPositive() && x < q;
764		if (level >= 1)
765			pass = pass && Integer::Gcd(x, q) == Integer::One();
766		return pass;
767	}
768
769	bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
770	{
771		return GetValueHelper<DL_PrivateKey<Element> >(this, name, valueType, pValue).Assignable();
772	}
773
774	void AssignFrom(const NameValuePairs &source)
775	{
776		AssignFromHelper<DL_PrivateKey<Element> >(this, source);
777	}
778
779	void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &params)
780	{
781		if (!params.GetThisObject(this->AccessGroupParameters()))
782			this->AccessGroupParameters().GenerateRandom(rng, params);
783//		std::pair<const byte *, int> seed;
784		Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent());
785//			Integer::ANY, Integer::Zero(), Integer::One(),
786//			params.GetValue("DeterministicKeyGenerationSeed", seed) ? &seed : NULL);
787		SetPrivateExponent(x);
788	}
789
790	bool SupportsPrecomputation() const {return true;}
791
792	void Precompute(unsigned int precomputationStorage=16)
793		{AccessAbstractGroupParameters().Precompute(precomputationStorage);}
794
795	void LoadPrecomputation(BufferedTransformation &storedPrecomputation)
796		{AccessAbstractGroupParameters().LoadPrecomputation(storedPrecomputation);}
797
798	void SavePrecomputation(BufferedTransformation &storedPrecomputation) const
799		{GetAbstractGroupParameters().SavePrecomputation(storedPrecomputation);}
800
801	// DL_Key
802	const DL_GroupParameters<Element> & GetAbstractGroupParameters() const {return this->GetGroupParameters();}
803	DL_GroupParameters<Element> & AccessAbstractGroupParameters() {return this->AccessGroupParameters();}
804
805	// DL_PrivateKey
806	const Integer & GetPrivateExponent() const {return m_x;}
807	void SetPrivateExponent(const Integer &x) {m_x = x;}
808
809	// PKCS8PrivateKey
810	void BERDecodePrivateKey(BufferedTransformation &bt, bool, size_t)
811		{m_x.BERDecode(bt);}
812	void DEREncodePrivateKey(BufferedTransformation &bt) const
813		{m_x.DEREncode(bt);}
814
815private:
816	Integer m_x;
817};
818
819//! _
820template <class BASE, class SIGNATURE_SCHEME>
821class DL_PrivateKey_WithSignaturePairwiseConsistencyTest : public BASE
822{
823public:
824	void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &params)
825	{
826		BASE::GenerateRandom(rng, params);
827
828		if (FIPS_140_2_ComplianceEnabled())
829		{
830			typename SIGNATURE_SCHEME::Signer signer(*this);
831			typename SIGNATURE_SCHEME::Verifier verifier(signer);
832			SignaturePairwiseConsistencyTest_FIPS_140_Only(signer, verifier);
833		}
834	}
835};
836
837//! _
838template <class GP>
839class DL_PublicKeyImpl : public DL_PublicKey<typename GP::Element>, public DL_KeyImpl<X509PublicKey, GP>
840{
841public:
842	typedef typename GP::Element Element;
843
844	// CryptoMaterial
845	bool Validate(RandomNumberGenerator &rng, unsigned int level) const
846	{
847		bool pass = GetAbstractGroupParameters().Validate(rng, level);
848		pass = pass && GetAbstractGroupParameters().ValidateElement(level, this->GetPublicElement(), &GetPublicPrecomputation());
849		return pass;
850	}
851
852	bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
853	{
854		return GetValueHelper<DL_PublicKey<Element> >(this, name, valueType, pValue).Assignable();
855	}
856
857	void AssignFrom(const NameValuePairs &source)
858	{
859		AssignFromHelper<DL_PublicKey<Element> >(this, source);
860	}
861
862	bool SupportsPrecomputation() const {return true;}
863
864	void Precompute(unsigned int precomputationStorage=16)
865	{
866		AccessAbstractGroupParameters().Precompute(precomputationStorage);
867		AccessPublicPrecomputation().Precompute(GetAbstractGroupParameters().GetGroupPrecomputation(), GetAbstractGroupParameters().GetSubgroupOrder().BitCount(), precomputationStorage);
868	}
869
870	void LoadPrecomputation(BufferedTransformation &storedPrecomputation)
871	{
872		AccessAbstractGroupParameters().LoadPrecomputation(storedPrecomputation);
873		AccessPublicPrecomputation().Load(GetAbstractGroupParameters().GetGroupPrecomputation(), storedPrecomputation);
874	}
875
876	void SavePrecomputation(BufferedTransformation &storedPrecomputation) const
877	{
878		GetAbstractGroupParameters().SavePrecomputation(storedPrecomputation);
879		GetPublicPrecomputation().Save(GetAbstractGroupParameters().GetGroupPrecomputation(), storedPrecomputation);
880	}
881
882	// DL_Key
883	const DL_GroupParameters<Element> & GetAbstractGroupParameters() const {return this->GetGroupParameters();}
884	DL_GroupParameters<Element> & AccessAbstractGroupParameters() {return this->AccessGroupParameters();}
885
886	// DL_PublicKey
887	const DL_FixedBasePrecomputation<Element> & GetPublicPrecomputation() const {return m_ypc;}
888	DL_FixedBasePrecomputation<Element> & AccessPublicPrecomputation() {return m_ypc;}
889
890	// non-inherited
891	bool operator==(const DL_PublicKeyImpl<GP> &rhs) const
892		{return this->GetGroupParameters() == rhs.GetGroupParameters() && this->GetPublicElement() == rhs.GetPublicElement();}
893
894private:
895	typename GP::BasePrecomputation m_ypc;
896};
897
898//! interface for Elgamal-like signature algorithms
899template <class T>
900class CRYPTOPP_NO_VTABLE DL_ElgamalLikeSignatureAlgorithm
901{
902public:
903	virtual void Sign(const DL_GroupParameters<T> &params, const Integer &privateKey, const Integer &k, const Integer &e, Integer &r, Integer &s) const =0;
904	virtual bool Verify(const DL_GroupParameters<T> &params, const DL_PublicKey<T> &publicKey, const Integer &e, const Integer &r, const Integer &s) const =0;
905	virtual Integer RecoverPresignature(const DL_GroupParameters<T> &params, const DL_PublicKey<T> &publicKey, const Integer &r, const Integer &s) const
906		{throw NotImplemented("DL_ElgamalLikeSignatureAlgorithm: this signature scheme does not support message recovery");}
907	virtual size_t RLen(const DL_GroupParameters<T> &params) const
908		{return params.GetSubgroupOrder().ByteCount();}
909	virtual size_t SLen(const DL_GroupParameters<T> &params) const
910		{return params.GetSubgroupOrder().ByteCount();}
911};
912
913//! interface for DL key agreement algorithms
914template <class T>
915class CRYPTOPP_NO_VTABLE DL_KeyAgreementAlgorithm
916{
917public:
918	typedef T Element;
919
920	virtual Element AgreeWithEphemeralPrivateKey(const DL_GroupParameters<Element> &params, const DL_FixedBasePrecomputation<Element> &publicPrecomputation, const Integer &privateExponent) const =0;
921	virtual Element AgreeWithStaticPrivateKey(const DL_GroupParameters<Element> &params, const Element &publicElement, bool validateOtherPublicKey, const Integer &privateExponent) const =0;
922};
923
924//! interface for key derivation algorithms used in DL cryptosystems
925template <class T>
926class CRYPTOPP_NO_VTABLE DL_KeyDerivationAlgorithm
927{
928public:
929	virtual bool ParameterSupported(const char *name) const {return false;}
930	virtual void Derive(const DL_GroupParameters<T> &groupParams, byte *derivedKey, size_t derivedLength, const T &agreedElement, const T &ephemeralPublicKey, const NameValuePairs &derivationParams) const =0;
931};
932
933//! interface for symmetric encryption algorithms used in DL cryptosystems
934class CRYPTOPP_NO_VTABLE DL_SymmetricEncryptionAlgorithm
935{
936public:
937	virtual bool ParameterSupported(const char *name) const {return false;}
938	virtual size_t GetSymmetricKeyLength(size_t plaintextLength) const =0;
939	virtual size_t GetSymmetricCiphertextLength(size_t plaintextLength) const =0;
940	virtual size_t GetMaxSymmetricPlaintextLength(size_t ciphertextLength) const =0;
941	virtual void SymmetricEncrypt(RandomNumberGenerator &rng, const byte *key, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs &parameters) const =0;
942	virtual DecodingResult SymmetricDecrypt(const byte *key, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs &parameters) const =0;
943};
944
945//! _
946template <class KI>
947class CRYPTOPP_NO_VTABLE DL_Base
948{
949protected:
950	typedef KI KeyInterface;
951	typedef typename KI::Element Element;
952
953	const DL_GroupParameters<Element> & GetAbstractGroupParameters() const {return GetKeyInterface().GetAbstractGroupParameters();}
954	DL_GroupParameters<Element> & AccessAbstractGroupParameters() {return AccessKeyInterface().AccessAbstractGroupParameters();}
955
956	virtual KeyInterface & AccessKeyInterface() =0;
957	virtual const KeyInterface & GetKeyInterface() const =0;
958};
959
960//! _
961template <class INTERFACE, class KEY_INTERFACE>
962class CRYPTOPP_NO_VTABLE DL_SignatureSchemeBase : public INTERFACE, public DL_Base<KEY_INTERFACE>
963{
964public:
965	size_t SignatureLength() const
966	{
967		return GetSignatureAlgorithm().RLen(this->GetAbstractGroupParameters())
968			+ GetSignatureAlgorithm().SLen(this->GetAbstractGroupParameters());
969	}
970	size_t MaxRecoverableLength() const
971		{return GetMessageEncodingInterface().MaxRecoverableLength(0, GetHashIdentifier().second, GetDigestSize());}
972	size_t MaxRecoverableLengthFromSignatureLength(size_t signatureLength) const
973		{assert(false); return 0;}	// TODO
974
975	bool IsProbabilistic() const
976		{return true;}
977	bool AllowNonrecoverablePart() const
978		{return GetMessageEncodingInterface().AllowNonrecoverablePart();}
979	bool RecoverablePartFirst() const
980		{return GetMessageEncodingInterface().RecoverablePartFirst();}
981
982protected:
983	size_t MessageRepresentativeLength() const {return BitsToBytes(MessageRepresentativeBitLength());}
984	size_t MessageRepresentativeBitLength() const {return this->GetAbstractGroupParameters().GetSubgroupOrder().BitCount();}
985
986	virtual const DL_ElgamalLikeSignatureAlgorithm<CPP_TYPENAME KEY_INTERFACE::Element> & GetSignatureAlgorithm() const =0;
987	virtual const PK_SignatureMessageEncodingMethod & GetMessageEncodingInterface() const =0;
988	virtual HashIdentifier GetHashIdentifier() const =0;
989	virtual size_t GetDigestSize() const =0;
990};
991
992//! _
993template <class T>
994class CRYPTOPP_NO_VTABLE DL_SignerBase : public DL_SignatureSchemeBase<PK_Signer, DL_PrivateKey<T> >
995{
996public:
997	// for validation testing
998	void RawSign(const Integer &k, const Integer &e, Integer &r, Integer &s) const
999	{
1000		const DL_ElgamalLikeSignatureAlgorithm<T> &alg = this->GetSignatureAlgorithm();
1001		const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
1002		const DL_PrivateKey<T> &key = this->GetKeyInterface();
1003
1004		r = params.ConvertElementToInteger(params.ExponentiateBase(k));
1005		alg.Sign(params, key.GetPrivateExponent(), k, e, r, s);
1006	}
1007
1008	void InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, size_t recoverableMessageLength) const
1009	{
1010		PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
1011		ma.m_recoverableMessage.Assign(recoverableMessage, recoverableMessageLength);
1012		this->GetMessageEncodingInterface().ProcessRecoverableMessage(ma.AccessHash(),
1013			recoverableMessage, recoverableMessageLength,
1014			ma.m_presignature, ma.m_presignature.size(),
1015			ma.m_semisignature);
1016	}
1017
1018	size_t SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart) const
1019	{
1020		this->GetMaterial().DoQuickSanityCheck();
1021
1022		PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
1023		const DL_ElgamalLikeSignatureAlgorithm<T> &alg = this->GetSignatureAlgorithm();
1024		const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
1025		const DL_PrivateKey<T> &key = this->GetKeyInterface();
1026
1027		SecByteBlock representative(this->MessageRepresentativeLength());
1028		this->GetMessageEncodingInterface().ComputeMessageRepresentative(
1029			rng,
1030			ma.m_recoverableMessage, ma.m_recoverableMessage.size(),
1031			ma.AccessHash(), this->GetHashIdentifier(), ma.m_empty,
1032			representative, this->MessageRepresentativeBitLength());
1033		ma.m_empty = true;
1034		Integer e(representative, representative.size());
1035
1036		// hash message digest into random number k to prevent reusing the same k on a different messages
1037		// after virtual machine rollback
1038		if (rng.CanIncorporateEntropy())
1039			rng.IncorporateEntropy(representative, representative.size());
1040		Integer k(rng, 1, params.GetSubgroupOrder()-1);
1041		Integer r, s;
1042		r = params.ConvertElementToInteger(params.ExponentiateBase(k));
1043		alg.Sign(params, key.GetPrivateExponent(), k, e, r, s);
1044
1045		/*
1046		Integer r, s;
1047		if (this->MaxRecoverableLength() > 0)
1048			r.Decode(ma.m_semisignature, ma.m_semisignature.size());
1049		else
1050			r.Decode(ma.m_presignature, ma.m_presignature.size());
1051		alg.Sign(params, key.GetPrivateExponent(), ma.m_k, e, r, s);
1052		*/
1053
1054		size_t rLen = alg.RLen(params);
1055		r.Encode(signature, rLen);
1056		s.Encode(signature+rLen, alg.SLen(params));
1057
1058		if (restart)
1059			RestartMessageAccumulator(rng, ma);
1060
1061		return this->SignatureLength();
1062	}
1063
1064protected:
1065	void RestartMessageAccumulator(RandomNumberGenerator &rng, PK_MessageAccumulatorBase &ma) const
1066	{
1067		// k needs to be generated before hashing for signature schemes with recovery
1068		// but to defend against VM rollbacks we need to generate k after hashing.
1069		// so this code is commented out, since no DL-based signature scheme with recovery
1070		// has been implemented in Crypto++ anyway
1071		/*
1072		const DL_ElgamalLikeSignatureAlgorithm<T> &alg = this->GetSignatureAlgorithm();
1073		const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
1074		ma.m_k.Randomize(rng, 1, params.GetSubgroupOrder()-1);
1075		ma.m_presignature.New(params.GetEncodedElementSize(false));
1076		params.ConvertElementToInteger(params.ExponentiateBase(ma.m_k)).Encode(ma.m_presignature, ma.m_presignature.size());
1077		*/
1078	}
1079};
1080
1081//! _
1082template <class T>
1083class CRYPTOPP_NO_VTABLE DL_VerifierBase : public DL_SignatureSchemeBase<PK_Verifier, DL_PublicKey<T> >
1084{
1085public:
1086	void InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, size_t signatureLength) const
1087	{
1088		PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
1089		const DL_ElgamalLikeSignatureAlgorithm<T> &alg = this->GetSignatureAlgorithm();
1090		const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
1091
1092		size_t rLen = alg.RLen(params);
1093		ma.m_semisignature.Assign(signature, rLen);
1094		ma.m_s.Decode(signature+rLen, alg.SLen(params));
1095
1096		this->GetMessageEncodingInterface().ProcessSemisignature(ma.AccessHash(), ma.m_semisignature, ma.m_semisignature.size());
1097	}
1098
1099	bool VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const
1100	{
1101		this->GetMaterial().DoQuickSanityCheck();
1102
1103		PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
1104		const DL_ElgamalLikeSignatureAlgorithm<T> &alg = this->GetSignatureAlgorithm();
1105		const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
1106		const DL_PublicKey<T> &key = this->GetKeyInterface();
1107
1108		SecByteBlock representative(this->MessageRepresentativeLength());
1109		this->GetMessageEncodingInterface().ComputeMessageRepresentative(NullRNG(), ma.m_recoverableMessage, ma.m_recoverableMessage.size(),
1110			ma.AccessHash(), this->GetHashIdentifier(), ma.m_empty,
1111			representative, this->MessageRepresentativeBitLength());
1112		ma.m_empty = true;
1113		Integer e(representative, representative.size());
1114
1115		Integer r(ma.m_semisignature, ma.m_semisignature.size());
1116		return alg.Verify(params, key, e, r, ma.m_s);
1117	}
1118
1119	DecodingResult RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &messageAccumulator) const
1120	{
1121		this->GetMaterial().DoQuickSanityCheck();
1122
1123		PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
1124		const DL_ElgamalLikeSignatureAlgorithm<T> &alg = this->GetSignatureAlgorithm();
1125		const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
1126		const DL_PublicKey<T> &key = this->GetKeyInterface();
1127
1128		SecByteBlock representative(this->MessageRepresentativeLength());
1129		this->GetMessageEncodingInterface().ComputeMessageRepresentative(
1130			NullRNG(),
1131			ma.m_recoverableMessage, ma.m_recoverableMessage.size(),
1132			ma.AccessHash(), this->GetHashIdentifier(), ma.m_empty,
1133			representative, this->MessageRepresentativeBitLength());
1134		ma.m_empty = true;
1135		Integer e(representative, representative.size());
1136
1137		ma.m_presignature.New(params.GetEncodedElementSize(false));
1138		Integer r(ma.m_semisignature, ma.m_semisignature.size());
1139		alg.RecoverPresignature(params, key, r, ma.m_s).Encode(ma.m_presignature, ma.m_presignature.size());
1140
1141		return this->GetMessageEncodingInterface().RecoverMessageFromSemisignature(
1142			ma.AccessHash(), this->GetHashIdentifier(),
1143			ma.m_presignature, ma.m_presignature.size(),
1144			ma.m_semisignature, ma.m_semisignature.size(),
1145			recoveredMessage);
1146	}
1147};
1148
1149//! _
1150template <class PK, class KI>
1151class CRYPTOPP_NO_VTABLE DL_CryptoSystemBase : public PK, public DL_Base<KI>
1152{
1153public:
1154	typedef typename DL_Base<KI>::Element Element;
1155
1156	size_t MaxPlaintextLength(size_t ciphertextLength) const
1157	{
1158		unsigned int minLen = this->GetAbstractGroupParameters().GetEncodedElementSize(true);
1159		return ciphertextLength < minLen ? 0 : GetSymmetricEncryptionAlgorithm().GetMaxSymmetricPlaintextLength(ciphertextLength - minLen);
1160	}
1161
1162	size_t CiphertextLength(size_t plaintextLength) const
1163	{
1164		size_t len = GetSymmetricEncryptionAlgorithm().GetSymmetricCiphertextLength(plaintextLength);
1165		return len == 0 ? 0 : this->GetAbstractGroupParameters().GetEncodedElementSize(true) + len;
1166	}
1167
1168	bool ParameterSupported(const char *name) const
1169		{return GetKeyDerivationAlgorithm().ParameterSupported(name) || GetSymmetricEncryptionAlgorithm().ParameterSupported(name);}
1170
1171protected:
1172	virtual const DL_KeyAgreementAlgorithm<Element> & GetKeyAgreementAlgorithm() const =0;
1173	virtual const DL_KeyDerivationAlgorithm<Element> & GetKeyDerivationAlgorithm() const =0;
1174	virtual const DL_SymmetricEncryptionAlgorithm & GetSymmetricEncryptionAlgorithm() const =0;
1175};
1176
1177//! _
1178template <class T>
1179class CRYPTOPP_NO_VTABLE DL_DecryptorBase : public DL_CryptoSystemBase<PK_Decryptor, DL_PrivateKey<T> >
1180{
1181public:
1182	typedef T Element;
1183
1184	DecodingResult Decrypt(RandomNumberGenerator &rng, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs &parameters = g_nullNameValuePairs) const
1185	{
1186		try
1187		{
1188			const DL_KeyAgreementAlgorithm<T> &agreeAlg = this->GetKeyAgreementAlgorithm();
1189			const DL_KeyDerivationAlgorithm<T> &derivAlg = this->GetKeyDerivationAlgorithm();
1190			const DL_SymmetricEncryptionAlgorithm &encAlg = this->GetSymmetricEncryptionAlgorithm();
1191			const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
1192			const DL_PrivateKey<T> &key = this->GetKeyInterface();
1193
1194			Element q = params.DecodeElement(ciphertext, true);
1195			size_t elementSize = params.GetEncodedElementSize(true);
1196			ciphertext += elementSize;
1197			ciphertextLength -= elementSize;
1198
1199			Element z = agreeAlg.AgreeWithStaticPrivateKey(params, q, true, key.GetPrivateExponent());
1200
1201			SecByteBlock derivedKey(encAlg.GetSymmetricKeyLength(encAlg.GetMaxSymmetricPlaintextLength(ciphertextLength)));
1202			derivAlg.Derive(params, derivedKey, derivedKey.size(), z, q, parameters);
1203
1204			return encAlg.SymmetricDecrypt(derivedKey, ciphertext, ciphertextLength, plaintext, parameters);
1205		}
1206		catch (DL_BadElement &)
1207		{
1208			return DecodingResult();
1209		}
1210	}
1211};
1212
1213//! _
1214template <class T>
1215class CRYPTOPP_NO_VTABLE DL_EncryptorBase : public DL_CryptoSystemBase<PK_Encryptor, DL_PublicKey<T> >
1216{
1217public:
1218	typedef T Element;
1219
1220	void Encrypt(RandomNumberGenerator &rng, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs &parameters = g_nullNameValuePairs) const
1221	{
1222		const DL_KeyAgreementAlgorithm<T> &agreeAlg = this->GetKeyAgreementAlgorithm();
1223		const DL_KeyDerivationAlgorithm<T> &derivAlg = this->GetKeyDerivationAlgorithm();
1224		const DL_SymmetricEncryptionAlgorithm &encAlg = this->GetSymmetricEncryptionAlgorithm();
1225		const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
1226		const DL_PublicKey<T> &key = this->GetKeyInterface();
1227
1228		Integer x(rng, Integer::One(), params.GetMaxExponent());
1229		Element q = params.ExponentiateBase(x);
1230		params.EncodeElement(true, q, ciphertext);
1231		unsigned int elementSize = params.GetEncodedElementSize(true);
1232		ciphertext += elementSize;
1233
1234		Element z = agreeAlg.AgreeWithEphemeralPrivateKey(params, key.GetPublicPrecomputation(), x);
1235
1236		SecByteBlock derivedKey(encAlg.GetSymmetricKeyLength(plaintextLength));
1237		derivAlg.Derive(params, derivedKey, derivedKey.size(), z, q, parameters);
1238
1239		encAlg.SymmetricEncrypt(rng, derivedKey, plaintext, plaintextLength, ciphertext, parameters);
1240	}
1241};
1242
1243//! _
1244template <class T1, class T2>
1245struct DL_SchemeOptionsBase
1246{
1247	typedef T1 AlgorithmInfo;
1248	typedef T2 GroupParameters;
1249	typedef typename GroupParameters::Element Element;
1250};
1251
1252//! _
1253template <class T1, class T2>
1254struct DL_KeyedSchemeOptions : public DL_SchemeOptionsBase<T1, typename T2::PublicKey::GroupParameters>
1255{
1256	typedef T2 Keys;
1257	typedef typename Keys::PrivateKey PrivateKey;
1258	typedef typename Keys::PublicKey PublicKey;
1259};
1260
1261//! _
1262template <class T1, class T2, class T3, class T4, class T5>
1263struct DL_SignatureSchemeOptions : public DL_KeyedSchemeOptions<T1, T2>
1264{
1265	typedef T3 SignatureAlgorithm;
1266	typedef T4 MessageEncodingMethod;
1267	typedef T5 HashFunction;
1268};
1269
1270//! _
1271template <class T1, class T2, class T3, class T4, class T5>
1272struct DL_CryptoSchemeOptions : public DL_KeyedSchemeOptions<T1, T2>
1273{
1274	typedef T3 KeyAgreementAlgorithm;
1275	typedef T4 KeyDerivationAlgorithm;
1276	typedef T5 SymmetricEncryptionAlgorithm;
1277};
1278
1279//! _
1280template <class BASE, class SCHEME_OPTIONS, class KEY>
1281class CRYPTOPP_NO_VTABLE DL_ObjectImplBase : public AlgorithmImpl<BASE, typename SCHEME_OPTIONS::AlgorithmInfo>
1282{
1283public:
1284	typedef SCHEME_OPTIONS SchemeOptions;
1285	typedef typename KEY::Element Element;
1286
1287	PrivateKey & AccessPrivateKey() {return m_key;}
1288	PublicKey & AccessPublicKey() {return m_key;}
1289
1290	// KeyAccessor
1291	const KEY & GetKey() const {return m_key;}
1292	KEY & AccessKey() {return m_key;}
1293
1294protected:
1295	typename BASE::KeyInterface & AccessKeyInterface() {return m_key;}
1296	const typename BASE::KeyInterface & GetKeyInterface() const {return m_key;}
1297
1298	// for signature scheme
1299	HashIdentifier GetHashIdentifier() const
1300	{
1301		typedef typename SchemeOptions::MessageEncodingMethod::HashIdentifierLookup HashLookup;
1302		return HashLookup::template HashIdentifierLookup2<CPP_TYPENAME SchemeOptions::HashFunction>::Lookup();
1303	}
1304	size_t GetDigestSize() const
1305	{
1306		typedef CPP_TYPENAME SchemeOptions::HashFunction H;
1307		return H::DIGESTSIZE;
1308	}
1309
1310private:
1311	KEY m_key;
1312};
1313
1314//! _
1315template <class BASE, class SCHEME_OPTIONS, class KEY>
1316class CRYPTOPP_NO_VTABLE DL_ObjectImpl : public DL_ObjectImplBase<BASE, SCHEME_OPTIONS, KEY>
1317{
1318public:
1319	typedef typename KEY::Element Element;
1320
1321protected:
1322	const DL_ElgamalLikeSignatureAlgorithm<Element> & GetSignatureAlgorithm() const
1323		{return Singleton<CPP_TYPENAME SCHEME_OPTIONS::SignatureAlgorithm>().Ref();}
1324	const DL_KeyAgreementAlgorithm<Element> & GetKeyAgreementAlgorithm() const
1325		{return Singleton<CPP_TYPENAME SCHEME_OPTIONS::KeyAgreementAlgorithm>().Ref();}
1326	const DL_KeyDerivationAlgorithm<Element> & GetKeyDerivationAlgorithm() const
1327		{return Singleton<CPP_TYPENAME SCHEME_OPTIONS::KeyDerivationAlgorithm>().Ref();}
1328	const DL_SymmetricEncryptionAlgorithm & GetSymmetricEncryptionAlgorithm() const
1329		{return Singleton<CPP_TYPENAME SCHEME_OPTIONS::SymmetricEncryptionAlgorithm>().Ref();}
1330	HashIdentifier GetHashIdentifier() const
1331		{return HashIdentifier();}
1332	const PK_SignatureMessageEncodingMethod & GetMessageEncodingInterface() const
1333		{return Singleton<CPP_TYPENAME SCHEME_OPTIONS::MessageEncodingMethod>().Ref();}
1334};
1335
1336//! _
1337template <class SCHEME_OPTIONS>
1338class DL_SignerImpl : public DL_ObjectImpl<DL_SignerBase<typename SCHEME_OPTIONS::Element>, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PrivateKey>
1339{
1340public:
1341	PK_MessageAccumulator * NewSignatureAccumulator(RandomNumberGenerator &rng) const
1342	{
1343		std::auto_ptr<PK_MessageAccumulatorBase> p(new PK_MessageAccumulatorImpl<CPP_TYPENAME SCHEME_OPTIONS::HashFunction>);
1344		this->RestartMessageAccumulator(rng, *p);
1345		return p.release();
1346	}
1347};
1348
1349//! _
1350template <class SCHEME_OPTIONS>
1351class DL_VerifierImpl : public DL_ObjectImpl<DL_VerifierBase<typename SCHEME_OPTIONS::Element>, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PublicKey>
1352{
1353public:
1354	PK_MessageAccumulator * NewVerificationAccumulator() const
1355	{
1356		return new PK_MessageAccumulatorImpl<CPP_TYPENAME SCHEME_OPTIONS::HashFunction>;
1357	}
1358};
1359
1360//! _
1361template <class SCHEME_OPTIONS>
1362class DL_EncryptorImpl : public DL_ObjectImpl<DL_EncryptorBase<typename SCHEME_OPTIONS::Element>, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PublicKey>
1363{
1364};
1365
1366//! _
1367template <class SCHEME_OPTIONS>
1368class DL_DecryptorImpl : public DL_ObjectImpl<DL_DecryptorBase<typename SCHEME_OPTIONS::Element>, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PrivateKey>
1369{
1370};
1371
1372// ********************************************************
1373
1374//! _
1375template <class T>
1376class CRYPTOPP_NO_VTABLE DL_SimpleKeyAgreementDomainBase : public SimpleKeyAgreementDomain
1377{
1378public:
1379	typedef T Element;
1380
1381	CryptoParameters & AccessCryptoParameters() {return AccessAbstractGroupParameters();}
1382	unsigned int AgreedValueLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(false);}
1383	unsigned int PrivateKeyLength() const {return GetAbstractGroupParameters().GetSubgroupOrder().ByteCount();}
1384	unsigned int PublicKeyLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(true);}
1385
1386	void GeneratePrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
1387	{
1388		Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent());
1389		x.Encode(privateKey, PrivateKeyLength());
1390	}
1391
1392	void GeneratePublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
1393	{
1394		const DL_GroupParameters<T> &params = GetAbstractGroupParameters();
1395		Integer x(privateKey, PrivateKeyLength());
1396		Element y = params.ExponentiateBase(x);
1397		params.EncodeElement(true, y, publicKey);
1398	}
1399
1400	bool Agree(byte *agreedValue, const byte *privateKey, const byte *otherPublicKey, bool validateOtherPublicKey=true) const
1401	{
1402		try
1403		{
1404			const DL_GroupParameters<T> &params = GetAbstractGroupParameters();
1405			Integer x(privateKey, PrivateKeyLength());
1406			Element w = params.DecodeElement(otherPublicKey, validateOtherPublicKey);
1407
1408			Element z = GetKeyAgreementAlgorithm().AgreeWithStaticPrivateKey(
1409				GetAbstractGroupParameters(), w, validateOtherPublicKey, x);
1410			params.EncodeElement(false, z, agreedValue);
1411		}
1412		catch (DL_BadElement &)
1413		{
1414			return false;
1415		}
1416		return true;
1417	}
1418
1419	const Element &GetGenerator() const {return GetAbstractGroupParameters().GetSubgroupGenerator();}
1420
1421protected:
1422	virtual const DL_KeyAgreementAlgorithm<Element> & GetKeyAgreementAlgorithm() const =0;
1423	virtual DL_GroupParameters<Element> & AccessAbstractGroupParameters() =0;
1424	const DL_GroupParameters<Element> & GetAbstractGroupParameters() const {return const_cast<DL_SimpleKeyAgreementDomainBase<Element> *>(this)->AccessAbstractGroupParameters();}
1425};
1426
1427enum CofactorMultiplicationOption {NO_COFACTOR_MULTIPLICTION, COMPATIBLE_COFACTOR_MULTIPLICTION, INCOMPATIBLE_COFACTOR_MULTIPLICTION};
1428typedef EnumToType<CofactorMultiplicationOption, NO_COFACTOR_MULTIPLICTION> NoCofactorMultiplication;
1429typedef EnumToType<CofactorMultiplicationOption, COMPATIBLE_COFACTOR_MULTIPLICTION> CompatibleCofactorMultiplication;
1430typedef EnumToType<CofactorMultiplicationOption, INCOMPATIBLE_COFACTOR_MULTIPLICTION> IncompatibleCofactorMultiplication;
1431
1432//! DH key agreement algorithm
1433template <class ELEMENT, class COFACTOR_OPTION>
1434class DL_KeyAgreementAlgorithm_DH : public DL_KeyAgreementAlgorithm<ELEMENT>
1435{
1436public:
1437	typedef ELEMENT Element;
1438
1439	static const char * CRYPTOPP_API StaticAlgorithmName()
1440		{return COFACTOR_OPTION::ToEnum() == INCOMPATIBLE_COFACTOR_MULTIPLICTION ? "DHC" : "DH";}
1441
1442	Element AgreeWithEphemeralPrivateKey(const DL_GroupParameters<Element> &params, const DL_FixedBasePrecomputation<Element> &publicPrecomputation, const Integer &privateExponent) const
1443	{
1444		return publicPrecomputation.Exponentiate(params.GetGroupPrecomputation(),
1445			COFACTOR_OPTION::ToEnum() == INCOMPATIBLE_COFACTOR_MULTIPLICTION ? privateExponent*params.GetCofactor() : privateExponent);
1446	}
1447
1448	Element AgreeWithStaticPrivateKey(const DL_GroupParameters<Element> &params, const Element &publicElement, bool validateOtherPublicKey, const Integer &privateExponent) const
1449	{
1450		if (COFACTOR_OPTION::ToEnum() == COMPATIBLE_COFACTOR_MULTIPLICTION)
1451		{
1452			const Integer &k = params.GetCofactor();
1453			return params.ExponentiateElement(publicElement,
1454				ModularArithmetic(params.GetSubgroupOrder()).Divide(privateExponent, k)*k);
1455		}
1456		else if (COFACTOR_OPTION::ToEnum() == INCOMPATIBLE_COFACTOR_MULTIPLICTION)
1457			return params.ExponentiateElement(publicElement, privateExponent*params.GetCofactor());
1458		else
1459		{
1460			assert(COFACTOR_OPTION::ToEnum() == NO_COFACTOR_MULTIPLICTION);
1461
1462			if (!validateOtherPublicKey)
1463				return params.ExponentiateElement(publicElement, privateExponent);
1464
1465			if (params.FastSubgroupCheckAvailable())
1466			{
1467				if (!params.ValidateElement(2, publicElement, NULL))
1468					throw DL_BadElement();
1469				return params.ExponentiateElement(publicElement, privateExponent);
1470			}
1471			else
1472			{
1473				const Integer e[2] = {params.GetSubgroupOrder(), privateExponent};
1474				Element r[2];
1475				params.SimultaneousExponentiate(r, publicElement, e, 2);
1476				if (!params.IsIdentity(r[0]))
1477					throw DL_BadElement();
1478				return r[1];
1479			}
1480		}
1481	}
1482};
1483
1484// ********************************************************
1485
1486//! A template implementing constructors for public key algorithm classes
1487template <class BASE>
1488class CRYPTOPP_NO_VTABLE PK_FinalTemplate : public BASE
1489{
1490public:
1491	PK_FinalTemplate() {}
1492
1493	PK_FinalTemplate(const CryptoMaterial &key)
1494		{this->AccessKey().AssignFrom(key);}
1495
1496	PK_FinalTemplate(BufferedTransformation &bt)
1497		{this->AccessKey().BERDecode(bt);}
1498
1499	PK_FinalTemplate(const AsymmetricAlgorithm &algorithm)
1500		{this->AccessKey().AssignFrom(algorithm.GetMaterial());}
1501
1502	PK_FinalTemplate(const Integer &v1)
1503		{this->AccessKey().Initialize(v1);}
1504
1505#if (defined(_MSC_VER) && _MSC_VER < 1300)
1506
1507	template <class T1, class T2>
1508	PK_FinalTemplate(T1 &v1, T2 &v2)
1509		{this->AccessKey().Initialize(v1, v2);}
1510
1511	template <class T1, class T2, class T3>
1512	PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3)
1513		{this->AccessKey().Initialize(v1, v2, v3);}
1514
1515	template <class T1, class T2, class T3, class T4>
1516	PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4)
1517		{this->AccessKey().Initialize(v1, v2, v3, v4);}
1518
1519	template <class T1, class T2, class T3, class T4, class T5>
1520	PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5)
1521		{this->AccessKey().Initialize(v1, v2, v3, v4, v5);}
1522
1523	template <class T1, class T2, class T3, class T4, class T5, class T6>
1524	PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5, T6 &v6)
1525		{this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6);}
1526
1527	template <class T1, class T2, class T3, class T4, class T5, class T6, class T7>
1528	PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5, T6 &v6, T7 &v7)
1529		{this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7);}
1530
1531	template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
1532	PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5, T6 &v6, T7 &v7, T8 &v8)
1533		{this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7, v8);}
1534
1535#else
1536
1537	template <class T1, class T2>
1538	PK_FinalTemplate(const T1 &v1, const T2 &v2)
1539		{this->AccessKey().Initialize(v1, v2);}
1540
1541	template <class T1, class T2, class T3>
1542	PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3)
1543		{this->AccessKey().Initialize(v1, v2, v3);}
1544
1545	template <class T1, class T2, class T3, class T4>
1546	PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4)
1547		{this->AccessKey().Initialize(v1, v2, v3, v4);}
1548
1549	template <class T1, class T2, class T3, class T4, class T5>
1550	PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5)
1551		{this->AccessKey().Initialize(v1, v2, v3, v4, v5);}
1552
1553	template <class T1, class T2, class T3, class T4, class T5, class T6>
1554	PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6)
1555		{this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6);}
1556
1557	template <class T1, class T2, class T3, class T4, class T5, class T6, class T7>
1558	PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7)
1559		{this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7);}
1560
1561	template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
1562	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)
1563		{this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7, v8);}
1564
1565	template <class T1, class T2>
1566	PK_FinalTemplate(T1 &v1, const T2 &v2)
1567		{this->AccessKey().Initialize(v1, v2);}
1568
1569	template <class T1, class T2, class T3>
1570	PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3)
1571		{this->AccessKey().Initialize(v1, v2, v3);}
1572
1573	template <class T1, class T2, class T3, class T4>
1574	PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4)
1575		{this->AccessKey().Initialize(v1, v2, v3, v4);}
1576
1577	template <class T1, class T2, class T3, class T4, class T5>
1578	PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5)
1579		{this->AccessKey().Initialize(v1, v2, v3, v4, v5);}
1580
1581	template <class T1, class T2, class T3, class T4, class T5, class T6>
1582	PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6)
1583		{this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6);}
1584
1585	template <class T1, class T2, class T3, class T4, class T5, class T6, class T7>
1586	PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7)
1587		{this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7);}
1588
1589	template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
1590	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)
1591		{this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7, v8);}
1592
1593#endif
1594};
1595
1596//! Base class for public key encryption standard classes. These classes are used to select from variants of algorithms. Note that not all standards apply to all algorithms.
1597struct EncryptionStandard {};
1598
1599//! Base class for public key signature standard classes. These classes are used to select from variants of algorithms. Note that not all standards apply to all algorithms.
1600struct SignatureStandard {};
1601
1602template <class STANDARD, class KEYS, class ALG_INFO>
1603class TF_ES;
1604
1605//! Trapdoor Function Based Encryption Scheme
1606template <class STANDARD, class KEYS, class ALG_INFO = TF_ES<STANDARD, KEYS, int> >
1607class TF_ES : public KEYS
1608{
1609	typedef typename STANDARD::EncryptionMessageEncodingMethod MessageEncodingMethod;
1610
1611public:
1612	//! see EncryptionStandard for a list of standards
1613	typedef STANDARD Standard;
1614	typedef TF_CryptoSchemeOptions<ALG_INFO, KEYS, MessageEncodingMethod> SchemeOptions;
1615
1616	static std::string CRYPTOPP_API StaticAlgorithmName() {return std::string(KEYS::StaticAlgorithmName()) + "/" + MessageEncodingMethod::StaticAlgorithmName();}
1617
1618	//! implements PK_Decryptor interface
1619	typedef PK_FinalTemplate<TF_DecryptorImpl<SchemeOptions> > Decryptor;
1620	//! implements PK_Encryptor interface
1621	typedef PK_FinalTemplate<TF_EncryptorImpl<SchemeOptions> > Encryptor;
1622};
1623
1624template <class STANDARD, class H, class KEYS, class ALG_INFO>	// VC60 workaround: doesn't work if KEYS is first parameter
1625class TF_SS;
1626
1627//! Trapdoor Function Based Signature Scheme
1628template <class STANDARD, class H, class KEYS, class ALG_INFO = TF_SS<STANDARD, H, KEYS, int> >	// VC60 workaround: doesn't work if KEYS is first parameter
1629class TF_SS : public KEYS
1630{
1631public:
1632	//! see SignatureStandard for a list of standards
1633	typedef STANDARD Standard;
1634	typedef typename Standard::SignatureMessageEncodingMethod MessageEncodingMethod;
1635	typedef TF_SignatureSchemeOptions<ALG_INFO, KEYS, MessageEncodingMethod, H> SchemeOptions;
1636
1637	static std::string CRYPTOPP_API StaticAlgorithmName() {return std::string(KEYS::StaticAlgorithmName()) + "/" + MessageEncodingMethod::StaticAlgorithmName() + "(" + H::StaticAlgorithmName() + ")";}
1638
1639	//! implements PK_Signer interface
1640	typedef PK_FinalTemplate<TF_SignerImpl<SchemeOptions> > Signer;
1641	//! implements PK_Verifier interface
1642	typedef PK_FinalTemplate<TF_VerifierImpl<SchemeOptions> > Verifier;
1643};
1644
1645template <class KEYS, class SA, class MEM, class H, class ALG_INFO>
1646class DL_SS;
1647
1648//! Discrete Log Based Signature Scheme
1649template <class KEYS, class SA, class MEM, class H, class ALG_INFO = DL_SS<KEYS, SA, MEM, H, int> >
1650class DL_SS : public KEYS
1651{
1652	typedef DL_SignatureSchemeOptions<ALG_INFO, KEYS, SA, MEM, H> SchemeOptions;
1653
1654public:
1655	static std::string StaticAlgorithmName() {return SA::StaticAlgorithmName() + std::string("/EMSA1(") + H::StaticAlgorithmName() + ")";}
1656
1657	//! implements PK_Signer interface
1658	typedef PK_FinalTemplate<DL_SignerImpl<SchemeOptions> > Signer;
1659	//! implements PK_Verifier interface
1660	typedef PK_FinalTemplate<DL_VerifierImpl<SchemeOptions> > Verifier;
1661};
1662
1663//! Discrete Log Based Encryption Scheme
1664template <class KEYS, class AA, class DA, class EA, class ALG_INFO>
1665class DL_ES : public KEYS
1666{
1667	typedef DL_CryptoSchemeOptions<ALG_INFO, KEYS, AA, DA, EA> SchemeOptions;
1668
1669public:
1670	//! implements PK_Decryptor interface
1671	typedef PK_FinalTemplate<DL_DecryptorImpl<SchemeOptions> > Decryptor;
1672	//! implements PK_Encryptor interface
1673	typedef PK_FinalTemplate<DL_EncryptorImpl<SchemeOptions> > Encryptor;
1674};
1675
1676NAMESPACE_END
1677
1678#endif
1679