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 | |
---|
26 | NAMESPACE_BEGIN(CryptoPP) |
---|
27 | |
---|
28 | CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters<Integer>; |
---|
29 | |
---|
30 | //! _ |
---|
31 | class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE DL_GroupParameters_IntegerBased : public ASN1CryptoMaterial<DL_GroupParameters<Integer> > |
---|
32 | { |
---|
33 | typedef DL_GroupParameters_IntegerBased ThisClass; |
---|
34 | |
---|
35 | public: |
---|
36 | void Initialize(const DL_GroupParameters_IntegerBased ¶ms) |
---|
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 | |
---|
91 | protected: |
---|
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 | |
---|
99 | private: |
---|
100 | Integer m_q; |
---|
101 | }; |
---|
102 | |
---|
103 | //! _ |
---|
104 | template <class GROUP_PRECOMP, class BASE_PRECOMP = DL_FixedBasePrecomputationImpl<CPP_TYPENAME GROUP_PRECOMP::Element> > |
---|
105 | class 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 | |
---|
109 | public: |
---|
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 | |
---|
141 | CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_IntegerBasedImpl<ModExpPrecomputation>; |
---|
142 | |
---|
143 | //! GF(p) group parameters |
---|
144 | class CRYPTOPP_DLL DL_GroupParameters_GFP : public DL_GroupParameters_IntegerBasedImpl<ModExpPrecomputation> |
---|
145 | { |
---|
146 | public: |
---|
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 | |
---|
165 | protected: |
---|
166 | int GetFieldType() const {return 1;} |
---|
167 | }; |
---|
168 | |
---|
169 | //! GF(p) group parameters that default to same primes |
---|
170 | class CRYPTOPP_DLL DL_GroupParameters_GFP_DefaultSafePrime : public DL_GroupParameters_GFP |
---|
171 | { |
---|
172 | public: |
---|
173 | typedef NoCofactorMultiplication DefaultCofactorOption; |
---|
174 | |
---|
175 | #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562 |
---|
176 | virtual ~DL_GroupParameters_GFP_DefaultSafePrime() {} |
---|
177 | #endif |
---|
178 | |
---|
179 | protected: |
---|
180 | unsigned int GetDefaultSubgroupOrderSize(unsigned int modulusSize) const {return modulusSize-1;} |
---|
181 | }; |
---|
182 | |
---|
183 | //! GDSA algorithm |
---|
184 | template <class T> |
---|
185 | class DL_Algorithm_GDSA : public DL_ElgamalLikeSignatureAlgorithm<T> |
---|
186 | { |
---|
187 | public: |
---|
188 | CRYPTOPP_CONSTEXPR static const char * CRYPTOPP_API StaticAlgorithmName() {return "DSA-1363";} |
---|
189 | |
---|
190 | void Sign(const DL_GroupParameters<T> ¶ms, 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> ¶ms, 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 | |
---|
217 | CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_GDSA<Integer>; |
---|
218 | |
---|
219 | //! NR algorithm |
---|
220 | template <class T> |
---|
221 | class DL_Algorithm_NR : public DL_ElgamalLikeSignatureAlgorithm<T> |
---|
222 | { |
---|
223 | public: |
---|
224 | CRYPTOPP_CONSTEXPR static const char * CRYPTOPP_API StaticAlgorithmName() {return "NR";} |
---|
225 | |
---|
226 | void Sign(const DL_GroupParameters<T> ¶ms, 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> ¶ms, 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. */ |
---|
251 | template <class GP> |
---|
252 | class DL_PublicKey_GFP : public DL_PublicKeyImpl<GP> |
---|
253 | { |
---|
254 | public: |
---|
255 | void Initialize(const DL_GroupParameters_IntegerBased ¶ms, 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) |
---|
274 | template <class GP> |
---|
275 | class DL_PrivateKey_GFP : public DL_PrivateKeyImpl<GP> |
---|
276 | { |
---|
277 | public: |
---|
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 ¶ms, 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) |
---|
297 | struct 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) |
---|
309 | struct 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 |
---|
321 | template <class BASE> |
---|
322 | class DL_PublicKey_GFP_OldFormat : public BASE |
---|
323 | { |
---|
324 | public: |
---|
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 |
---|
364 | template <class BASE> |
---|
365 | class DL_PrivateKey_GFP_OldFormat : public BASE |
---|
366 | { |
---|
367 | public: |
---|
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> |
---|
409 | template <class H> |
---|
410 | struct 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> |
---|
422 | template <class H> |
---|
423 | struct 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 |
---|
435 | class CRYPTOPP_DLL DL_GroupParameters_DSA : public DL_GroupParameters_GFP |
---|
436 | { |
---|
437 | public: |
---|
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 | |
---|
454 | template <class H> |
---|
455 | class DSA2; |
---|
456 | |
---|
457 | //! DSA keys |
---|
458 | struct 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) |
---|
470 | template <class H> |
---|
471 | class DSA2 : public DL_SS< |
---|
472 | DL_Keys_DSA, |
---|
473 | DL_Algorithm_GDSA<Integer>, |
---|
474 | DL_SignatureMessageEncodingMethod_DSA, |
---|
475 | H, |
---|
476 | DSA2<H> > |
---|
477 | { |
---|
478 | public: |
---|
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 |
---|
491 | typedef DSA2<SHA> DSA; |
---|
492 | |
---|
493 | CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_GFP<DL_GroupParameters_DSA>; |
---|
494 | CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_GFP<DL_GroupParameters_DSA>; |
---|
495 | CRYPTOPP_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 |
---|
498 | template <class MAC, bool DHAES_MODE> |
---|
499 | class DL_EncryptionAlgorithm_Xor : public DL_SymmetricEncryptionAlgorithm |
---|
500 | { |
---|
501 | public: |
---|
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 ¶meters) 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 ¶meters) 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 | //! _ |
---|
583 | template <class T, bool DHAES_MODE, class KDF> |
---|
584 | class DL_KeyDerivationAlgorithm_P1363 : public DL_KeyDerivationAlgorithm<T> |
---|
585 | { |
---|
586 | public: |
---|
587 | bool ParameterSupported(const char *name) const {return strcmp(name, Name::KeyDerivationParameters()) == 0;} |
---|
588 | void Derive(const DL_GroupParameters<T> ¶ms, byte *derivedKey, size_t derivedLength, const T &agreedElement, const T &ephemeralPublicKey, const NameValuePairs ¶meters) 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> |
---|
614 | template <class COFACTOR_OPTION = NoCofactorMultiplication, bool DHAES_MODE = true> |
---|
615 | struct 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 | |
---|
630 | NAMESPACE_END |
---|
631 | |
---|
632 | #if CRYPTOPP_MSC_VERSION |
---|
633 | # pragma warning(pop) |
---|
634 | #endif |
---|
635 | |
---|
636 | #endif |
---|