Crypto++
|
00001 // pubkey.h - written and placed in the public domain by Wei Dai 00002 00003 #ifndef CRYPTOPP_PUBKEY_H 00004 #define CRYPTOPP_PUBKEY_H 00005 00006 /** \file 00007 00008 This file contains helper classes/functions for implementing public key algorithms. 00009 00010 The class hierachies in this .h file tend to look like this: 00011 <pre> 00012 x1 00013 / \ 00014 y1 z1 00015 | | 00016 x2<y1> x2<z1> 00017 | | 00018 y2 z2 00019 | | 00020 x3<y2> x3<z2> 00021 | | 00022 y3 z3 00023 </pre> 00024 - x1, y1, z1 are abstract interface classes defined in cryptlib.h 00025 - x2, y2, z2 are implementations of the interfaces using "abstract policies", which 00026 are pure virtual functions that should return interfaces to interchangeable algorithms. 00027 These classes have "Base" suffixes. 00028 - x3, y3, z3 hold actual algorithms and implement those virtual functions. 00029 These classes have "Impl" suffixes. 00030 00031 The "TF_" prefix means an implementation using trapdoor functions on integers. 00032 The "DL_" prefix means an implementation using group operations (in groups where discrete log is hard). 00033 */ 00034 00035 #include "modarith.h" 00036 #include "filters.h" 00037 #include "eprecomp.h" 00038 #include "fips140.h" 00039 #include "argnames.h" 00040 #include <memory> 00041 00042 // VC60 workaround: this macro is defined in shlobj.h and conflicts with a template parameter used in this file 00043 #undef INTERFACE 00044 00045 NAMESPACE_BEGIN(CryptoPP) 00046 00047 //! _ 00048 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TrapdoorFunctionBounds 00049 { 00050 public: 00051 virtual ~TrapdoorFunctionBounds() {} 00052 00053 virtual Integer PreimageBound() const =0; 00054 virtual Integer ImageBound() const =0; 00055 virtual Integer MaxPreimage() const {return --PreimageBound();} 00056 virtual Integer MaxImage() const {return --ImageBound();} 00057 }; 00058 00059 //! _ 00060 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE RandomizedTrapdoorFunction : public TrapdoorFunctionBounds 00061 { 00062 public: 00063 virtual Integer ApplyRandomizedFunction(RandomNumberGenerator &rng, const Integer &x) const =0; 00064 virtual bool IsRandomized() const {return true;} 00065 }; 00066 00067 //! _ 00068 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TrapdoorFunction : public RandomizedTrapdoorFunction 00069 { 00070 public: 00071 Integer ApplyRandomizedFunction(RandomNumberGenerator &rng, const Integer &x) const 00072 {return ApplyFunction(x);} 00073 bool IsRandomized() const {return false;} 00074 00075 virtual Integer ApplyFunction(const Integer &x) const =0; 00076 }; 00077 00078 //! _ 00079 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE RandomizedTrapdoorFunctionInverse 00080 { 00081 public: 00082 virtual ~RandomizedTrapdoorFunctionInverse() {} 00083 00084 virtual Integer CalculateRandomizedInverse(RandomNumberGenerator &rng, const Integer &x) const =0; 00085 virtual bool IsRandomized() const {return true;} 00086 }; 00087 00088 //! _ 00089 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TrapdoorFunctionInverse : public RandomizedTrapdoorFunctionInverse 00090 { 00091 public: 00092 virtual ~TrapdoorFunctionInverse() {} 00093 00094 Integer CalculateRandomizedInverse(RandomNumberGenerator &rng, const Integer &x) const 00095 {return CalculateInverse(rng, x);} 00096 bool IsRandomized() const {return false;} 00097 00098 virtual Integer CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const =0; 00099 }; 00100 00101 // ******************************************************** 00102 00103 //! message encoding method for public key encryption 00104 class CRYPTOPP_NO_VTABLE PK_EncryptionMessageEncodingMethod 00105 { 00106 public: 00107 virtual ~PK_EncryptionMessageEncodingMethod() {} 00108 00109 virtual bool ParameterSupported(const char *name) const {return false;} 00110 00111 //! max size of unpadded message in bytes, given max size of padded message in bits (1 less than size of modulus) 00112 virtual size_t MaxUnpaddedLength(size_t paddedLength) const =0; 00113 00114 virtual void Pad(RandomNumberGenerator &rng, const byte *raw, size_t inputLength, byte *padded, size_t paddedBitLength, const NameValuePairs ¶meters) const =0; 00115 00116 virtual DecodingResult Unpad(const byte *padded, size_t paddedBitLength, byte *raw, const NameValuePairs ¶meters) const =0; 00117 }; 00118 00119 // ******************************************************** 00120 00121 //! _ 00122 template <class TFI, class MEI> 00123 class CRYPTOPP_NO_VTABLE TF_Base 00124 { 00125 protected: 00126 virtual const TrapdoorFunctionBounds & GetTrapdoorFunctionBounds() const =0; 00127 00128 typedef TFI TrapdoorFunctionInterface; 00129 virtual const TrapdoorFunctionInterface & GetTrapdoorFunctionInterface() const =0; 00130 00131 typedef MEI MessageEncodingInterface; 00132 virtual const MessageEncodingInterface & GetMessageEncodingInterface() const =0; 00133 }; 00134 00135 // ******************************************************** 00136 00137 //! _ 00138 template <class BASE> 00139 class CRYPTOPP_NO_VTABLE PK_FixedLengthCryptoSystemImpl : public BASE 00140 { 00141 public: 00142 size_t MaxPlaintextLength(size_t ciphertextLength) const 00143 {return ciphertextLength == FixedCiphertextLength() ? FixedMaxPlaintextLength() : 0;} 00144 size_t CiphertextLength(size_t plaintextLength) const 00145 {return plaintextLength <= FixedMaxPlaintextLength() ? FixedCiphertextLength() : 0;} 00146 00147 virtual size_t FixedMaxPlaintextLength() const =0; 00148 virtual size_t FixedCiphertextLength() const =0; 00149 }; 00150 00151 //! _ 00152 template <class INTERFACE, class BASE> 00153 class CRYPTOPP_NO_VTABLE TF_CryptoSystemBase : public PK_FixedLengthCryptoSystemImpl<INTERFACE>, protected BASE 00154 { 00155 public: 00156 bool ParameterSupported(const char *name) const {return this->GetMessageEncodingInterface().ParameterSupported(name);} 00157 size_t FixedMaxPlaintextLength() const {return this->GetMessageEncodingInterface().MaxUnpaddedLength(PaddedBlockBitLength());} 00158 size_t FixedCiphertextLength() const {return this->GetTrapdoorFunctionBounds().MaxImage().ByteCount();} 00159 00160 protected: 00161 size_t PaddedBlockByteLength() const {return BitsToBytes(PaddedBlockBitLength());} 00162 size_t PaddedBlockBitLength() const {return this->GetTrapdoorFunctionBounds().PreimageBound().BitCount()-1;} 00163 }; 00164 00165 //! _ 00166 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_DecryptorBase : public TF_CryptoSystemBase<PK_Decryptor, TF_Base<TrapdoorFunctionInverse, PK_EncryptionMessageEncodingMethod> > 00167 { 00168 public: 00169 DecodingResult Decrypt(RandomNumberGenerator &rng, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs ¶meters = g_nullNameValuePairs) const; 00170 }; 00171 00172 //! _ 00173 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_EncryptorBase : public TF_CryptoSystemBase<PK_Encryptor, TF_Base<RandomizedTrapdoorFunction, PK_EncryptionMessageEncodingMethod> > 00174 { 00175 public: 00176 void Encrypt(RandomNumberGenerator &rng, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs ¶meters = g_nullNameValuePairs) const; 00177 }; 00178 00179 // ******************************************************** 00180 00181 typedef std::pair<const byte *, size_t> HashIdentifier; 00182 00183 //! interface for message encoding method for public key signature schemes 00184 class CRYPTOPP_NO_VTABLE PK_SignatureMessageEncodingMethod 00185 { 00186 public: 00187 virtual ~PK_SignatureMessageEncodingMethod() {} 00188 00189 virtual size_t MinRepresentativeBitLength(size_t hashIdentifierLength, size_t digestLength) const 00190 {return 0;} 00191 virtual size_t MaxRecoverableLength(size_t representativeBitLength, size_t hashIdentifierLength, size_t digestLength) const 00192 {return 0;} 00193 00194 bool IsProbabilistic() const 00195 {return true;} 00196 bool AllowNonrecoverablePart() const 00197 {throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");} 00198 virtual bool RecoverablePartFirst() const 00199 {throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");} 00200 00201 // for verification, DL 00202 virtual void ProcessSemisignature(HashTransformation &hash, const byte *semisignature, size_t semisignatureLength) const {} 00203 00204 // for signature 00205 virtual void ProcessRecoverableMessage(HashTransformation &hash, 00206 const byte *recoverableMessage, size_t recoverableMessageLength, 00207 const byte *presignature, size_t presignatureLength, 00208 SecByteBlock &semisignature) const 00209 { 00210 if (RecoverablePartFirst()) 00211 assert(!"ProcessRecoverableMessage() not implemented"); 00212 } 00213 00214 virtual void ComputeMessageRepresentative(RandomNumberGenerator &rng, 00215 const byte *recoverableMessage, size_t recoverableMessageLength, 00216 HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, 00217 byte *representative, size_t representativeBitLength) const =0; 00218 00219 virtual bool VerifyMessageRepresentative( 00220 HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, 00221 byte *representative, size_t representativeBitLength) const =0; 00222 00223 virtual DecodingResult RecoverMessageFromRepresentative( // for TF 00224 HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, 00225 byte *representative, size_t representativeBitLength, 00226 byte *recoveredMessage) const 00227 {throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");} 00228 00229 virtual DecodingResult RecoverMessageFromSemisignature( // for DL 00230 HashTransformation &hash, HashIdentifier hashIdentifier, 00231 const byte *presignature, size_t presignatureLength, 00232 const byte *semisignature, size_t semisignatureLength, 00233 byte *recoveredMessage) const 00234 {throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");} 00235 00236 // VC60 workaround 00237 struct HashIdentifierLookup 00238 { 00239 template <class H> struct HashIdentifierLookup2 00240 { 00241 static HashIdentifier CRYPTOPP_API Lookup() 00242 { 00243 return HashIdentifier((const byte *)NULL, 0); 00244 } 00245 }; 00246 }; 00247 }; 00248 00249 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_DeterministicSignatureMessageEncodingMethod : public PK_SignatureMessageEncodingMethod 00250 { 00251 public: 00252 bool VerifyMessageRepresentative( 00253 HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, 00254 byte *representative, size_t representativeBitLength) const; 00255 }; 00256 00257 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_RecoverableSignatureMessageEncodingMethod : public PK_SignatureMessageEncodingMethod 00258 { 00259 public: 00260 bool VerifyMessageRepresentative( 00261 HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, 00262 byte *representative, size_t representativeBitLength) const; 00263 }; 00264 00265 class CRYPTOPP_DLL DL_SignatureMessageEncodingMethod_DSA : public PK_DeterministicSignatureMessageEncodingMethod 00266 { 00267 public: 00268 void ComputeMessageRepresentative(RandomNumberGenerator &rng, 00269 const byte *recoverableMessage, size_t recoverableMessageLength, 00270 HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, 00271 byte *representative, size_t representativeBitLength) const; 00272 }; 00273 00274 class CRYPTOPP_DLL DL_SignatureMessageEncodingMethod_NR : public PK_DeterministicSignatureMessageEncodingMethod 00275 { 00276 public: 00277 void ComputeMessageRepresentative(RandomNumberGenerator &rng, 00278 const byte *recoverableMessage, size_t recoverableMessageLength, 00279 HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, 00280 byte *representative, size_t representativeBitLength) const; 00281 }; 00282 00283 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_MessageAccumulatorBase : public PK_MessageAccumulator 00284 { 00285 public: 00286 PK_MessageAccumulatorBase() : m_empty(true) {} 00287 00288 virtual HashTransformation & AccessHash() =0; 00289 00290 void Update(const byte *input, size_t length) 00291 { 00292 AccessHash().Update(input, length); 00293 m_empty = m_empty && length == 0; 00294 } 00295 00296 SecByteBlock m_recoverableMessage, m_representative, m_presignature, m_semisignature; 00297 Integer m_k, m_s; 00298 bool m_empty; 00299 }; 00300 00301 template <class HASH_ALGORITHM> 00302 class PK_MessageAccumulatorImpl : public PK_MessageAccumulatorBase, protected ObjectHolder<HASH_ALGORITHM> 00303 { 00304 public: 00305 HashTransformation & AccessHash() {return this->m_object;} 00306 }; 00307 00308 //! _ 00309 template <class INTERFACE, class BASE> 00310 class CRYPTOPP_NO_VTABLE TF_SignatureSchemeBase : public INTERFACE, protected BASE 00311 { 00312 public: 00313 size_t SignatureLength() const 00314 {return this->GetTrapdoorFunctionBounds().MaxPreimage().ByteCount();} 00315 size_t MaxRecoverableLength() const 00316 {return this->GetMessageEncodingInterface().MaxRecoverableLength(MessageRepresentativeBitLength(), GetHashIdentifier().second, GetDigestSize());} 00317 size_t MaxRecoverableLengthFromSignatureLength(size_t signatureLength) const 00318 {return this->MaxRecoverableLength();} 00319 00320 bool IsProbabilistic() const 00321 {return this->GetTrapdoorFunctionInterface().IsRandomized() || this->GetMessageEncodingInterface().IsProbabilistic();} 00322 bool AllowNonrecoverablePart() const 00323 {return this->GetMessageEncodingInterface().AllowNonrecoverablePart();} 00324 bool RecoverablePartFirst() const 00325 {return this->GetMessageEncodingInterface().RecoverablePartFirst();} 00326 00327 protected: 00328 size_t MessageRepresentativeLength() const {return BitsToBytes(MessageRepresentativeBitLength());} 00329 size_t MessageRepresentativeBitLength() const {return this->GetTrapdoorFunctionBounds().ImageBound().BitCount()-1;} 00330 virtual HashIdentifier GetHashIdentifier() const =0; 00331 virtual size_t GetDigestSize() const =0; 00332 }; 00333 00334 //! _ 00335 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_SignerBase : public TF_SignatureSchemeBase<PK_Signer, TF_Base<RandomizedTrapdoorFunctionInverse, PK_SignatureMessageEncodingMethod> > 00336 { 00337 public: 00338 void InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, size_t recoverableMessageLength) const; 00339 size_t SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart=true) const; 00340 }; 00341 00342 //! _ 00343 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_VerifierBase : public TF_SignatureSchemeBase<PK_Verifier, TF_Base<TrapdoorFunction, PK_SignatureMessageEncodingMethod> > 00344 { 00345 public: 00346 void InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, size_t signatureLength) const; 00347 bool VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const; 00348 DecodingResult RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &recoveryAccumulator) const; 00349 }; 00350 00351 // ******************************************************** 00352 00353 //! _ 00354 template <class T1, class T2, class T3> 00355 struct TF_CryptoSchemeOptions 00356 { 00357 typedef T1 AlgorithmInfo; 00358 typedef T2 Keys; 00359 typedef typename Keys::PrivateKey PrivateKey; 00360 typedef typename Keys::PublicKey PublicKey; 00361 typedef T3 MessageEncodingMethod; 00362 }; 00363 00364 //! _ 00365 template <class T1, class T2, class T3, class T4> 00366 struct TF_SignatureSchemeOptions : public TF_CryptoSchemeOptions<T1, T2, T3> 00367 { 00368 typedef T4 HashFunction; 00369 }; 00370 00371 //! _ 00372 template <class BASE, class SCHEME_OPTIONS, class KEY_CLASS> 00373 class CRYPTOPP_NO_VTABLE TF_ObjectImplBase : public AlgorithmImpl<BASE, typename SCHEME_OPTIONS::AlgorithmInfo> 00374 { 00375 public: 00376 typedef SCHEME_OPTIONS SchemeOptions; 00377 typedef KEY_CLASS KeyClass; 00378 00379 PublicKey & AccessPublicKey() {return AccessKey();} 00380 const PublicKey & GetPublicKey() const {return GetKey();} 00381 00382 PrivateKey & AccessPrivateKey() {return AccessKey();} 00383 const PrivateKey & GetPrivateKey() const {return GetKey();} 00384 00385 virtual const KeyClass & GetKey() const =0; 00386 virtual KeyClass & AccessKey() =0; 00387 00388 const KeyClass & GetTrapdoorFunction() const {return GetKey();} 00389 00390 PK_MessageAccumulator * NewSignatureAccumulator(RandomNumberGenerator &rng) const 00391 { 00392 return new PK_MessageAccumulatorImpl<CPP_TYPENAME SCHEME_OPTIONS::HashFunction>; 00393 } 00394 PK_MessageAccumulator * NewVerificationAccumulator() const 00395 { 00396 return new PK_MessageAccumulatorImpl<CPP_TYPENAME SCHEME_OPTIONS::HashFunction>; 00397 } 00398 00399 protected: 00400 const typename BASE::MessageEncodingInterface & GetMessageEncodingInterface() const 00401 {return Singleton<CPP_TYPENAME SCHEME_OPTIONS::MessageEncodingMethod>().Ref();} 00402 const TrapdoorFunctionBounds & GetTrapdoorFunctionBounds() const 00403 {return GetKey();} 00404 const typename BASE::TrapdoorFunctionInterface & GetTrapdoorFunctionInterface() const 00405 {return GetKey();} 00406 00407 // for signature scheme 00408 HashIdentifier GetHashIdentifier() const 00409 { 00410 typedef CPP_TYPENAME SchemeOptions::MessageEncodingMethod::HashIdentifierLookup::template HashIdentifierLookup2<CPP_TYPENAME SchemeOptions::HashFunction> L; 00411 return L::Lookup(); 00412 } 00413 size_t GetDigestSize() const 00414 { 00415 typedef CPP_TYPENAME SchemeOptions::HashFunction H; 00416 return H::DIGESTSIZE; 00417 } 00418 }; 00419 00420 //! _ 00421 template <class BASE, class SCHEME_OPTIONS, class KEY> 00422 class TF_ObjectImplExtRef : public TF_ObjectImplBase<BASE, SCHEME_OPTIONS, KEY> 00423 { 00424 public: 00425 TF_ObjectImplExtRef(const KEY *pKey = NULL) : m_pKey(pKey) {} 00426 void SetKeyPtr(const KEY *pKey) {m_pKey = pKey;} 00427 00428 const KEY & GetKey() const {return *m_pKey;} 00429 KEY & AccessKey() {throw NotImplemented("TF_ObjectImplExtRef: cannot modify refererenced key");} 00430 00431 private: 00432 const KEY * m_pKey; 00433 }; 00434 00435 //! _ 00436 template <class BASE, class SCHEME_OPTIONS, class KEY_CLASS> 00437 class CRYPTOPP_NO_VTABLE TF_ObjectImpl : public TF_ObjectImplBase<BASE, SCHEME_OPTIONS, KEY_CLASS> 00438 { 00439 public: 00440 typedef KEY_CLASS KeyClass; 00441 00442 const KeyClass & GetKey() const {return m_trapdoorFunction;} 00443 KeyClass & AccessKey() {return m_trapdoorFunction;} 00444 00445 private: 00446 KeyClass m_trapdoorFunction; 00447 }; 00448 00449 //! _ 00450 template <class SCHEME_OPTIONS> 00451 class TF_DecryptorImpl : public TF_ObjectImpl<TF_DecryptorBase, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PrivateKey> 00452 { 00453 }; 00454 00455 //! _ 00456 template <class SCHEME_OPTIONS> 00457 class TF_EncryptorImpl : public TF_ObjectImpl<TF_EncryptorBase, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PublicKey> 00458 { 00459 }; 00460 00461 //! _ 00462 template <class SCHEME_OPTIONS> 00463 class TF_SignerImpl : public TF_ObjectImpl<TF_SignerBase, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PrivateKey> 00464 { 00465 }; 00466 00467 //! _ 00468 template <class SCHEME_OPTIONS> 00469 class TF_VerifierImpl : public TF_ObjectImpl<TF_VerifierBase, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PublicKey> 00470 { 00471 }; 00472 00473 // ******************************************************** 00474 00475 //! _ 00476 class CRYPTOPP_NO_VTABLE MaskGeneratingFunction 00477 { 00478 public: 00479 virtual ~MaskGeneratingFunction() {} 00480 virtual void GenerateAndMask(HashTransformation &hash, byte *output, size_t outputLength, const byte *input, size_t inputLength, bool mask = true) const =0; 00481 }; 00482 00483 CRYPTOPP_DLL void CRYPTOPP_API P1363_MGF1KDF2_Common(HashTransformation &hash, byte *output, size_t outputLength, const byte *input, size_t inputLength, const byte *derivationParams, size_t derivationParamsLength, bool mask, unsigned int counterStart); 00484 00485 //! _ 00486 class P1363_MGF1 : public MaskGeneratingFunction 00487 { 00488 public: 00489 static const char * CRYPTOPP_API StaticAlgorithmName() {return "MGF1";} 00490 void GenerateAndMask(HashTransformation &hash, byte *output, size_t outputLength, const byte *input, size_t inputLength, bool mask = true) const 00491 { 00492 P1363_MGF1KDF2_Common(hash, output, outputLength, input, inputLength, NULL, 0, mask, 0); 00493 } 00494 }; 00495 00496 // ******************************************************** 00497 00498 //! _ 00499 template <class H> 00500 class P1363_KDF2 00501 { 00502 public: 00503 static void CRYPTOPP_API DeriveKey(byte *output, size_t outputLength, const byte *input, size_t inputLength, const byte *derivationParams, size_t derivationParamsLength) 00504 { 00505 H h; 00506 P1363_MGF1KDF2_Common(h, output, outputLength, input, inputLength, derivationParams, derivationParamsLength, false, 1); 00507 } 00508 }; 00509 00510 // ******************************************************** 00511 00512 //! to be thrown by DecodeElement and AgreeWithStaticPrivateKey 00513 class DL_BadElement : public InvalidDataFormat 00514 { 00515 public: 00516 DL_BadElement() : InvalidDataFormat("CryptoPP: invalid group element") {} 00517 }; 00518 00519 //! interface for DL group parameters 00520 template <class T> 00521 class CRYPTOPP_NO_VTABLE DL_GroupParameters : public CryptoParameters 00522 { 00523 typedef DL_GroupParameters<T> ThisClass; 00524 00525 public: 00526 typedef T Element; 00527 00528 DL_GroupParameters() : m_validationLevel(0) {} 00529 00530 // CryptoMaterial 00531 bool Validate(RandomNumberGenerator &rng, unsigned int level) const 00532 { 00533 if (!GetBasePrecomputation().IsInitialized()) 00534 return false; 00535 00536 if (m_validationLevel > level) 00537 return true; 00538 00539 bool pass = ValidateGroup(rng, level); 00540 pass = pass && ValidateElement(level, GetSubgroupGenerator(), &GetBasePrecomputation()); 00541 00542 m_validationLevel = pass ? level+1 : 0; 00543 00544 return pass; 00545 } 00546 00547 bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const 00548 { 00549 return GetValueHelper(this, name, valueType, pValue) 00550 CRYPTOPP_GET_FUNCTION_ENTRY(SubgroupOrder) 00551 CRYPTOPP_GET_FUNCTION_ENTRY(SubgroupGenerator) 00552 ; 00553 } 00554 00555 bool SupportsPrecomputation() const {return true;} 00556 00557 void Precompute(unsigned int precomputationStorage=16) 00558 { 00559 AccessBasePrecomputation().Precompute(GetGroupPrecomputation(), GetSubgroupOrder().BitCount(), precomputationStorage); 00560 } 00561 00562 void LoadPrecomputation(BufferedTransformation &storedPrecomputation) 00563 { 00564 AccessBasePrecomputation().Load(GetGroupPrecomputation(), storedPrecomputation); 00565 m_validationLevel = 0; 00566 } 00567 00568 void SavePrecomputation(BufferedTransformation &storedPrecomputation) const 00569 { 00570 GetBasePrecomputation().Save(GetGroupPrecomputation(), storedPrecomputation); 00571 } 00572 00573 // non-inherited 00574 virtual const Element & GetSubgroupGenerator() const {return GetBasePrecomputation().GetBase(GetGroupPrecomputation());} 00575 virtual void SetSubgroupGenerator(const Element &base) {AccessBasePrecomputation().SetBase(GetGroupPrecomputation(), base);} 00576 virtual Element ExponentiateBase(const Integer &exponent) const 00577 { 00578 return GetBasePrecomputation().Exponentiate(GetGroupPrecomputation(), exponent); 00579 } 00580 virtual Element ExponentiateElement(const Element &base, const Integer &exponent) const 00581 { 00582 Element result; 00583 SimultaneousExponentiate(&result, base, &exponent, 1); 00584 return result; 00585 } 00586 00587 virtual const DL_GroupPrecomputation<Element> & GetGroupPrecomputation() const =0; 00588 virtual const DL_FixedBasePrecomputation<Element> & GetBasePrecomputation() const =0; 00589 virtual DL_FixedBasePrecomputation<Element> & AccessBasePrecomputation() =0; 00590 virtual const Integer & GetSubgroupOrder() const =0; // order of subgroup generated by base element 00591 virtual Integer GetMaxExponent() const =0; 00592 virtual Integer GetGroupOrder() const {return GetSubgroupOrder()*GetCofactor();} // one of these two needs to be overriden 00593 virtual Integer GetCofactor() const {return GetGroupOrder()/GetSubgroupOrder();} 00594 virtual unsigned int GetEncodedElementSize(bool reversible) const =0; 00595 virtual void EncodeElement(bool reversible, const Element &element, byte *encoded) const =0; 00596 virtual Element DecodeElement(const byte *encoded, bool checkForGroupMembership) const =0; 00597 virtual Integer ConvertElementToInteger(const Element &element) const =0; 00598 virtual bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const =0; 00599 virtual bool ValidateElement(unsigned int level, const Element &element, const DL_FixedBasePrecomputation<Element> *precomp) const =0; 00600 virtual bool FastSubgroupCheckAvailable() const =0; 00601 virtual bool IsIdentity(const Element &element) const =0; 00602 virtual void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const =0; 00603 00604 protected: 00605 void ParametersChanged() {m_validationLevel = 0;} 00606 00607 private: 00608 mutable unsigned int m_validationLevel; 00609 }; 00610 00611 //! _ 00612 template <class GROUP_PRECOMP, class BASE_PRECOMP = DL_FixedBasePrecomputationImpl<CPP_TYPENAME GROUP_PRECOMP::Element>, class BASE = DL_GroupParameters<CPP_TYPENAME GROUP_PRECOMP::Element> > 00613 class DL_GroupParametersImpl : public BASE 00614 { 00615 public: 00616 typedef GROUP_PRECOMP GroupPrecomputation; 00617 typedef typename GROUP_PRECOMP::Element Element; 00618 typedef BASE_PRECOMP BasePrecomputation; 00619 00620 const DL_GroupPrecomputation<Element> & GetGroupPrecomputation() const {return m_groupPrecomputation;} 00621 const DL_FixedBasePrecomputation<Element> & GetBasePrecomputation() const {return m_gpc;} 00622 DL_FixedBasePrecomputation<Element> & AccessBasePrecomputation() {return m_gpc;} 00623 00624 protected: 00625 GROUP_PRECOMP m_groupPrecomputation; 00626 BASE_PRECOMP m_gpc; 00627 }; 00628 00629 //! _ 00630 template <class T> 00631 class CRYPTOPP_NO_VTABLE DL_Key 00632 { 00633 public: 00634 virtual const DL_GroupParameters<T> & GetAbstractGroupParameters() const =0; 00635 virtual DL_GroupParameters<T> & AccessAbstractGroupParameters() =0; 00636 }; 00637 00638 //! interface for DL public keys 00639 template <class T> 00640 class CRYPTOPP_NO_VTABLE DL_PublicKey : public DL_Key<T> 00641 { 00642 typedef DL_PublicKey<T> ThisClass; 00643 00644 public: 00645 typedef T Element; 00646 00647 bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const 00648 { 00649 return GetValueHelper(this, name, valueType, pValue, &this->GetAbstractGroupParameters()) 00650 CRYPTOPP_GET_FUNCTION_ENTRY(PublicElement); 00651 } 00652 00653 void AssignFrom(const NameValuePairs &source); 00654 00655 // non-inherited 00656 virtual const Element & GetPublicElement() const {return GetPublicPrecomputation().GetBase(this->GetAbstractGroupParameters().GetGroupPrecomputation());} 00657 virtual void SetPublicElement(const Element &y) {AccessPublicPrecomputation().SetBase(this->GetAbstractGroupParameters().GetGroupPrecomputation(), y);} 00658 virtual Element ExponentiatePublicElement(const Integer &exponent) const 00659 { 00660 const DL_GroupParameters<T> ¶ms = this->GetAbstractGroupParameters(); 00661 return GetPublicPrecomputation().Exponentiate(params.GetGroupPrecomputation(), exponent); 00662 } 00663 virtual Element CascadeExponentiateBaseAndPublicElement(const Integer &baseExp, const Integer &publicExp) const 00664 { 00665 const DL_GroupParameters<T> ¶ms = this->GetAbstractGroupParameters(); 00666 return params.GetBasePrecomputation().CascadeExponentiate(params.GetGroupPrecomputation(), baseExp, GetPublicPrecomputation(), publicExp); 00667 } 00668 00669 virtual const DL_FixedBasePrecomputation<T> & GetPublicPrecomputation() const =0; 00670 virtual DL_FixedBasePrecomputation<T> & AccessPublicPrecomputation() =0; 00671 }; 00672 00673 //! interface for DL private keys 00674 template <class T> 00675 class CRYPTOPP_NO_VTABLE DL_PrivateKey : public DL_Key<T> 00676 { 00677 typedef DL_PrivateKey<T> ThisClass; 00678 00679 public: 00680 typedef T Element; 00681 00682 void MakePublicKey(DL_PublicKey<T> &pub) const 00683 { 00684 pub.AccessAbstractGroupParameters().AssignFrom(this->GetAbstractGroupParameters()); 00685 pub.SetPublicElement(this->GetAbstractGroupParameters().ExponentiateBase(GetPrivateExponent())); 00686 } 00687 00688 bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const 00689 { 00690 return GetValueHelper(this, name, valueType, pValue, &this->GetAbstractGroupParameters()) 00691 CRYPTOPP_GET_FUNCTION_ENTRY(PrivateExponent); 00692 } 00693 00694 void AssignFrom(const NameValuePairs &source) 00695 { 00696 this->AccessAbstractGroupParameters().AssignFrom(source); 00697 AssignFromHelper(this, source) 00698 CRYPTOPP_SET_FUNCTION_ENTRY(PrivateExponent); 00699 } 00700 00701 virtual const Integer & GetPrivateExponent() const =0; 00702 virtual void SetPrivateExponent(const Integer &x) =0; 00703 }; 00704 00705 template <class T> 00706 void DL_PublicKey<T>::AssignFrom(const NameValuePairs &source) 00707 { 00708 DL_PrivateKey<T> *pPrivateKey = NULL; 00709 if (source.GetThisPointer(pPrivateKey)) 00710 pPrivateKey->MakePublicKey(*this); 00711 else 00712 { 00713 this->AccessAbstractGroupParameters().AssignFrom(source); 00714 AssignFromHelper(this, source) 00715 CRYPTOPP_SET_FUNCTION_ENTRY(PublicElement); 00716 } 00717 } 00718 00719 class OID; 00720 00721 //! _ 00722 template <class PK, class GP, class O = OID> 00723 class DL_KeyImpl : public PK 00724 { 00725 public: 00726 typedef GP GroupParameters; 00727 00728 O GetAlgorithmID() const {return GetGroupParameters().GetAlgorithmID();} 00729 // void BERDecode(BufferedTransformation &bt) 00730 // {PK::BERDecode(bt);} 00731 // void DEREncode(BufferedTransformation &bt) const 00732 // {PK::DEREncode(bt);} 00733 bool BERDecodeAlgorithmParameters(BufferedTransformation &bt) 00734 {AccessGroupParameters().BERDecode(bt); return true;} 00735 bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const 00736 {GetGroupParameters().DEREncode(bt); return true;} 00737 00738 const GP & GetGroupParameters() const {return m_groupParameters;} 00739 GP & AccessGroupParameters() {return m_groupParameters;} 00740 00741 private: 00742 GP m_groupParameters; 00743 }; 00744 00745 class X509PublicKey; 00746 class PKCS8PrivateKey; 00747 00748 //! _ 00749 template <class GP> 00750 class DL_PrivateKeyImpl : public DL_PrivateKey<CPP_TYPENAME GP::Element>, public DL_KeyImpl<PKCS8PrivateKey, GP> 00751 { 00752 public: 00753 typedef typename GP::Element Element; 00754 00755 // GeneratableCryptoMaterial 00756 bool Validate(RandomNumberGenerator &rng, unsigned int level) const 00757 { 00758 bool pass = GetAbstractGroupParameters().Validate(rng, level); 00759 00760 const Integer &q = GetAbstractGroupParameters().GetSubgroupOrder(); 00761 const Integer &x = GetPrivateExponent(); 00762 00763 pass = pass && x.IsPositive() && x < q; 00764 if (level >= 1) 00765 pass = pass && Integer::Gcd(x, q) == Integer::One(); 00766 return pass; 00767 } 00768 00769 bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const 00770 { 00771 return GetValueHelper<DL_PrivateKey<Element> >(this, name, valueType, pValue).Assignable(); 00772 } 00773 00774 void AssignFrom(const NameValuePairs &source) 00775 { 00776 AssignFromHelper<DL_PrivateKey<Element> >(this, source); 00777 } 00778 00779 void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs ¶ms) 00780 { 00781 if (!params.GetThisObject(this->AccessGroupParameters())) 00782 this->AccessGroupParameters().GenerateRandom(rng, params); 00783 // std::pair<const byte *, int> seed; 00784 Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent()); 00785 // Integer::ANY, Integer::Zero(), Integer::One(), 00786 // params.GetValue("DeterministicKeyGenerationSeed", seed) ? &seed : NULL); 00787 SetPrivateExponent(x); 00788 } 00789 00790 bool SupportsPrecomputation() const {return true;} 00791 00792 void Precompute(unsigned int precomputationStorage=16) 00793 {AccessAbstractGroupParameters().Precompute(precomputationStorage);} 00794 00795 void LoadPrecomputation(BufferedTransformation &storedPrecomputation) 00796 {AccessAbstractGroupParameters().LoadPrecomputation(storedPrecomputation);} 00797 00798 void SavePrecomputation(BufferedTransformation &storedPrecomputation) const 00799 {GetAbstractGroupParameters().SavePrecomputation(storedPrecomputation);} 00800 00801 // DL_Key 00802 const DL_GroupParameters<Element> & GetAbstractGroupParameters() const {return this->GetGroupParameters();} 00803 DL_GroupParameters<Element> & AccessAbstractGroupParameters() {return this->AccessGroupParameters();} 00804 00805 // DL_PrivateKey 00806 const Integer & GetPrivateExponent() const {return m_x;} 00807 void SetPrivateExponent(const Integer &x) {m_x = x;} 00808 00809 // PKCS8PrivateKey 00810 void BERDecodePrivateKey(BufferedTransformation &bt, bool, size_t) 00811 {m_x.BERDecode(bt);} 00812 void DEREncodePrivateKey(BufferedTransformation &bt) const 00813 {m_x.DEREncode(bt);} 00814 00815 private: 00816 Integer m_x; 00817 }; 00818 00819 //! _ 00820 template <class BASE, class SIGNATURE_SCHEME> 00821 class DL_PrivateKey_WithSignaturePairwiseConsistencyTest : public BASE 00822 { 00823 public: 00824 void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs ¶ms) 00825 { 00826 BASE::GenerateRandom(rng, params); 00827 00828 if (FIPS_140_2_ComplianceEnabled()) 00829 { 00830 typename SIGNATURE_SCHEME::Signer signer(*this); 00831 typename SIGNATURE_SCHEME::Verifier verifier(signer); 00832 SignaturePairwiseConsistencyTest_FIPS_140_Only(signer, verifier); 00833 } 00834 } 00835 }; 00836 00837 //! _ 00838 template <class GP> 00839 class DL_PublicKeyImpl : public DL_PublicKey<typename GP::Element>, public DL_KeyImpl<X509PublicKey, GP> 00840 { 00841 public: 00842 typedef typename GP::Element Element; 00843 00844 // CryptoMaterial 00845 bool Validate(RandomNumberGenerator &rng, unsigned int level) const 00846 { 00847 bool pass = GetAbstractGroupParameters().Validate(rng, level); 00848 pass = pass && GetAbstractGroupParameters().ValidateElement(level, this->GetPublicElement(), &GetPublicPrecomputation()); 00849 return pass; 00850 } 00851 00852 bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const 00853 { 00854 return GetValueHelper<DL_PublicKey<Element> >(this, name, valueType, pValue).Assignable(); 00855 } 00856 00857 void AssignFrom(const NameValuePairs &source) 00858 { 00859 AssignFromHelper<DL_PublicKey<Element> >(this, source); 00860 } 00861 00862 bool SupportsPrecomputation() const {return true;} 00863 00864 void Precompute(unsigned int precomputationStorage=16) 00865 { 00866 AccessAbstractGroupParameters().Precompute(precomputationStorage); 00867 AccessPublicPrecomputation().Precompute(GetAbstractGroupParameters().GetGroupPrecomputation(), GetAbstractGroupParameters().GetSubgroupOrder().BitCount(), precomputationStorage); 00868 } 00869 00870 void LoadPrecomputation(BufferedTransformation &storedPrecomputation) 00871 { 00872 AccessAbstractGroupParameters().LoadPrecomputation(storedPrecomputation); 00873 AccessPublicPrecomputation().Load(GetAbstractGroupParameters().GetGroupPrecomputation(), storedPrecomputation); 00874 } 00875 00876 void SavePrecomputation(BufferedTransformation &storedPrecomputation) const 00877 { 00878 GetAbstractGroupParameters().SavePrecomputation(storedPrecomputation); 00879 GetPublicPrecomputation().Save(GetAbstractGroupParameters().GetGroupPrecomputation(), storedPrecomputation); 00880 } 00881 00882 // DL_Key 00883 const DL_GroupParameters<Element> & GetAbstractGroupParameters() const {return this->GetGroupParameters();} 00884 DL_GroupParameters<Element> & AccessAbstractGroupParameters() {return this->AccessGroupParameters();} 00885 00886 // DL_PublicKey 00887 const DL_FixedBasePrecomputation<Element> & GetPublicPrecomputation() const {return m_ypc;} 00888 DL_FixedBasePrecomputation<Element> & AccessPublicPrecomputation() {return m_ypc;} 00889 00890 // non-inherited 00891 bool operator==(const DL_PublicKeyImpl<GP> &rhs) const 00892 {return this->GetGroupParameters() == rhs.GetGroupParameters() && this->GetPublicElement() == rhs.GetPublicElement();} 00893 00894 private: 00895 typename GP::BasePrecomputation m_ypc; 00896 }; 00897 00898 //! interface for Elgamal-like signature algorithms 00899 template <class T> 00900 class CRYPTOPP_NO_VTABLE DL_ElgamalLikeSignatureAlgorithm 00901 { 00902 public: 00903 virtual void Sign(const DL_GroupParameters<T> ¶ms, const Integer &privateKey, const Integer &k, const Integer &e, Integer &r, Integer &s) const =0; 00904 virtual bool Verify(const DL_GroupParameters<T> ¶ms, const DL_PublicKey<T> &publicKey, const Integer &e, const Integer &r, const Integer &s) const =0; 00905 virtual Integer RecoverPresignature(const DL_GroupParameters<T> ¶ms, const DL_PublicKey<T> &publicKey, const Integer &r, const Integer &s) const 00906 {throw NotImplemented("DL_ElgamalLikeSignatureAlgorithm: this signature scheme does not support message recovery");} 00907 virtual size_t RLen(const DL_GroupParameters<T> ¶ms) const 00908 {return params.GetSubgroupOrder().ByteCount();} 00909 virtual size_t SLen(const DL_GroupParameters<T> ¶ms) const 00910 {return params.GetSubgroupOrder().ByteCount();} 00911 }; 00912 00913 //! interface for DL key agreement algorithms 00914 template <class T> 00915 class CRYPTOPP_NO_VTABLE DL_KeyAgreementAlgorithm 00916 { 00917 public: 00918 typedef T Element; 00919 00920 virtual Element AgreeWithEphemeralPrivateKey(const DL_GroupParameters<Element> ¶ms, const DL_FixedBasePrecomputation<Element> &publicPrecomputation, const Integer &privateExponent) const =0; 00921 virtual Element AgreeWithStaticPrivateKey(const DL_GroupParameters<Element> ¶ms, const Element &publicElement, bool validateOtherPublicKey, const Integer &privateExponent) const =0; 00922 }; 00923 00924 //! interface for key derivation algorithms used in DL cryptosystems 00925 template <class T> 00926 class CRYPTOPP_NO_VTABLE DL_KeyDerivationAlgorithm 00927 { 00928 public: 00929 virtual bool ParameterSupported(const char *name) const {return false;} 00930 virtual void Derive(const DL_GroupParameters<T> &groupParams, byte *derivedKey, size_t derivedLength, const T &agreedElement, const T &ephemeralPublicKey, const NameValuePairs &derivationParams) const =0; 00931 }; 00932 00933 //! interface for symmetric encryption algorithms used in DL cryptosystems 00934 class CRYPTOPP_NO_VTABLE DL_SymmetricEncryptionAlgorithm 00935 { 00936 public: 00937 virtual bool ParameterSupported(const char *name) const {return false;} 00938 virtual size_t GetSymmetricKeyLength(size_t plaintextLength) const =0; 00939 virtual size_t GetSymmetricCiphertextLength(size_t plaintextLength) const =0; 00940 virtual size_t GetMaxSymmetricPlaintextLength(size_t ciphertextLength) const =0; 00941 virtual void SymmetricEncrypt(RandomNumberGenerator &rng, const byte *key, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs ¶meters) const =0; 00942 virtual DecodingResult SymmetricDecrypt(const byte *key, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs ¶meters) const =0; 00943 }; 00944 00945 //! _ 00946 template <class KI> 00947 class CRYPTOPP_NO_VTABLE DL_Base 00948 { 00949 protected: 00950 typedef KI KeyInterface; 00951 typedef typename KI::Element Element; 00952 00953 const DL_GroupParameters<Element> & GetAbstractGroupParameters() const {return GetKeyInterface().GetAbstractGroupParameters();} 00954 DL_GroupParameters<Element> & AccessAbstractGroupParameters() {return AccessKeyInterface().AccessAbstractGroupParameters();} 00955 00956 virtual KeyInterface & AccessKeyInterface() =0; 00957 virtual const KeyInterface & GetKeyInterface() const =0; 00958 }; 00959 00960 //! _ 00961 template <class INTERFACE, class KEY_INTERFACE> 00962 class CRYPTOPP_NO_VTABLE DL_SignatureSchemeBase : public INTERFACE, public DL_Base<KEY_INTERFACE> 00963 { 00964 public: 00965 size_t SignatureLength() const 00966 { 00967 return GetSignatureAlgorithm().RLen(this->GetAbstractGroupParameters()) 00968 + GetSignatureAlgorithm().SLen(this->GetAbstractGroupParameters()); 00969 } 00970 size_t MaxRecoverableLength() const 00971 {return GetMessageEncodingInterface().MaxRecoverableLength(0, GetHashIdentifier().second, GetDigestSize());} 00972 size_t MaxRecoverableLengthFromSignatureLength(size_t signatureLength) const 00973 {assert(false); return 0;} // TODO 00974 00975 bool IsProbabilistic() const 00976 {return true;} 00977 bool AllowNonrecoverablePart() const 00978 {return GetMessageEncodingInterface().AllowNonrecoverablePart();} 00979 bool RecoverablePartFirst() const 00980 {return GetMessageEncodingInterface().RecoverablePartFirst();} 00981 00982 protected: 00983 size_t MessageRepresentativeLength() const {return BitsToBytes(MessageRepresentativeBitLength());} 00984 size_t MessageRepresentativeBitLength() const {return this->GetAbstractGroupParameters().GetSubgroupOrder().BitCount();} 00985 00986 virtual const DL_ElgamalLikeSignatureAlgorithm<CPP_TYPENAME KEY_INTERFACE::Element> & GetSignatureAlgorithm() const =0; 00987 virtual const PK_SignatureMessageEncodingMethod & GetMessageEncodingInterface() const =0; 00988 virtual HashIdentifier GetHashIdentifier() const =0; 00989 virtual size_t GetDigestSize() const =0; 00990 }; 00991 00992 //! _ 00993 template <class T> 00994 class CRYPTOPP_NO_VTABLE DL_SignerBase : public DL_SignatureSchemeBase<PK_Signer, DL_PrivateKey<T> > 00995 { 00996 public: 00997 // for validation testing 00998 void RawSign(const Integer &k, const Integer &e, Integer &r, Integer &s) const 00999 { 01000 const DL_ElgamalLikeSignatureAlgorithm<T> &alg = this->GetSignatureAlgorithm(); 01001 const DL_GroupParameters<T> ¶ms = this->GetAbstractGroupParameters(); 01002 const DL_PrivateKey<T> &key = this->GetKeyInterface(); 01003 01004 r = params.ConvertElementToInteger(params.ExponentiateBase(k)); 01005 alg.Sign(params, key.GetPrivateExponent(), k, e, r, s); 01006 } 01007 01008 void InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, size_t recoverableMessageLength) const 01009 { 01010 PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator); 01011 ma.m_recoverableMessage.Assign(recoverableMessage, recoverableMessageLength); 01012 this->GetMessageEncodingInterface().ProcessRecoverableMessage(ma.AccessHash(), 01013 recoverableMessage, recoverableMessageLength, 01014 ma.m_presignature, ma.m_presignature.size(), 01015 ma.m_semisignature); 01016 } 01017 01018 size_t SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart) const 01019 { 01020 this->GetMaterial().DoQuickSanityCheck(); 01021 01022 PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator); 01023 const DL_ElgamalLikeSignatureAlgorithm<T> &alg = this->GetSignatureAlgorithm(); 01024 const DL_GroupParameters<T> ¶ms = this->GetAbstractGroupParameters(); 01025 const DL_PrivateKey<T> &key = this->GetKeyInterface(); 01026 01027 SecByteBlock representative(this->MessageRepresentativeLength()); 01028 this->GetMessageEncodingInterface().ComputeMessageRepresentative( 01029 rng, 01030 ma.m_recoverableMessage, ma.m_recoverableMessage.size(), 01031 ma.AccessHash(), this->GetHashIdentifier(), ma.m_empty, 01032 representative, this->MessageRepresentativeBitLength()); 01033 ma.m_empty = true; 01034 Integer e(representative, representative.size()); 01035 01036 // hash message digest into random number k to prevent reusing the same k on a different messages 01037 // after virtual machine rollback 01038 if (rng.CanIncorporateEntropy()) 01039 rng.IncorporateEntropy(representative, representative.size()); 01040 Integer k(rng, 1, params.GetSubgroupOrder()-1); 01041 Integer r, s; 01042 r = params.ConvertElementToInteger(params.ExponentiateBase(k)); 01043 alg.Sign(params, key.GetPrivateExponent(), k, e, r, s); 01044 01045 /* 01046 Integer r, s; 01047 if (this->MaxRecoverableLength() > 0) 01048 r.Decode(ma.m_semisignature, ma.m_semisignature.size()); 01049 else 01050 r.Decode(ma.m_presignature, ma.m_presignature.size()); 01051 alg.Sign(params, key.GetPrivateExponent(), ma.m_k, e, r, s); 01052 */ 01053 01054 size_t rLen = alg.RLen(params); 01055 r.Encode(signature, rLen); 01056 s.Encode(signature+rLen, alg.SLen(params)); 01057 01058 if (restart) 01059 RestartMessageAccumulator(rng, ma); 01060 01061 return this->SignatureLength(); 01062 } 01063 01064 protected: 01065 void RestartMessageAccumulator(RandomNumberGenerator &rng, PK_MessageAccumulatorBase &ma) const 01066 { 01067 // k needs to be generated before hashing for signature schemes with recovery 01068 // but to defend against VM rollbacks we need to generate k after hashing. 01069 // so this code is commented out, since no DL-based signature scheme with recovery 01070 // has been implemented in Crypto++ anyway 01071 /* 01072 const DL_ElgamalLikeSignatureAlgorithm<T> &alg = this->GetSignatureAlgorithm(); 01073 const DL_GroupParameters<T> ¶ms = this->GetAbstractGroupParameters(); 01074 ma.m_k.Randomize(rng, 1, params.GetSubgroupOrder()-1); 01075 ma.m_presignature.New(params.GetEncodedElementSize(false)); 01076 params.ConvertElementToInteger(params.ExponentiateBase(ma.m_k)).Encode(ma.m_presignature, ma.m_presignature.size()); 01077 */ 01078 } 01079 }; 01080 01081 //! _ 01082 template <class T> 01083 class CRYPTOPP_NO_VTABLE DL_VerifierBase : public DL_SignatureSchemeBase<PK_Verifier, DL_PublicKey<T> > 01084 { 01085 public: 01086 void InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, size_t signatureLength) const 01087 { 01088 PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator); 01089 const DL_ElgamalLikeSignatureAlgorithm<T> &alg = this->GetSignatureAlgorithm(); 01090 const DL_GroupParameters<T> ¶ms = this->GetAbstractGroupParameters(); 01091 01092 size_t rLen = alg.RLen(params); 01093 ma.m_semisignature.Assign(signature, rLen); 01094 ma.m_s.Decode(signature+rLen, alg.SLen(params)); 01095 01096 this->GetMessageEncodingInterface().ProcessSemisignature(ma.AccessHash(), ma.m_semisignature, ma.m_semisignature.size()); 01097 } 01098 01099 bool VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const 01100 { 01101 this->GetMaterial().DoQuickSanityCheck(); 01102 01103 PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator); 01104 const DL_ElgamalLikeSignatureAlgorithm<T> &alg = this->GetSignatureAlgorithm(); 01105 const DL_GroupParameters<T> ¶ms = this->GetAbstractGroupParameters(); 01106 const DL_PublicKey<T> &key = this->GetKeyInterface(); 01107 01108 SecByteBlock representative(this->MessageRepresentativeLength()); 01109 this->GetMessageEncodingInterface().ComputeMessageRepresentative(NullRNG(), ma.m_recoverableMessage, ma.m_recoverableMessage.size(), 01110 ma.AccessHash(), this->GetHashIdentifier(), ma.m_empty, 01111 representative, this->MessageRepresentativeBitLength()); 01112 ma.m_empty = true; 01113 Integer e(representative, representative.size()); 01114 01115 Integer r(ma.m_semisignature, ma.m_semisignature.size()); 01116 return alg.Verify(params, key, e, r, ma.m_s); 01117 } 01118 01119 DecodingResult RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &messageAccumulator) const 01120 { 01121 this->GetMaterial().DoQuickSanityCheck(); 01122 01123 PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator); 01124 const DL_ElgamalLikeSignatureAlgorithm<T> &alg = this->GetSignatureAlgorithm(); 01125 const DL_GroupParameters<T> ¶ms = this->GetAbstractGroupParameters(); 01126 const DL_PublicKey<T> &key = this->GetKeyInterface(); 01127 01128 SecByteBlock representative(this->MessageRepresentativeLength()); 01129 this->GetMessageEncodingInterface().ComputeMessageRepresentative( 01130 NullRNG(), 01131 ma.m_recoverableMessage, ma.m_recoverableMessage.size(), 01132 ma.AccessHash(), this->GetHashIdentifier(), ma.m_empty, 01133 representative, this->MessageRepresentativeBitLength()); 01134 ma.m_empty = true; 01135 Integer e(representative, representative.size()); 01136 01137 ma.m_presignature.New(params.GetEncodedElementSize(false)); 01138 Integer r(ma.m_semisignature, ma.m_semisignature.size()); 01139 alg.RecoverPresignature(params, key, r, ma.m_s).Encode(ma.m_presignature, ma.m_presignature.size()); 01140 01141 return this->GetMessageEncodingInterface().RecoverMessageFromSemisignature( 01142 ma.AccessHash(), this->GetHashIdentifier(), 01143 ma.m_presignature, ma.m_presignature.size(), 01144 ma.m_semisignature, ma.m_semisignature.size(), 01145 recoveredMessage); 01146 } 01147 }; 01148 01149 //! _ 01150 template <class PK, class KI> 01151 class CRYPTOPP_NO_VTABLE DL_CryptoSystemBase : public PK, public DL_Base<KI> 01152 { 01153 public: 01154 typedef typename DL_Base<KI>::Element Element; 01155 01156 size_t MaxPlaintextLength(size_t ciphertextLength) const 01157 { 01158 unsigned int minLen = this->GetAbstractGroupParameters().GetEncodedElementSize(true); 01159 return ciphertextLength < minLen ? 0 : GetSymmetricEncryptionAlgorithm().GetMaxSymmetricPlaintextLength(ciphertextLength - minLen); 01160 } 01161 01162 size_t CiphertextLength(size_t plaintextLength) const 01163 { 01164 size_t len = GetSymmetricEncryptionAlgorithm().GetSymmetricCiphertextLength(plaintextLength); 01165 return len == 0 ? 0 : this->GetAbstractGroupParameters().GetEncodedElementSize(true) + len; 01166 } 01167 01168 bool ParameterSupported(const char *name) const 01169 {return GetKeyDerivationAlgorithm().ParameterSupported(name) || GetSymmetricEncryptionAlgorithm().ParameterSupported(name);} 01170 01171 protected: 01172 virtual const DL_KeyAgreementAlgorithm<Element> & GetKeyAgreementAlgorithm() const =0; 01173 virtual const DL_KeyDerivationAlgorithm<Element> & GetKeyDerivationAlgorithm() const =0; 01174 virtual const DL_SymmetricEncryptionAlgorithm & GetSymmetricEncryptionAlgorithm() const =0; 01175 }; 01176 01177 //! _ 01178 template <class T> 01179 class CRYPTOPP_NO_VTABLE DL_DecryptorBase : public DL_CryptoSystemBase<PK_Decryptor, DL_PrivateKey<T> > 01180 { 01181 public: 01182 typedef T Element; 01183 01184 DecodingResult Decrypt(RandomNumberGenerator &rng, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs ¶meters = g_nullNameValuePairs) const 01185 { 01186 try 01187 { 01188 const DL_KeyAgreementAlgorithm<T> &agreeAlg = this->GetKeyAgreementAlgorithm(); 01189 const DL_KeyDerivationAlgorithm<T> &derivAlg = this->GetKeyDerivationAlgorithm(); 01190 const DL_SymmetricEncryptionAlgorithm &encAlg = this->GetSymmetricEncryptionAlgorithm(); 01191 const DL_GroupParameters<T> ¶ms = this->GetAbstractGroupParameters(); 01192 const DL_PrivateKey<T> &key = this->GetKeyInterface(); 01193 01194 Element q = params.DecodeElement(ciphertext, true); 01195 size_t elementSize = params.GetEncodedElementSize(true); 01196 ciphertext += elementSize; 01197 ciphertextLength -= elementSize; 01198 01199 Element z = agreeAlg.AgreeWithStaticPrivateKey(params, q, true, key.GetPrivateExponent()); 01200 01201 SecByteBlock derivedKey(encAlg.GetSymmetricKeyLength(encAlg.GetMaxSymmetricPlaintextLength(ciphertextLength))); 01202 derivAlg.Derive(params, derivedKey, derivedKey.size(), z, q, parameters); 01203 01204 return encAlg.SymmetricDecrypt(derivedKey, ciphertext, ciphertextLength, plaintext, parameters); 01205 } 01206 catch (DL_BadElement &) 01207 { 01208 return DecodingResult(); 01209 } 01210 } 01211 }; 01212 01213 //! _ 01214 template <class T> 01215 class CRYPTOPP_NO_VTABLE DL_EncryptorBase : public DL_CryptoSystemBase<PK_Encryptor, DL_PublicKey<T> > 01216 { 01217 public: 01218 typedef T Element; 01219 01220 void Encrypt(RandomNumberGenerator &rng, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs ¶meters = g_nullNameValuePairs) const 01221 { 01222 const DL_KeyAgreementAlgorithm<T> &agreeAlg = this->GetKeyAgreementAlgorithm(); 01223 const DL_KeyDerivationAlgorithm<T> &derivAlg = this->GetKeyDerivationAlgorithm(); 01224 const DL_SymmetricEncryptionAlgorithm &encAlg = this->GetSymmetricEncryptionAlgorithm(); 01225 const DL_GroupParameters<T> ¶ms = this->GetAbstractGroupParameters(); 01226 const DL_PublicKey<T> &key = this->GetKeyInterface(); 01227 01228 Integer x(rng, Integer::One(), params.GetMaxExponent()); 01229 Element q = params.ExponentiateBase(x); 01230 params.EncodeElement(true, q, ciphertext); 01231 unsigned int elementSize = params.GetEncodedElementSize(true); 01232 ciphertext += elementSize; 01233 01234 Element z = agreeAlg.AgreeWithEphemeralPrivateKey(params, key.GetPublicPrecomputation(), x); 01235 01236 SecByteBlock derivedKey(encAlg.GetSymmetricKeyLength(plaintextLength)); 01237 derivAlg.Derive(params, derivedKey, derivedKey.size(), z, q, parameters); 01238 01239 encAlg.SymmetricEncrypt(rng, derivedKey, plaintext, plaintextLength, ciphertext, parameters); 01240 } 01241 }; 01242 01243 //! _ 01244 template <class T1, class T2> 01245 struct DL_SchemeOptionsBase 01246 { 01247 typedef T1 AlgorithmInfo; 01248 typedef T2 GroupParameters; 01249 typedef typename GroupParameters::Element Element; 01250 }; 01251 01252 //! _ 01253 template <class T1, class T2> 01254 struct DL_KeyedSchemeOptions : public DL_SchemeOptionsBase<T1, typename T2::PublicKey::GroupParameters> 01255 { 01256 typedef T2 Keys; 01257 typedef typename Keys::PrivateKey PrivateKey; 01258 typedef typename Keys::PublicKey PublicKey; 01259 }; 01260 01261 //! _ 01262 template <class T1, class T2, class T3, class T4, class T5> 01263 struct DL_SignatureSchemeOptions : public DL_KeyedSchemeOptions<T1, T2> 01264 { 01265 typedef T3 SignatureAlgorithm; 01266 typedef T4 MessageEncodingMethod; 01267 typedef T5 HashFunction; 01268 }; 01269 01270 //! _ 01271 template <class T1, class T2, class T3, class T4, class T5> 01272 struct DL_CryptoSchemeOptions : public DL_KeyedSchemeOptions<T1, T2> 01273 { 01274 typedef T3 KeyAgreementAlgorithm; 01275 typedef T4 KeyDerivationAlgorithm; 01276 typedef T5 SymmetricEncryptionAlgorithm; 01277 }; 01278 01279 //! _ 01280 template <class BASE, class SCHEME_OPTIONS, class KEY> 01281 class CRYPTOPP_NO_VTABLE DL_ObjectImplBase : public AlgorithmImpl<BASE, typename SCHEME_OPTIONS::AlgorithmInfo> 01282 { 01283 public: 01284 typedef SCHEME_OPTIONS SchemeOptions; 01285 typedef typename KEY::Element Element; 01286 01287 PrivateKey & AccessPrivateKey() {return m_key;} 01288 PublicKey & AccessPublicKey() {return m_key;} 01289 01290 // KeyAccessor 01291 const KEY & GetKey() const {return m_key;} 01292 KEY & AccessKey() {return m_key;} 01293 01294 protected: 01295 typename BASE::KeyInterface & AccessKeyInterface() {return m_key;} 01296 const typename BASE::KeyInterface & GetKeyInterface() const {return m_key;} 01297 01298 // for signature scheme 01299 HashIdentifier GetHashIdentifier() const 01300 { 01301 typedef typename SchemeOptions::MessageEncodingMethod::HashIdentifierLookup HashLookup; 01302 return HashLookup::template HashIdentifierLookup2<CPP_TYPENAME SchemeOptions::HashFunction>::Lookup(); 01303 } 01304 size_t GetDigestSize() const 01305 { 01306 typedef CPP_TYPENAME SchemeOptions::HashFunction H; 01307 return H::DIGESTSIZE; 01308 } 01309 01310 private: 01311 KEY m_key; 01312 }; 01313 01314 //! _ 01315 template <class BASE, class SCHEME_OPTIONS, class KEY> 01316 class CRYPTOPP_NO_VTABLE DL_ObjectImpl : public DL_ObjectImplBase<BASE, SCHEME_OPTIONS, KEY> 01317 { 01318 public: 01319 typedef typename KEY::Element Element; 01320 01321 protected: 01322 const DL_ElgamalLikeSignatureAlgorithm<Element> & GetSignatureAlgorithm() const 01323 {return Singleton<CPP_TYPENAME SCHEME_OPTIONS::SignatureAlgorithm>().Ref();} 01324 const DL_KeyAgreementAlgorithm<Element> & GetKeyAgreementAlgorithm() const 01325 {return Singleton<CPP_TYPENAME SCHEME_OPTIONS::KeyAgreementAlgorithm>().Ref();} 01326 const DL_KeyDerivationAlgorithm<Element> & GetKeyDerivationAlgorithm() const 01327 {return Singleton<CPP_TYPENAME SCHEME_OPTIONS::KeyDerivationAlgorithm>().Ref();} 01328 const DL_SymmetricEncryptionAlgorithm & GetSymmetricEncryptionAlgorithm() const 01329 {return Singleton<CPP_TYPENAME SCHEME_OPTIONS::SymmetricEncryptionAlgorithm>().Ref();} 01330 HashIdentifier GetHashIdentifier() const 01331 {return HashIdentifier();} 01332 const PK_SignatureMessageEncodingMethod & GetMessageEncodingInterface() const 01333 {return Singleton<CPP_TYPENAME SCHEME_OPTIONS::MessageEncodingMethod>().Ref();} 01334 }; 01335 01336 //! _ 01337 template <class SCHEME_OPTIONS> 01338 class DL_SignerImpl : public DL_ObjectImpl<DL_SignerBase<typename SCHEME_OPTIONS::Element>, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PrivateKey> 01339 { 01340 public: 01341 PK_MessageAccumulator * NewSignatureAccumulator(RandomNumberGenerator &rng) const 01342 { 01343 std::auto_ptr<PK_MessageAccumulatorBase> p(new PK_MessageAccumulatorImpl<CPP_TYPENAME SCHEME_OPTIONS::HashFunction>); 01344 this->RestartMessageAccumulator(rng, *p); 01345 return p.release(); 01346 } 01347 }; 01348 01349 //! _ 01350 template <class SCHEME_OPTIONS> 01351 class DL_VerifierImpl : public DL_ObjectImpl<DL_VerifierBase<typename SCHEME_OPTIONS::Element>, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PublicKey> 01352 { 01353 public: 01354 PK_MessageAccumulator * NewVerificationAccumulator() const 01355 { 01356 return new PK_MessageAccumulatorImpl<CPP_TYPENAME SCHEME_OPTIONS::HashFunction>; 01357 } 01358 }; 01359 01360 //! _ 01361 template <class SCHEME_OPTIONS> 01362 class DL_EncryptorImpl : public DL_ObjectImpl<DL_EncryptorBase<typename SCHEME_OPTIONS::Element>, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PublicKey> 01363 { 01364 }; 01365 01366 //! _ 01367 template <class SCHEME_OPTIONS> 01368 class DL_DecryptorImpl : public DL_ObjectImpl<DL_DecryptorBase<typename SCHEME_OPTIONS::Element>, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PrivateKey> 01369 { 01370 }; 01371 01372 // ******************************************************** 01373 01374 //! _ 01375 template <class T> 01376 class CRYPTOPP_NO_VTABLE DL_SimpleKeyAgreementDomainBase : public SimpleKeyAgreementDomain 01377 { 01378 public: 01379 typedef T Element; 01380 01381 CryptoParameters & AccessCryptoParameters() {return AccessAbstractGroupParameters();} 01382 unsigned int AgreedValueLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(false);} 01383 unsigned int PrivateKeyLength() const {return GetAbstractGroupParameters().GetSubgroupOrder().ByteCount();} 01384 unsigned int PublicKeyLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(true);} 01385 01386 void GeneratePrivateKey(RandomNumberGenerator &rng, byte *privateKey) const 01387 { 01388 Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent()); 01389 x.Encode(privateKey, PrivateKeyLength()); 01390 } 01391 01392 void GeneratePublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const 01393 { 01394 const DL_GroupParameters<T> ¶ms = GetAbstractGroupParameters(); 01395 Integer x(privateKey, PrivateKeyLength()); 01396 Element y = params.ExponentiateBase(x); 01397 params.EncodeElement(true, y, publicKey); 01398 } 01399 01400 bool Agree(byte *agreedValue, const byte *privateKey, const byte *otherPublicKey, bool validateOtherPublicKey=true) const 01401 { 01402 try 01403 { 01404 const DL_GroupParameters<T> ¶ms = GetAbstractGroupParameters(); 01405 Integer x(privateKey, PrivateKeyLength()); 01406 Element w = params.DecodeElement(otherPublicKey, validateOtherPublicKey); 01407 01408 Element z = GetKeyAgreementAlgorithm().AgreeWithStaticPrivateKey( 01409 GetAbstractGroupParameters(), w, validateOtherPublicKey, x); 01410 params.EncodeElement(false, z, agreedValue); 01411 } 01412 catch (DL_BadElement &) 01413 { 01414 return false; 01415 } 01416 return true; 01417 } 01418 01419 const Element &GetGenerator() const {return GetAbstractGroupParameters().GetSubgroupGenerator();} 01420 01421 protected: 01422 virtual const DL_KeyAgreementAlgorithm<Element> & GetKeyAgreementAlgorithm() const =0; 01423 virtual DL_GroupParameters<Element> & AccessAbstractGroupParameters() =0; 01424 const DL_GroupParameters<Element> & GetAbstractGroupParameters() const {return const_cast<DL_SimpleKeyAgreementDomainBase<Element> *>(this)->AccessAbstractGroupParameters();} 01425 }; 01426 01427 enum CofactorMultiplicationOption {NO_COFACTOR_MULTIPLICTION, COMPATIBLE_COFACTOR_MULTIPLICTION, INCOMPATIBLE_COFACTOR_MULTIPLICTION}; 01428 typedef EnumToType<CofactorMultiplicationOption, NO_COFACTOR_MULTIPLICTION> NoCofactorMultiplication; 01429 typedef EnumToType<CofactorMultiplicationOption, COMPATIBLE_COFACTOR_MULTIPLICTION> CompatibleCofactorMultiplication; 01430 typedef EnumToType<CofactorMultiplicationOption, INCOMPATIBLE_COFACTOR_MULTIPLICTION> IncompatibleCofactorMultiplication; 01431 01432 //! DH key agreement algorithm 01433 template <class ELEMENT, class COFACTOR_OPTION> 01434 class DL_KeyAgreementAlgorithm_DH : public DL_KeyAgreementAlgorithm<ELEMENT> 01435 { 01436 public: 01437 typedef ELEMENT Element; 01438 01439 static const char * CRYPTOPP_API StaticAlgorithmName() 01440 {return COFACTOR_OPTION::ToEnum() == INCOMPATIBLE_COFACTOR_MULTIPLICTION ? "DHC" : "DH";} 01441 01442 Element AgreeWithEphemeralPrivateKey(const DL_GroupParameters<Element> ¶ms, const DL_FixedBasePrecomputation<Element> &publicPrecomputation, const Integer &privateExponent) const 01443 { 01444 return publicPrecomputation.Exponentiate(params.GetGroupPrecomputation(), 01445 COFACTOR_OPTION::ToEnum() == INCOMPATIBLE_COFACTOR_MULTIPLICTION ? privateExponent*params.GetCofactor() : privateExponent); 01446 } 01447 01448 Element AgreeWithStaticPrivateKey(const DL_GroupParameters<Element> ¶ms, const Element &publicElement, bool validateOtherPublicKey, const Integer &privateExponent) const 01449 { 01450 if (COFACTOR_OPTION::ToEnum() == COMPATIBLE_COFACTOR_MULTIPLICTION) 01451 { 01452 const Integer &k = params.GetCofactor(); 01453 return params.ExponentiateElement(publicElement, 01454 ModularArithmetic(params.GetSubgroupOrder()).Divide(privateExponent, k)*k); 01455 } 01456 else if (COFACTOR_OPTION::ToEnum() == INCOMPATIBLE_COFACTOR_MULTIPLICTION) 01457 return params.ExponentiateElement(publicElement, privateExponent*params.GetCofactor()); 01458 else 01459 { 01460 assert(COFACTOR_OPTION::ToEnum() == NO_COFACTOR_MULTIPLICTION); 01461 01462 if (!validateOtherPublicKey) 01463 return params.ExponentiateElement(publicElement, privateExponent); 01464 01465 if (params.FastSubgroupCheckAvailable()) 01466 { 01467 if (!params.ValidateElement(2, publicElement, NULL)) 01468 throw DL_BadElement(); 01469 return params.ExponentiateElement(publicElement, privateExponent); 01470 } 01471 else 01472 { 01473 const Integer e[2] = {params.GetSubgroupOrder(), privateExponent}; 01474 Element r[2]; 01475 params.SimultaneousExponentiate(r, publicElement, e, 2); 01476 if (!params.IsIdentity(r[0])) 01477 throw DL_BadElement(); 01478 return r[1]; 01479 } 01480 } 01481 } 01482 }; 01483 01484 // ******************************************************** 01485 01486 //! A template implementing constructors for public key algorithm classes 01487 template <class BASE> 01488 class CRYPTOPP_NO_VTABLE PK_FinalTemplate : public BASE 01489 { 01490 public: 01491 PK_FinalTemplate() {} 01492 01493 PK_FinalTemplate(const CryptoMaterial &key) 01494 {this->AccessKey().AssignFrom(key);} 01495 01496 PK_FinalTemplate(BufferedTransformation &bt) 01497 {this->AccessKey().BERDecode(bt);} 01498 01499 PK_FinalTemplate(const AsymmetricAlgorithm &algorithm) 01500 {this->AccessKey().AssignFrom(algorithm.GetMaterial());} 01501 01502 PK_FinalTemplate(const Integer &v1) 01503 {this->AccessKey().Initialize(v1);} 01504 01505 #if (defined(_MSC_VER) && _MSC_VER < 1300) 01506 01507 template <class T1, class T2> 01508 PK_FinalTemplate(T1 &v1, T2 &v2) 01509 {this->AccessKey().Initialize(v1, v2);} 01510 01511 template <class T1, class T2, class T3> 01512 PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3) 01513 {this->AccessKey().Initialize(v1, v2, v3);} 01514 01515 template <class T1, class T2, class T3, class T4> 01516 PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4) 01517 {this->AccessKey().Initialize(v1, v2, v3, v4);} 01518 01519 template <class T1, class T2, class T3, class T4, class T5> 01520 PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5) 01521 {this->AccessKey().Initialize(v1, v2, v3, v4, v5);} 01522 01523 template <class T1, class T2, class T3, class T4, class T5, class T6> 01524 PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5, T6 &v6) 01525 {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6);} 01526 01527 template <class T1, class T2, class T3, class T4, class T5, class T6, class T7> 01528 PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5, T6 &v6, T7 &v7) 01529 {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7);} 01530 01531 template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8> 01532 PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5, T6 &v6, T7 &v7, T8 &v8) 01533 {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7, v8);} 01534 01535 #else 01536 01537 template <class T1, class T2> 01538 PK_FinalTemplate(const T1 &v1, const T2 &v2) 01539 {this->AccessKey().Initialize(v1, v2);} 01540 01541 template <class T1, class T2, class T3> 01542 PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3) 01543 {this->AccessKey().Initialize(v1, v2, v3);} 01544 01545 template <class T1, class T2, class T3, class T4> 01546 PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4) 01547 {this->AccessKey().Initialize(v1, v2, v3, v4);} 01548 01549 template <class T1, class T2, class T3, class T4, class T5> 01550 PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5) 01551 {this->AccessKey().Initialize(v1, v2, v3, v4, v5);} 01552 01553 template <class T1, class T2, class T3, class T4, class T5, class T6> 01554 PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6) 01555 {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6);} 01556 01557 template <class T1, class T2, class T3, class T4, class T5, class T6, class T7> 01558 PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7) 01559 {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7);} 01560 01561 template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8> 01562 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) 01563 {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7, v8);} 01564 01565 template <class T1, class T2> 01566 PK_FinalTemplate(T1 &v1, const T2 &v2) 01567 {this->AccessKey().Initialize(v1, v2);} 01568 01569 template <class T1, class T2, class T3> 01570 PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3) 01571 {this->AccessKey().Initialize(v1, v2, v3);} 01572 01573 template <class T1, class T2, class T3, class T4> 01574 PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4) 01575 {this->AccessKey().Initialize(v1, v2, v3, v4);} 01576 01577 template <class T1, class T2, class T3, class T4, class T5> 01578 PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5) 01579 {this->AccessKey().Initialize(v1, v2, v3, v4, v5);} 01580 01581 template <class T1, class T2, class T3, class T4, class T5, class T6> 01582 PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6) 01583 {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6);} 01584 01585 template <class T1, class T2, class T3, class T4, class T5, class T6, class T7> 01586 PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7) 01587 {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7);} 01588 01589 template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8> 01590 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) 01591 {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7, v8);} 01592 01593 #endif 01594 }; 01595 01596 //! 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. 01597 struct EncryptionStandard {}; 01598 01599 //! 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. 01600 struct SignatureStandard {}; 01601 01602 template <class STANDARD, class KEYS, class ALG_INFO> 01603 class TF_ES; 01604 01605 //! Trapdoor Function Based Encryption Scheme 01606 template <class STANDARD, class KEYS, class ALG_INFO = TF_ES<STANDARD, KEYS, int> > 01607 class TF_ES : public KEYS 01608 { 01609 typedef typename STANDARD::EncryptionMessageEncodingMethod MessageEncodingMethod; 01610 01611 public: 01612 //! see EncryptionStandard for a list of standards 01613 typedef STANDARD Standard; 01614 typedef TF_CryptoSchemeOptions<ALG_INFO, KEYS, MessageEncodingMethod> SchemeOptions; 01615 01616 static std::string CRYPTOPP_API StaticAlgorithmName() {return std::string(KEYS::StaticAlgorithmName()) + "/" + MessageEncodingMethod::StaticAlgorithmName();} 01617 01618 //! implements PK_Decryptor interface 01619 typedef PK_FinalTemplate<TF_DecryptorImpl<SchemeOptions> > Decryptor; 01620 //! implements PK_Encryptor interface 01621 typedef PK_FinalTemplate<TF_EncryptorImpl<SchemeOptions> > Encryptor; 01622 }; 01623 01624 template <class STANDARD, class H, class KEYS, class ALG_INFO> // VC60 workaround: doesn't work if KEYS is first parameter 01625 class TF_SS; 01626 01627 //! Trapdoor Function Based Signature Scheme 01628 template <class STANDARD, class H, class KEYS, class ALG_INFO = TF_SS<STANDARD, H, KEYS, int> > // VC60 workaround: doesn't work if KEYS is first parameter 01629 class TF_SS : public KEYS 01630 { 01631 public: 01632 //! see SignatureStandard for a list of standards 01633 typedef STANDARD Standard; 01634 typedef typename Standard::SignatureMessageEncodingMethod MessageEncodingMethod; 01635 typedef TF_SignatureSchemeOptions<ALG_INFO, KEYS, MessageEncodingMethod, H> SchemeOptions; 01636 01637 static std::string CRYPTOPP_API StaticAlgorithmName() {return std::string(KEYS::StaticAlgorithmName()) + "/" + MessageEncodingMethod::StaticAlgorithmName() + "(" + H::StaticAlgorithmName() + ")";} 01638 01639 //! implements PK_Signer interface 01640 typedef PK_FinalTemplate<TF_SignerImpl<SchemeOptions> > Signer; 01641 //! implements PK_Verifier interface 01642 typedef PK_FinalTemplate<TF_VerifierImpl<SchemeOptions> > Verifier; 01643 }; 01644 01645 template <class KEYS, class SA, class MEM, class H, class ALG_INFO> 01646 class DL_SS; 01647 01648 //! Discrete Log Based Signature Scheme 01649 template <class KEYS, class SA, class MEM, class H, class ALG_INFO = DL_SS<KEYS, SA, MEM, H, int> > 01650 class DL_SS : public KEYS 01651 { 01652 typedef DL_SignatureSchemeOptions<ALG_INFO, KEYS, SA, MEM, H> SchemeOptions; 01653 01654 public: 01655 static std::string StaticAlgorithmName() {return SA::StaticAlgorithmName() + std::string("/EMSA1(") + H::StaticAlgorithmName() + ")";} 01656 01657 //! implements PK_Signer interface 01658 typedef PK_FinalTemplate<DL_SignerImpl<SchemeOptions> > Signer; 01659 //! implements PK_Verifier interface 01660 typedef PK_FinalTemplate<DL_VerifierImpl<SchemeOptions> > Verifier; 01661 }; 01662 01663 //! Discrete Log Based Encryption Scheme 01664 template <class KEYS, class AA, class DA, class EA, class ALG_INFO> 01665 class DL_ES : public KEYS 01666 { 01667 typedef DL_CryptoSchemeOptions<ALG_INFO, KEYS, AA, DA, EA> SchemeOptions; 01668 01669 public: 01670 //! implements PK_Decryptor interface 01671 typedef PK_FinalTemplate<DL_DecryptorImpl<SchemeOptions> > Decryptor; 01672 //! implements PK_Encryptor interface 01673 typedef PK_FinalTemplate<DL_EncryptorImpl<SchemeOptions> > Encryptor; 01674 }; 01675 01676 NAMESPACE_END 01677 01678 #endif