~ubuntu-branches/debian/squeeze/pycryptopp/squeeze

« back to all changes in this revision

Viewing changes to cryptopp/pubkey.h

  • Committer: Bazaar Package Importer
  • Author(s): Zooko O'Whielacronx
  • Date: 2009-06-22 22:20:50 UTC
  • Revision ID: james.westby@ubuntu.com-20090622222050-hbqmn50dt2kvoz5o
Tags: upstream-0.5.14
ImportĀ upstreamĀ versionĀ 0.5.14

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
45
NAMESPACE_BEGIN(CryptoPP)
 
46
 
 
47
//! _
 
48
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TrapdoorFunctionBounds
 
49
{
 
50
public:
 
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
//! _
 
60
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE RandomizedTrapdoorFunction : public TrapdoorFunctionBounds
 
61
{
 
62
public:
 
63
        virtual Integer ApplyRandomizedFunction(RandomNumberGenerator &rng, const Integer &x) const =0;
 
64
        virtual bool IsRandomized() const {return true;}
 
65
};
 
66
 
 
67
//! _
 
68
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TrapdoorFunction : public RandomizedTrapdoorFunction
 
69
{
 
70
public:
 
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
//! _
 
79
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE RandomizedTrapdoorFunctionInverse
 
80
{
 
81
public:
 
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
//! _
 
89
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TrapdoorFunctionInverse : public RandomizedTrapdoorFunctionInverse
 
90
{
 
91
public:
 
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
 
104
class CRYPTOPP_NO_VTABLE PK_EncryptionMessageEncodingMethod
 
105
{
 
106
public:
 
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
//! _
 
122
template <class TFI, class MEI>
 
123
class CRYPTOPP_NO_VTABLE TF_Base
 
124
{
 
125
protected:
 
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
//! _
 
138
template <class BASE>
 
139
class CRYPTOPP_NO_VTABLE PK_FixedLengthCryptoSystemImpl : public BASE
 
140
{
 
141
public:
 
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
//! _
 
152
template <class INTERFACE, class BASE>
 
153
class CRYPTOPP_NO_VTABLE TF_CryptoSystemBase : public PK_FixedLengthCryptoSystemImpl<INTERFACE>, protected BASE
 
154
{
 
155
public:
 
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
 
 
160
protected:
 
161
        size_t PaddedBlockByteLength() const {return BitsToBytes(PaddedBlockBitLength());}
 
162
        size_t PaddedBlockBitLength() const {return this->GetTrapdoorFunctionBounds().PreimageBound().BitCount()-1;}
 
163
};
 
164
 
 
165
//! _
 
166
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_DecryptorBase : public TF_CryptoSystemBase<PK_Decryptor, TF_Base<TrapdoorFunctionInverse, PK_EncryptionMessageEncodingMethod> >
 
167
{
 
168
public:
 
169
        DecodingResult Decrypt(RandomNumberGenerator &rng, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs &parameters = g_nullNameValuePairs) const;
 
170
};
 
171
 
 
172
//! _
 
173
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_EncryptorBase : public TF_CryptoSystemBase<PK_Encryptor, TF_Base<RandomizedTrapdoorFunction, PK_EncryptionMessageEncodingMethod> >
 
174
{
 
175
public:
 
176
        void Encrypt(RandomNumberGenerator &rng, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs &parameters = g_nullNameValuePairs) const;
 
177
};
 
178
 
 
179
// ********************************************************
 
180
 
 
181
typedef std::pair<const byte *, size_t> HashIdentifier;
 
182
 
 
183
//! interface for message encoding method for public key signature schemes
 
184
class CRYPTOPP_NO_VTABLE PK_SignatureMessageEncodingMethod
 
185
{
 
186
public:
 
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
 
 
249
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_DeterministicSignatureMessageEncodingMethod : public PK_SignatureMessageEncodingMethod
 
250
{
 
251
public:
 
252
        bool VerifyMessageRepresentative(
 
253
                HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
 
254
                byte *representative, size_t representativeBitLength) const;
 
255
};
 
256
 
 
257
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_RecoverableSignatureMessageEncodingMethod : public PK_SignatureMessageEncodingMethod
 
258
{
 
259
public:
 
260
        bool VerifyMessageRepresentative(
 
261
                HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
 
262
                byte *representative, size_t representativeBitLength) const;
 
263
};
 
264
 
 
265
class CRYPTOPP_DLL DL_SignatureMessageEncodingMethod_DSA : public PK_DeterministicSignatureMessageEncodingMethod
 
266
{
 
267
public:
 
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
 
 
274
class CRYPTOPP_DLL DL_SignatureMessageEncodingMethod_NR : public PK_DeterministicSignatureMessageEncodingMethod
 
275
{
 
276
public:
 
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
 
 
283
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_MessageAccumulatorBase : public PK_MessageAccumulator
 
284
{
 
285
public:
 
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
 
 
301
template <class HASH_ALGORITHM>
 
302
class PK_MessageAccumulatorImpl : public PK_MessageAccumulatorBase, protected ObjectHolder<HASH_ALGORITHM>
 
303
{
 
304
public:
 
305
        HashTransformation & AccessHash() {return this->m_object;}
 
306
};
 
307
 
 
308
//! _
 
309
template <class INTERFACE, class BASE>
 
310
class CRYPTOPP_NO_VTABLE TF_SignatureSchemeBase : public INTERFACE, protected BASE
 
311
{
 
312
public:
 
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
 
 
327
protected:
 
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
//! _
 
335
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_SignerBase : public TF_SignatureSchemeBase<PK_Signer, TF_Base<RandomizedTrapdoorFunctionInverse, PK_SignatureMessageEncodingMethod> >
 
336
{
 
337
public:
 
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
//! _
 
343
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_VerifierBase : public TF_SignatureSchemeBase<PK_Verifier, TF_Base<TrapdoorFunction, PK_SignatureMessageEncodingMethod> >
 
344
{
 
345
public:
 
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
//! _
 
354
template <class T1, class T2, class T3>
 
355
struct 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
//! _
 
365
template <class T1, class T2, class T3, class T4>
 
366
struct TF_SignatureSchemeOptions : public TF_CryptoSchemeOptions<T1, T2, T3>
 
367
{
 
368
        typedef T4 HashFunction;
 
369
};
 
370
 
 
371
//! _
 
372
template <class BASE, class SCHEME_OPTIONS, class KEY_CLASS>
 
373
class CRYPTOPP_NO_VTABLE TF_ObjectImplBase : public AlgorithmImpl<BASE, typename SCHEME_OPTIONS::AlgorithmInfo>
 
374
{
 
375
public:
 
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
 
 
399
protected:
 
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
//! _
 
421
template <class BASE, class SCHEME_OPTIONS, class KEY>
 
422
class TF_ObjectImplExtRef : public TF_ObjectImplBase<BASE, SCHEME_OPTIONS, KEY>
 
423
{
 
424
public:
 
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
 
 
431
private:
 
432
        const KEY * m_pKey;
 
433
};
 
434
 
 
435
//! _
 
436
template <class BASE, class SCHEME_OPTIONS, class KEY_CLASS>
 
437
class CRYPTOPP_NO_VTABLE TF_ObjectImpl : public TF_ObjectImplBase<BASE, SCHEME_OPTIONS, KEY_CLASS>
 
438
{
 
439
public:
 
440
        typedef KEY_CLASS KeyClass;
 
441
 
 
442
        const KeyClass & GetKey() const {return m_trapdoorFunction;}
 
443
        KeyClass & AccessKey() {return m_trapdoorFunction;}
 
444
 
 
445
private:
 
446
        KeyClass m_trapdoorFunction;
 
447
};
 
448
 
 
449
//! _
 
450
template <class SCHEME_OPTIONS>
 
451
class TF_DecryptorImpl : public TF_ObjectImpl<TF_DecryptorBase, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PrivateKey>
 
452
{
 
453
};
 
454
 
 
455
//! _
 
456
template <class SCHEME_OPTIONS>
 
457
class TF_EncryptorImpl : public TF_ObjectImpl<TF_EncryptorBase, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PublicKey>
 
458
{
 
459
};
 
460
 
 
461
//! _
 
462
template <class SCHEME_OPTIONS>
 
463
class TF_SignerImpl : public TF_ObjectImpl<TF_SignerBase, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PrivateKey>
 
464
{
 
465
};
 
466
 
 
467
//! _
 
468
template <class SCHEME_OPTIONS>
 
469
class TF_VerifierImpl : public TF_ObjectImpl<TF_VerifierBase, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PublicKey>
 
470
{
 
471
};
 
472
 
 
473
// ********************************************************
 
474
 
 
475
//! _
 
476
class CRYPTOPP_NO_VTABLE MaskGeneratingFunction
 
477
{
 
478
public:
 
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
 
 
483
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);
 
484
 
 
485
//! _
 
486
class P1363_MGF1 : public MaskGeneratingFunction
 
487
{
 
488
public:
 
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
//! _
 
499
template <class H>
 
500
class P1363_KDF2
 
501
{
 
502
public:
 
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
 
513
class DL_BadElement : public InvalidDataFormat
 
514
{
 
515
public:
 
516
        DL_BadElement() : InvalidDataFormat("CryptoPP: invalid group element") {}
 
517
};
 
518
 
 
519
//! interface for DL group parameters
 
520
template <class T>
 
521
class CRYPTOPP_NO_VTABLE DL_GroupParameters : public CryptoParameters
 
522
{
 
523
        typedef DL_GroupParameters<T> ThisClass;
 
524
        
 
525
public:
 
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
 
 
604
protected:
 
605
        void ParametersChanged() {m_validationLevel = 0;}
 
606
 
 
607
private:
 
608
        mutable unsigned int m_validationLevel;
 
609
};
 
610
 
 
611
//! _
 
612
template <class GROUP_PRECOMP, class BASE_PRECOMP = DL_FixedBasePrecomputationImpl<CPP_TYPENAME GROUP_PRECOMP::Element>, class BASE = DL_GroupParameters<CPP_TYPENAME GROUP_PRECOMP::Element> >
 
613
class DL_GroupParametersImpl : public BASE
 
614
{
 
615
public:
 
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
 
 
624
protected:
 
625
        GROUP_PRECOMP m_groupPrecomputation;
 
626
        BASE_PRECOMP m_gpc;
 
627
};
 
628
 
 
629
//! _
 
630
template <class T>
 
631
class CRYPTOPP_NO_VTABLE DL_Key
 
632
{
 
633
public:
 
634
        virtual const DL_GroupParameters<T> & GetAbstractGroupParameters() const =0;
 
635
        virtual DL_GroupParameters<T> & AccessAbstractGroupParameters() =0;
 
636
};
 
637
 
 
638
//! interface for DL public keys
 
639
template <class T>
 
640
class CRYPTOPP_NO_VTABLE DL_PublicKey : public DL_Key<T>
 
641
{
 
642
        typedef DL_PublicKey<T> ThisClass;
 
643
 
 
644
public:
 
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
 
674
template <class T>
 
675
class CRYPTOPP_NO_VTABLE DL_PrivateKey : public DL_Key<T>
 
676
{
 
677
        typedef DL_PrivateKey<T> ThisClass;
 
678
 
 
679
public:
 
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
 
 
705
template <class T>
 
706
void 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
 
 
719
class OID;
 
720
 
 
721
//! _
 
722
template <class PK, class GP, class O = OID>
 
723
class DL_KeyImpl : public PK
 
724
{
 
725
public:
 
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
 
 
741
private:
 
742
        GP m_groupParameters;
 
743
};
 
744
 
 
745
class X509PublicKey;
 
746
class PKCS8PrivateKey;
 
747
 
 
748
//! _
 
749
template <class GP>
 
750
class DL_PrivateKeyImpl : public DL_PrivateKey<CPP_TYPENAME GP::Element>, public DL_KeyImpl<PKCS8PrivateKey, GP>
 
751
{
 
752
public:
 
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
 
 
815
private:
 
816
        Integer m_x;
 
817
};
 
818
 
 
819
//! _
 
820
template <class BASE, class SIGNATURE_SCHEME>
 
821
class DL_PrivateKey_WithSignaturePairwiseConsistencyTest : public BASE
 
822
{
 
823
public:
 
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
//! _
 
838
template <class GP>
 
839
class DL_PublicKeyImpl : public DL_PublicKey<typename GP::Element>, public DL_KeyImpl<X509PublicKey, GP>
 
840
{
 
841
public:
 
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
 
 
894
private:
 
895
        typename GP::BasePrecomputation m_ypc;
 
896
};
 
897
 
 
898
//! interface for Elgamal-like signature algorithms
 
899
template <class T>
 
900
class CRYPTOPP_NO_VTABLE DL_ElgamalLikeSignatureAlgorithm
 
901
{
 
902
public:
 
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
 
914
template <class T>
 
915
class CRYPTOPP_NO_VTABLE DL_KeyAgreementAlgorithm
 
916
{
 
917
public:
 
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
 
925
template <class T>
 
926
class CRYPTOPP_NO_VTABLE DL_KeyDerivationAlgorithm
 
927
{
 
928
public:
 
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
 
934
class CRYPTOPP_NO_VTABLE DL_SymmetricEncryptionAlgorithm
 
935
{
 
936
public:
 
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
//! _
 
946
template <class KI>
 
947
class CRYPTOPP_NO_VTABLE DL_Base
 
948
{
 
949
protected:
 
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
//! _
 
961
template <class INTERFACE, class KEY_INTERFACE>
 
962
class CRYPTOPP_NO_VTABLE DL_SignatureSchemeBase : public INTERFACE, public DL_Base<KEY_INTERFACE>
 
963
{
 
964
public:
 
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
 
 
982
protected:
 
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
//! _
 
993
template <class T>
 
994
class CRYPTOPP_NO_VTABLE DL_SignerBase : public DL_SignatureSchemeBase<PK_Signer, DL_PrivateKey<T> >
 
995
{
 
996
public:
 
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
 
 
1064
protected:
 
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
//! _
 
1082
template <class T>
 
1083
class CRYPTOPP_NO_VTABLE DL_VerifierBase : public DL_SignatureSchemeBase<PK_Verifier, DL_PublicKey<T> >
 
1084
{
 
1085
public:
 
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
//! _
 
1150
template <class PK, class KI>
 
1151
class CRYPTOPP_NO_VTABLE DL_CryptoSystemBase : public PK, public DL_Base<KI>
 
1152
{
 
1153
public:
 
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
 
 
1171
protected:
 
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
//! _
 
1178
template <class T>
 
1179
class CRYPTOPP_NO_VTABLE DL_DecryptorBase : public DL_CryptoSystemBase<PK_Decryptor, DL_PrivateKey<T> >
 
1180
{
 
1181
public:
 
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
//! _
 
1214
template <class T>
 
1215
class CRYPTOPP_NO_VTABLE DL_EncryptorBase : public DL_CryptoSystemBase<PK_Encryptor, DL_PublicKey<T> >
 
1216
{
 
1217
public:
 
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
//! _
 
1244
template <class T1, class T2>
 
1245
struct DL_SchemeOptionsBase
 
1246
{
 
1247
        typedef T1 AlgorithmInfo;
 
1248
        typedef T2 GroupParameters;
 
1249
        typedef typename GroupParameters::Element Element;
 
1250
};
 
1251
 
 
1252
//! _
 
1253
template <class T1, class T2>
 
1254
struct 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
//! _
 
1262
template <class T1, class T2, class T3, class T4, class T5>
 
1263
struct DL_SignatureSchemeOptions : public DL_KeyedSchemeOptions<T1, T2>
 
1264
{
 
1265
        typedef T3 SignatureAlgorithm;
 
1266
        typedef T4 MessageEncodingMethod;
 
1267
        typedef T5 HashFunction;
 
1268
};
 
1269
 
 
1270
//! _
 
1271
template <class T1, class T2, class T3, class T4, class T5>
 
1272
struct DL_CryptoSchemeOptions : public DL_KeyedSchemeOptions<T1, T2>
 
1273
{
 
1274
        typedef T3 KeyAgreementAlgorithm;
 
1275
        typedef T4 KeyDerivationAlgorithm;
 
1276
        typedef T5 SymmetricEncryptionAlgorithm;
 
1277
};
 
1278
 
 
1279
//! _
 
1280
template <class BASE, class SCHEME_OPTIONS, class KEY>
 
1281
class CRYPTOPP_NO_VTABLE DL_ObjectImplBase : public AlgorithmImpl<BASE, typename SCHEME_OPTIONS::AlgorithmInfo>
 
1282
{
 
1283
public:
 
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
 
 
1294
protected:
 
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
 
 
1310
private:
 
1311
        KEY m_key;
 
1312
};
 
1313
 
 
1314
//! _
 
1315
template <class BASE, class SCHEME_OPTIONS, class KEY>
 
1316
class CRYPTOPP_NO_VTABLE DL_ObjectImpl : public DL_ObjectImplBase<BASE, SCHEME_OPTIONS, KEY>
 
1317
{
 
1318
public:
 
1319
        typedef typename KEY::Element Element;
 
1320
 
 
1321
protected:
 
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
//! _
 
1337
template <class SCHEME_OPTIONS>
 
1338
class DL_SignerImpl : public DL_ObjectImpl<DL_SignerBase<typename SCHEME_OPTIONS::Element>, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PrivateKey>
 
1339
{
 
1340
public:
 
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
//! _
 
1350
template <class SCHEME_OPTIONS>
 
1351
class DL_VerifierImpl : public DL_ObjectImpl<DL_VerifierBase<typename SCHEME_OPTIONS::Element>, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PublicKey>
 
1352
{
 
1353
public:
 
1354
        PK_MessageAccumulator * NewVerificationAccumulator() const
 
1355
        {
 
1356
                return new PK_MessageAccumulatorImpl<CPP_TYPENAME SCHEME_OPTIONS::HashFunction>;
 
1357
        }
 
1358
};
 
1359
 
 
1360
//! _
 
1361
template <class SCHEME_OPTIONS>
 
1362
class DL_EncryptorImpl : public DL_ObjectImpl<DL_EncryptorBase<typename SCHEME_OPTIONS::Element>, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PublicKey>
 
1363
{
 
1364
};
 
1365
 
 
1366
//! _
 
1367
template <class SCHEME_OPTIONS>
 
1368
class DL_DecryptorImpl : public DL_ObjectImpl<DL_DecryptorBase<typename SCHEME_OPTIONS::Element>, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PrivateKey>
 
1369
{
 
1370
};
 
1371
 
 
1372
// ********************************************************
 
1373
 
 
1374
//! _
 
1375
template <class T>
 
1376
class CRYPTOPP_NO_VTABLE DL_SimpleKeyAgreementDomainBase : public SimpleKeyAgreementDomain
 
1377
{
 
1378
public:
 
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
 
 
1421
protected:
 
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
 
 
1427
enum CofactorMultiplicationOption {NO_COFACTOR_MULTIPLICTION, COMPATIBLE_COFACTOR_MULTIPLICTION, INCOMPATIBLE_COFACTOR_MULTIPLICTION};
 
1428
typedef EnumToType<CofactorMultiplicationOption, NO_COFACTOR_MULTIPLICTION> NoCofactorMultiplication;
 
1429
typedef EnumToType<CofactorMultiplicationOption, COMPATIBLE_COFACTOR_MULTIPLICTION> CompatibleCofactorMultiplication;
 
1430
typedef EnumToType<CofactorMultiplicationOption, INCOMPATIBLE_COFACTOR_MULTIPLICTION> IncompatibleCofactorMultiplication;
 
1431
 
 
1432
//! DH key agreement algorithm
 
1433
template <class ELEMENT, class COFACTOR_OPTION>
 
1434
class DL_KeyAgreementAlgorithm_DH : public DL_KeyAgreementAlgorithm<ELEMENT>
 
1435
{
 
1436
public:
 
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
 
1487
template <class BASE>
 
1488
class CRYPTOPP_NO_VTABLE PK_FinalTemplate : public BASE
 
1489
{
 
1490
public:
 
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.
 
1597
struct 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.
 
1600
struct SignatureStandard {};
 
1601
 
 
1602
template <class STANDARD, class KEYS, class ALG_INFO>
 
1603
class TF_ES;
 
1604
 
 
1605
//! Trapdoor Function Based Encryption Scheme
 
1606
template <class STANDARD, class KEYS, class ALG_INFO = TF_ES<STANDARD, KEYS, int> >
 
1607
class TF_ES : public KEYS
 
1608
{
 
1609
        typedef typename STANDARD::EncryptionMessageEncodingMethod MessageEncodingMethod;
 
1610
 
 
1611
public:
 
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
 
 
1624
template <class STANDARD, class H, class KEYS, class ALG_INFO>  // VC60 workaround: doesn't work if KEYS is first parameter
 
1625
class TF_SS;
 
1626
 
 
1627
//! Trapdoor Function Based Signature Scheme
 
1628
template <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
 
1629
class TF_SS : public KEYS
 
1630
{
 
1631
public:
 
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
 
 
1645
template <class KEYS, class SA, class MEM, class H, class ALG_INFO>
 
1646
class DL_SS;
 
1647
 
 
1648
//! Discrete Log Based Signature Scheme
 
1649
template <class KEYS, class SA, class MEM, class H, class ALG_INFO = DL_SS<KEYS, SA, MEM, H, int> >
 
1650
class DL_SS : public KEYS
 
1651
{
 
1652
        typedef DL_SignatureSchemeOptions<ALG_INFO, KEYS, SA, MEM, H> SchemeOptions;
 
1653
 
 
1654
public:
 
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
 
1664
template <class KEYS, class AA, class DA, class EA, class ALG_INFO>
 
1665
class DL_ES : public KEYS
 
1666
{
 
1667
        typedef DL_CryptoSchemeOptions<ALG_INFO, KEYS, AA, DA, EA> SchemeOptions;
 
1668
 
 
1669
public:
 
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
 
 
1676
NAMESPACE_END
 
1677
 
 
1678
#endif