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