source: trunk/src-cryptopp/gfpcrypt.h

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

Add cryptopp from tag CRYPTOPP_5_6_5

  • Property mode set to 100644
File size: 22.4 KB
Line 
1#ifndef CRYPTOPP_GFPCRYPT_H
2#define CRYPTOPP_GFPCRYPT_H
3
4/** \file
5        Implementation of schemes based on DL over GF(p)
6*/
7
8#include "config.h"
9
10#if CRYPTOPP_MSC_VERSION
11# pragma warning(push)
12# pragma warning(disable: 4189)
13#endif
14
15#include "cryptlib.h"
16#include "pubkey.h"
17#include "integer.h"
18#include "modexppc.h"
19#include "algparam.h"
20#include "smartptr.h"
21#include "sha.h"
22#include "asn.h"
23#include "hmac.h"
24#include "misc.h"
25
26NAMESPACE_BEGIN(CryptoPP)
27
28CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters<Integer>;
29
30//! _
31class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE DL_GroupParameters_IntegerBased : public ASN1CryptoMaterial<DL_GroupParameters<Integer> >
32{
33        typedef DL_GroupParameters_IntegerBased ThisClass;
34
35public:
36        void Initialize(const DL_GroupParameters_IntegerBased &params)
37                {Initialize(params.GetModulus(), params.GetSubgroupOrder(), params.GetSubgroupGenerator());}
38        void Initialize(RandomNumberGenerator &rng, unsigned int pbits)
39                {GenerateRandom(rng, MakeParameters("ModulusSize", (int)pbits));}
40        void Initialize(const Integer &p, const Integer &g)
41                {SetModulusAndSubgroupGenerator(p, g); SetSubgroupOrder(ComputeGroupOrder(p)/2);}
42        void Initialize(const Integer &p, const Integer &q, const Integer &g)
43                {SetModulusAndSubgroupGenerator(p, g); SetSubgroupOrder(q);}
44
45        // ASN1Object interface
46        void BERDecode(BufferedTransformation &bt);
47        void DEREncode(BufferedTransformation &bt) const;
48
49        // GeneratibleCryptoMaterial interface
50        /*! parameters: (ModulusSize, SubgroupOrderSize (optional)) */
51        void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg);
52        bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
53        void AssignFrom(const NameValuePairs &source);
54
55        // DL_GroupParameters
56        const Integer & GetSubgroupOrder() const {return m_q;}
57        Integer GetGroupOrder() const {return GetFieldType() == 1 ? GetModulus()-Integer::One() : GetModulus()+Integer::One();}
58        bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const;
59        bool ValidateElement(unsigned int level, const Integer &element, const DL_FixedBasePrecomputation<Integer> *precomp) const;
60        bool FastSubgroupCheckAvailable() const {return GetCofactor() == 2;}
61
62#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
63        // Cygwin i386 crash at -O3; see .
64        void EncodeElement(bool reversible, const Element &element, byte *encoded) const;
65        unsigned int GetEncodedElementSize(bool reversible) const;
66#else
67        void EncodeElement(bool reversible, const Element &element, byte *encoded) const
68                {CRYPTOPP_UNUSED(reversible); element.Encode(encoded, GetModulus().ByteCount());}
69        unsigned int GetEncodedElementSize(bool reversible) const
70                {CRYPTOPP_UNUSED(reversible); return GetModulus().ByteCount();}
71#endif
72
73        Integer DecodeElement(const byte *encoded, bool checkForGroupMembership) const;
74        Integer ConvertElementToInteger(const Element &element) const
75                {return element;}
76        Integer GetMaxExponent() const;
77        static std::string CRYPTOPP_API StaticAlgorithmNamePrefix() {return "";}
78
79        OID GetAlgorithmID() const;
80
81        virtual const Integer & GetModulus() const =0;
82        virtual void SetModulusAndSubgroupGenerator(const Integer &p, const Integer &g) =0;
83
84        void SetSubgroupOrder(const Integer &q)
85                {m_q = q; ParametersChanged();}
86
87#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
88        virtual ~DL_GroupParameters_IntegerBased() {}
89#endif
90
91protected:
92        Integer ComputeGroupOrder(const Integer &modulus) const
93                {return modulus-(GetFieldType() == 1 ? 1 : -1);}
94
95        // GF(p) = 1, GF(p^2) = 2
96        virtual int GetFieldType() const =0;
97        virtual unsigned int GetDefaultSubgroupOrderSize(unsigned int modulusSize) const;
98
99private:
100        Integer m_q;
101};
102
103//! _
104template <class GROUP_PRECOMP, class BASE_PRECOMP = DL_FixedBasePrecomputationImpl<CPP_TYPENAME GROUP_PRECOMP::Element> >
105class CRYPTOPP_NO_VTABLE DL_GroupParameters_IntegerBasedImpl : public DL_GroupParametersImpl<GROUP_PRECOMP, BASE_PRECOMP, DL_GroupParameters_IntegerBased>
106{
107        typedef DL_GroupParameters_IntegerBasedImpl<GROUP_PRECOMP, BASE_PRECOMP> ThisClass;
108
109public:
110        typedef typename GROUP_PRECOMP::Element Element;
111
112        // GeneratibleCryptoMaterial interface
113        bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
114                {return GetValueHelper<DL_GroupParameters_IntegerBased>(this, name, valueType, pValue).Assignable();}
115
116        void AssignFrom(const NameValuePairs &source)
117                {AssignFromHelper<DL_GroupParameters_IntegerBased>(this, source);}
118
119        // DL_GroupParameters
120        const DL_FixedBasePrecomputation<Element> & GetBasePrecomputation() const {return this->m_gpc;}
121        DL_FixedBasePrecomputation<Element> & AccessBasePrecomputation() {return this->m_gpc;}
122
123        // IntegerGroupParameters
124        const Integer & GetModulus() const {return this->m_groupPrecomputation.GetModulus();}
125    const Integer & GetGenerator() const {return this->m_gpc.GetBase(this->GetGroupPrecomputation());}
126
127        void SetModulusAndSubgroupGenerator(const Integer &p, const Integer &g)         // these have to be set together
128                {this->m_groupPrecomputation.SetModulus(p); this->m_gpc.SetBase(this->GetGroupPrecomputation(), g); this->ParametersChanged();}
129
130        // non-inherited
131        bool operator==(const DL_GroupParameters_IntegerBasedImpl<GROUP_PRECOMP, BASE_PRECOMP> &rhs) const
132                {return GetModulus() == rhs.GetModulus() && GetGenerator() == rhs.GetGenerator() && this->GetSubgroupOrder() == rhs.GetSubgroupOrder();}
133        bool operator!=(const DL_GroupParameters_IntegerBasedImpl<GROUP_PRECOMP, BASE_PRECOMP> &rhs) const
134                {return !operator==(rhs);}
135
136#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
137        virtual ~DL_GroupParameters_IntegerBasedImpl() {}
138#endif
139};
140
141CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_IntegerBasedImpl<ModExpPrecomputation>;
142
143//! GF(p) group parameters
144class CRYPTOPP_DLL DL_GroupParameters_GFP : public DL_GroupParameters_IntegerBasedImpl<ModExpPrecomputation>
145{
146public:
147        // DL_GroupParameters
148        bool IsIdentity(const Integer &element) const {return element == Integer::One();}
149        void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
150
151        // NameValuePairs interface
152        bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
153        {
154                return GetValueHelper<DL_GroupParameters_IntegerBased>(this, name, valueType, pValue).Assignable();
155        }
156
157        // used by MQV
158        Element MultiplyElements(const Element &a, const Element &b) const;
159        Element CascadeExponentiate(const Element &element1, const Integer &exponent1, const Element &element2, const Integer &exponent2) const;
160
161#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
162        virtual ~DL_GroupParameters_GFP() {}
163#endif
164
165protected:
166        int GetFieldType() const {return 1;}
167};
168
169//! GF(p) group parameters that default to same primes
170class CRYPTOPP_DLL DL_GroupParameters_GFP_DefaultSafePrime : public DL_GroupParameters_GFP
171{
172public:
173        typedef NoCofactorMultiplication DefaultCofactorOption;
174
175#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
176        virtual ~DL_GroupParameters_GFP_DefaultSafePrime() {}
177#endif
178
179protected:
180        unsigned int GetDefaultSubgroupOrderSize(unsigned int modulusSize) const {return modulusSize-1;}
181};
182
183//! GDSA algorithm
184template <class T>
185class DL_Algorithm_GDSA : public DL_ElgamalLikeSignatureAlgorithm<T>
186{
187public:
188        CRYPTOPP_CONSTEXPR static const char * CRYPTOPP_API StaticAlgorithmName() {return "DSA-1363";}
189
190        void Sign(const DL_GroupParameters<T> &params, const Integer &x, const Integer &k, const Integer &e, Integer &r, Integer &s) const
191        {
192                const Integer &q = params.GetSubgroupOrder();
193                r %= q;
194                Integer kInv = k.InverseMod(q);
195                s = (kInv * (x*r + e)) % q;
196                CRYPTOPP_ASSERT(!!r && !!s);
197        }
198
199        bool Verify(const DL_GroupParameters<T> &params, const DL_PublicKey<T> &publicKey, const Integer &e, const Integer &r, const Integer &s) const
200        {
201                const Integer &q = params.GetSubgroupOrder();
202                if (r>=q || r<1 || s>=q || s<1)
203                        return false;
204
205                Integer w = s.InverseMod(q);
206                Integer u1 = (e * w) % q;
207                Integer u2 = (r * w) % q;
208                // verify r == (g^u1 * y^u2 mod p) mod q
209                return r == params.ConvertElementToInteger(publicKey.CascadeExponentiateBaseAndPublicElement(u1, u2)) % q;
210        }
211
212#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
213        virtual ~DL_Algorithm_GDSA() {}
214#endif
215};
216
217CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_GDSA<Integer>;
218
219//! NR algorithm
220template <class T>
221class DL_Algorithm_NR : public DL_ElgamalLikeSignatureAlgorithm<T>
222{
223public:
224        CRYPTOPP_CONSTEXPR static const char * CRYPTOPP_API StaticAlgorithmName() {return "NR";}
225
226        void Sign(const DL_GroupParameters<T> &params, const Integer &x, const Integer &k, const Integer &e, Integer &r, Integer &s) const
227        {
228                const Integer &q = params.GetSubgroupOrder();
229                r = (r + e) % q;
230                s = (k - x*r) % q;
231                CRYPTOPP_ASSERT(!!r);
232        }
233
234        bool Verify(const DL_GroupParameters<T> &params, const DL_PublicKey<T> &publicKey, const Integer &e, const Integer &r, const Integer &s) const
235        {
236                const Integer &q = params.GetSubgroupOrder();
237                if (r>=q || r<1 || s>=q)
238                        return false;
239
240                // check r == (m_g^s * m_y^r + m) mod m_q
241                return r == (params.ConvertElementToInteger(publicKey.CascadeExponentiateBaseAndPublicElement(s, r)) + e) % q;
242        }
243
244#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
245        virtual ~DL_Algorithm_NR() {}
246#endif
247};
248
249/*! DSA public key format is defined in 7.3.3 of RFC 2459. The
250        private key format is defined in 12.9 of PKCS #11 v2.10. */
251template <class GP>
252class DL_PublicKey_GFP : public DL_PublicKeyImpl<GP>
253{
254public:
255        void Initialize(const DL_GroupParameters_IntegerBased &params, const Integer &y)
256                {this->AccessGroupParameters().Initialize(params); this->SetPublicElement(y);}
257        void Initialize(const Integer &p, const Integer &g, const Integer &y)
258                {this->AccessGroupParameters().Initialize(p, g); this->SetPublicElement(y);}
259        void Initialize(const Integer &p, const Integer &q, const Integer &g, const Integer &y)
260                {this->AccessGroupParameters().Initialize(p, q, g); this->SetPublicElement(y);}
261
262        // X509PublicKey
263        void BERDecodePublicKey(BufferedTransformation &bt, bool, size_t)
264                {this->SetPublicElement(Integer(bt));}
265        void DEREncodePublicKey(BufferedTransformation &bt) const
266                {this->GetPublicElement().DEREncode(bt);}
267
268#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
269        virtual ~DL_PublicKey_GFP() {}
270#endif
271};
272
273//! DL private key (in GF(p) groups)
274template <class GP>
275class DL_PrivateKey_GFP : public DL_PrivateKeyImpl<GP>
276{
277public:
278        void Initialize(RandomNumberGenerator &rng, unsigned int modulusBits)
279                {this->GenerateRandomWithKeySize(rng, modulusBits);}
280        void Initialize(RandomNumberGenerator &rng, const Integer &p, const Integer &g)
281                {this->GenerateRandom(rng, MakeParameters("Modulus", p)("SubgroupGenerator", g));}
282        void Initialize(RandomNumberGenerator &rng, const Integer &p, const Integer &q, const Integer &g)
283                {this->GenerateRandom(rng, MakeParameters("Modulus", p)("SubgroupOrder", q)("SubgroupGenerator", g));}
284        void Initialize(const DL_GroupParameters_IntegerBased &params, const Integer &x)
285                {this->AccessGroupParameters().Initialize(params); this->SetPrivateExponent(x);}
286        void Initialize(const Integer &p, const Integer &g, const Integer &x)
287                {this->AccessGroupParameters().Initialize(p, g); this->SetPrivateExponent(x);}
288        void Initialize(const Integer &p, const Integer &q, const Integer &g, const Integer &x)
289                {this->AccessGroupParameters().Initialize(p, q, g); this->SetPrivateExponent(x);}
290
291#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
292        virtual ~DL_PrivateKey_GFP() {}
293#endif
294};
295
296//! DL signing/verification keys (in GF(p) groups)
297struct DL_SignatureKeys_GFP
298{
299        typedef DL_GroupParameters_GFP GroupParameters;
300        typedef DL_PublicKey_GFP<GroupParameters> PublicKey;
301        typedef DL_PrivateKey_GFP<GroupParameters> PrivateKey;
302
303#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
304        virtual ~DL_SignatureKeys_GFP() {}
305#endif
306};
307
308//! DL encryption/decryption keys (in GF(p) groups)
309struct DL_CryptoKeys_GFP
310{
311        typedef DL_GroupParameters_GFP_DefaultSafePrime GroupParameters;
312        typedef DL_PublicKey_GFP<GroupParameters> PublicKey;
313        typedef DL_PrivateKey_GFP<GroupParameters> PrivateKey;
314
315#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
316        virtual ~DL_CryptoKeys_GFP() {}
317#endif
318};
319
320//! provided for backwards compatibility, this class uses the old non-standard Crypto++ key format
321template <class BASE>
322class DL_PublicKey_GFP_OldFormat : public BASE
323{
324public:
325        void BERDecode(BufferedTransformation &bt)
326        {
327                BERSequenceDecoder seq(bt);
328                        Integer v1(seq);
329                        Integer v2(seq);
330                        Integer v3(seq);
331
332                        if (seq.EndReached())
333                        {
334                                this->AccessGroupParameters().Initialize(v1, v1/2, v2);
335                                this->SetPublicElement(v3);
336                        }
337                        else
338                        {
339                                Integer v4(seq);
340                                this->AccessGroupParameters().Initialize(v1, v2, v3);
341                                this->SetPublicElement(v4);
342                        }
343
344                seq.MessageEnd();
345        }
346
347        void DEREncode(BufferedTransformation &bt) const
348        {
349                DERSequenceEncoder seq(bt);
350                        this->GetGroupParameters().GetModulus().DEREncode(seq);
351                        if (this->GetGroupParameters().GetCofactor() != 2)
352                                this->GetGroupParameters().GetSubgroupOrder().DEREncode(seq);
353                        this->GetGroupParameters().GetGenerator().DEREncode(seq);
354                        this->GetPublicElement().DEREncode(seq);
355                seq.MessageEnd();
356        }
357
358#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
359        virtual ~DL_PublicKey_GFP_OldFormat() {}
360#endif
361};
362
363//! provided for backwards compatibility, this class uses the old non-standard Crypto++ key format
364template <class BASE>
365class DL_PrivateKey_GFP_OldFormat : public BASE
366{
367public:
368        void BERDecode(BufferedTransformation &bt)
369        {
370                BERSequenceDecoder seq(bt);
371                        Integer v1(seq);
372                        Integer v2(seq);
373                        Integer v3(seq);
374                        Integer v4(seq);
375
376                        if (seq.EndReached())
377                        {
378                                this->AccessGroupParameters().Initialize(v1, v1/2, v2);
379                                this->SetPrivateExponent(v4 % (v1/2));  // some old keys may have x >= q
380                        }
381                        else
382                        {
383                                Integer v5(seq);
384                                this->AccessGroupParameters().Initialize(v1, v2, v3);
385                                this->SetPrivateExponent(v5);
386                        }
387
388                seq.MessageEnd();
389        }
390
391        void DEREncode(BufferedTransformation &bt) const
392        {
393                DERSequenceEncoder seq(bt);
394                        this->GetGroupParameters().GetModulus().DEREncode(seq);
395                        if (this->GetGroupParameters().GetCofactor() != 2)
396                                this->GetGroupParameters().GetSubgroupOrder().DEREncode(seq);
397                        this->GetGroupParameters().GetGenerator().DEREncode(seq);
398                        this->GetGroupParameters().ExponentiateBase(this->GetPrivateExponent()).DEREncode(seq);
399                        this->GetPrivateExponent().DEREncode(seq);
400                seq.MessageEnd();
401        }
402
403#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
404        virtual ~DL_PrivateKey_GFP_OldFormat() {}
405#endif
406};
407
408//! <a href="http://www.weidai.com/scan-mirror/sig.html#DSA-1363">DSA-1363</a>
409template <class H>
410struct GDSA : public DL_SS<
411        DL_SignatureKeys_GFP,
412        DL_Algorithm_GDSA<Integer>,
413        DL_SignatureMessageEncodingMethod_DSA,
414        H>
415{
416#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
417        virtual ~GDSA() {}
418#endif
419};
420
421//! <a href="http://www.weidai.com/scan-mirror/sig.html#NR">NR</a>
422template <class H>
423struct NR : public DL_SS<
424        DL_SignatureKeys_GFP,
425        DL_Algorithm_NR<Integer>,
426        DL_SignatureMessageEncodingMethod_NR,
427        H>
428{
429#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
430        virtual ~NR() {}
431#endif
432};
433
434//! DSA group parameters, these are GF(p) group parameters that are allowed by the DSA standard
435class CRYPTOPP_DLL DL_GroupParameters_DSA : public DL_GroupParameters_GFP
436{
437public:
438        /*! also checks that the lengths of p and q are allowed by the DSA standard */
439        bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const;
440        /*! parameters: (ModulusSize), or (Modulus, SubgroupOrder, SubgroupGenerator) */
441        /*! ModulusSize must be between DSA::MIN_PRIME_LENGTH and DSA::MAX_PRIME_LENGTH, and divisible by DSA::PRIME_LENGTH_MULTIPLE */
442        void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg);
443
444        static bool CRYPTOPP_API IsValidPrimeLength(unsigned int pbits)
445                {return pbits >= MIN_PRIME_LENGTH && pbits <= MAX_PRIME_LENGTH && pbits % PRIME_LENGTH_MULTIPLE == 0;}
446
447        enum {MIN_PRIME_LENGTH = 1024, MAX_PRIME_LENGTH = 3072, PRIME_LENGTH_MULTIPLE = 1024};
448
449#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
450        virtual ~DL_GroupParameters_DSA() {}
451#endif
452};
453
454template <class H>
455class DSA2;
456
457//! DSA keys
458struct DL_Keys_DSA
459{
460        typedef DL_PublicKey_GFP<DL_GroupParameters_DSA> PublicKey;
461        typedef DL_PrivateKey_WithSignaturePairwiseConsistencyTest<DL_PrivateKey_GFP<DL_GroupParameters_DSA>, DSA2<SHA> > PrivateKey;
462
463#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
464        virtual ~DL_Keys_DSA() {}
465#endif
466};
467
468//! <a href="http://en.wikipedia.org/wiki/Digital_Signature_Algorithm">DSA</a>, as specified in FIPS 186-3
469// class named DSA2 instead of DSA for backwards compatibility (DSA was a non-template class)
470template <class H>
471class DSA2 : public DL_SS<
472        DL_Keys_DSA,
473        DL_Algorithm_GDSA<Integer>,
474        DL_SignatureMessageEncodingMethod_DSA,
475        H,
476        DSA2<H> >
477{
478public:
479        static std::string CRYPTOPP_API StaticAlgorithmName() {return "DSA/" + (std::string)H::StaticAlgorithmName();}
480
481#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
482        enum {MIN_PRIME_LENGTH = 1024, MAX_PRIME_LENGTH = 3072, PRIME_LENGTH_MULTIPLE = 1024};
483#endif
484
485#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
486        virtual ~DSA2() {}
487#endif
488};
489
490//! DSA with SHA-1, typedef'd for backwards compatibility
491typedef DSA2<SHA> DSA;
492
493CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_GFP<DL_GroupParameters_DSA>;
494CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_GFP<DL_GroupParameters_DSA>;
495CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_WithSignaturePairwiseConsistencyTest<DL_PrivateKey_GFP<DL_GroupParameters_DSA>, DSA2<SHA> >;
496
497//! the XOR encryption method, for use with DL-based cryptosystems
498template <class MAC, bool DHAES_MODE>
499class DL_EncryptionAlgorithm_Xor : public DL_SymmetricEncryptionAlgorithm
500{
501public:
502        bool ParameterSupported(const char *name) const {return strcmp(name, Name::EncodingParameters()) == 0;}
503        size_t GetSymmetricKeyLength(size_t plaintextLength) const
504                {return plaintextLength + MAC::DEFAULT_KEYLENGTH;}
505        size_t GetSymmetricCiphertextLength(size_t plaintextLength) const
506                {return plaintextLength + MAC::DIGESTSIZE;}
507        size_t GetMaxSymmetricPlaintextLength(size_t ciphertextLength) const
508                {return (unsigned int)SaturatingSubtract(ciphertextLength, (unsigned int)MAC::DIGESTSIZE);}
509        void SymmetricEncrypt(RandomNumberGenerator &rng, const byte *key, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs &parameters) const
510        {
511                CRYPTOPP_UNUSED(rng);
512                const byte *cipherKey = NULL, *macKey = NULL;
513                if (DHAES_MODE)
514                {
515                        macKey = key;
516                        cipherKey = key + MAC::DEFAULT_KEYLENGTH;
517                }
518                else
519                {
520                        cipherKey = key;
521                        macKey = key + plaintextLength;
522                }
523
524                ConstByteArrayParameter encodingParameters;
525                parameters.GetValue(Name::EncodingParameters(), encodingParameters);
526
527                if (plaintextLength)    // Coverity finding
528                        xorbuf(ciphertext, plaintext, cipherKey, plaintextLength);
529
530                MAC mac(macKey);
531                mac.Update(ciphertext, plaintextLength);
532                mac.Update(encodingParameters.begin(), encodingParameters.size());
533                if (DHAES_MODE)
534                {
535                        byte L[8] = {0,0,0,0};
536                        PutWord(false, BIG_ENDIAN_ORDER, L+4, word32(encodingParameters.size()));
537                        mac.Update(L, 8);
538                }
539                mac.Final(ciphertext + plaintextLength);
540        }
541        DecodingResult SymmetricDecrypt(const byte *key, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs &parameters) const
542        {
543                size_t plaintextLength = GetMaxSymmetricPlaintextLength(ciphertextLength);
544                const byte *cipherKey, *macKey;
545                if (DHAES_MODE)
546                {
547                        macKey = key;
548                        cipherKey = key + MAC::DEFAULT_KEYLENGTH;
549                }
550                else
551                {
552                        cipherKey = key;
553                        macKey = key + plaintextLength;
554                }
555
556                ConstByteArrayParameter encodingParameters;
557                parameters.GetValue(Name::EncodingParameters(), encodingParameters);
558
559                MAC mac(macKey);
560                mac.Update(ciphertext, plaintextLength);
561                mac.Update(encodingParameters.begin(), encodingParameters.size());
562                if (DHAES_MODE)
563                {
564                        byte L[8] = {0,0,0,0};
565                        PutWord(false, BIG_ENDIAN_ORDER, L+4, word32(encodingParameters.size()));
566                        mac.Update(L, 8);
567                }
568                if (!mac.Verify(ciphertext + plaintextLength))
569                        return DecodingResult();
570
571                if (plaintextLength)    // Coverity finding
572                        xorbuf(plaintext, ciphertext, cipherKey, plaintextLength);
573
574                return DecodingResult(plaintextLength);
575        }
576
577#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
578        virtual ~DL_EncryptionAlgorithm_Xor() {}
579#endif
580};
581
582//! _
583template <class T, bool DHAES_MODE, class KDF>
584class DL_KeyDerivationAlgorithm_P1363 : public DL_KeyDerivationAlgorithm<T>
585{
586public:
587        bool ParameterSupported(const char *name) const {return strcmp(name, Name::KeyDerivationParameters()) == 0;}
588        void Derive(const DL_GroupParameters<T> &params, byte *derivedKey, size_t derivedLength, const T &agreedElement, const T &ephemeralPublicKey, const NameValuePairs &parameters) const
589        {
590                SecByteBlock agreedSecret;
591                if (DHAES_MODE)
592                {
593                        agreedSecret.New(params.GetEncodedElementSize(true) + params.GetEncodedElementSize(false));
594                        params.EncodeElement(true, ephemeralPublicKey, agreedSecret);
595                        params.EncodeElement(false, agreedElement, agreedSecret + params.GetEncodedElementSize(true));
596                }
597                else
598                {
599                        agreedSecret.New(params.GetEncodedElementSize(false));
600                        params.EncodeElement(false, agreedElement, agreedSecret);
601                }
602
603                ConstByteArrayParameter derivationParameters;
604                parameters.GetValue(Name::KeyDerivationParameters(), derivationParameters);
605                KDF::DeriveKey(derivedKey, derivedLength, agreedSecret, agreedSecret.size(), derivationParameters.begin(), derivationParameters.size());
606        }
607
608#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
609        virtual ~DL_KeyDerivationAlgorithm_P1363() {}
610#endif
611};
612
613//! Discrete Log Integrated Encryption Scheme, AKA <a href="http://www.weidai.com/scan-mirror/ca.html#DLIES">DLIES</a>
614template <class COFACTOR_OPTION = NoCofactorMultiplication, bool DHAES_MODE = true>
615struct DLIES
616        : public DL_ES<
617                DL_CryptoKeys_GFP,
618                DL_KeyAgreementAlgorithm_DH<Integer, COFACTOR_OPTION>,
619                DL_KeyDerivationAlgorithm_P1363<Integer, DHAES_MODE, P1363_KDF2<SHA1> >,
620                DL_EncryptionAlgorithm_Xor<HMAC<SHA1>, DHAES_MODE>,
621                DLIES<> >
622{
623        static std::string CRYPTOPP_API StaticAlgorithmName() {return "DLIES";} // TODO: fix this after name is standardized
624
625#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
626        virtual ~DLIES() {}
627#endif
628};
629
630NAMESPACE_END
631
632#if CRYPTOPP_MSC_VERSION
633# pragma warning(pop)
634#endif
635
636#endif
Note: See TracBrowser for help on using the repository browser.