Crypto++
|
00001 #ifndef CRYPTOPP_ELGAMAL_H 00002 #define CRYPTOPP_ELGAMAL_H 00003 00004 #include "modexppc.h" 00005 #include "dsa.h" 00006 00007 NAMESPACE_BEGIN(CryptoPP) 00008 00009 class CRYPTOPP_NO_VTABLE ElGamalBase : public DL_KeyAgreementAlgorithm_DH<Integer, NoCofactorMultiplication>, 00010 public DL_KeyDerivationAlgorithm<Integer>, 00011 public DL_SymmetricEncryptionAlgorithm 00012 { 00013 public: 00014 void Derive(const DL_GroupParameters<Integer> &groupParams, byte *derivedKey, size_t derivedLength, const Integer &agreedElement, const Integer &ephemeralPublicKey, const NameValuePairs &derivationParams) const 00015 { 00016 agreedElement.Encode(derivedKey, derivedLength); 00017 } 00018 00019 size_t GetSymmetricKeyLength(size_t plainTextLength) const 00020 { 00021 return GetGroupParameters().GetModulus().ByteCount(); 00022 } 00023 00024 size_t GetSymmetricCiphertextLength(size_t plainTextLength) const 00025 { 00026 unsigned int len = GetGroupParameters().GetModulus().ByteCount(); 00027 if (plainTextLength <= GetMaxSymmetricPlaintextLength(len)) 00028 return len; 00029 else 00030 return 0; 00031 } 00032 00033 size_t GetMaxSymmetricPlaintextLength(size_t cipherTextLength) const 00034 { 00035 unsigned int len = GetGroupParameters().GetModulus().ByteCount(); 00036 if (cipherTextLength == len) 00037 return STDMIN(255U, len-3); 00038 else 00039 return 0; 00040 } 00041 00042 void SymmetricEncrypt(RandomNumberGenerator &rng, const byte *key, const byte *plainText, size_t plainTextLength, byte *cipherText, const NameValuePairs ¶meters) const 00043 { 00044 const Integer &p = GetGroupParameters().GetModulus(); 00045 unsigned int modulusLen = p.ByteCount(); 00046 00047 SecByteBlock block(modulusLen-1); 00048 rng.GenerateBlock(block, modulusLen-2-plainTextLength); 00049 memcpy(block+modulusLen-2-plainTextLength, plainText, plainTextLength); 00050 block[modulusLen-2] = (byte)plainTextLength; 00051 00052 a_times_b_mod_c(Integer(key, modulusLen), Integer(block, modulusLen-1), p).Encode(cipherText, modulusLen); 00053 } 00054 00055 DecodingResult SymmetricDecrypt(const byte *key, const byte *cipherText, size_t cipherTextLength, byte *plainText, const NameValuePairs ¶meters) const 00056 { 00057 const Integer &p = GetGroupParameters().GetModulus(); 00058 unsigned int modulusLen = p.ByteCount(); 00059 00060 if (cipherTextLength != modulusLen) 00061 return DecodingResult(); 00062 00063 Integer m = a_times_b_mod_c(Integer(cipherText, modulusLen), Integer(key, modulusLen).InverseMod(p), p); 00064 00065 m.Encode(plainText, 1); 00066 unsigned int plainTextLength = plainText[0]; 00067 if (plainTextLength > GetMaxSymmetricPlaintextLength(modulusLen)) 00068 return DecodingResult(); 00069 m >>= 8; 00070 m.Encode(plainText, plainTextLength); 00071 return DecodingResult(plainTextLength); 00072 } 00073 00074 virtual const DL_GroupParameters_GFP & GetGroupParameters() const =0; 00075 }; 00076 00077 template <class BASE, class SCHEME_OPTIONS, class KEY> 00078 class ElGamalObjectImpl : public DL_ObjectImplBase<BASE, SCHEME_OPTIONS, KEY>, public ElGamalBase 00079 { 00080 public: 00081 size_t FixedMaxPlaintextLength() const {return this->MaxPlaintextLength(FixedCiphertextLength());} 00082 size_t FixedCiphertextLength() const {return this->CiphertextLength(0);} 00083 00084 const DL_GroupParameters_GFP & GetGroupParameters() const {return this->GetKey().GetGroupParameters();} 00085 00086 DecodingResult FixedLengthDecrypt(RandomNumberGenerator &rng, const byte *cipherText, byte *plainText) const 00087 {return Decrypt(rng, cipherText, FixedCiphertextLength(), plainText);} 00088 00089 protected: 00090 const DL_KeyAgreementAlgorithm<Integer> & GetKeyAgreementAlgorithm() const {return *this;} 00091 const DL_KeyDerivationAlgorithm<Integer> & GetKeyDerivationAlgorithm() const {return *this;} 00092 const DL_SymmetricEncryptionAlgorithm & GetSymmetricEncryptionAlgorithm() const {return *this;} 00093 }; 00094 00095 struct ElGamalKeys 00096 { 00097 typedef DL_CryptoKeys_GFP::GroupParameters GroupParameters; 00098 typedef DL_PrivateKey_GFP_OldFormat<DL_CryptoKeys_GFP::PrivateKey> PrivateKey; 00099 typedef DL_PublicKey_GFP_OldFormat<DL_CryptoKeys_GFP::PublicKey> PublicKey; 00100 }; 00101 00102 //! ElGamal encryption scheme with non-standard padding 00103 struct ElGamal 00104 { 00105 typedef DL_CryptoSchemeOptions<ElGamal, ElGamalKeys, int, int, int> SchemeOptions; 00106 00107 static const char * StaticAlgorithmName() {return "ElgamalEnc/Crypto++Padding";} 00108 00109 typedef SchemeOptions::GroupParameters GroupParameters; 00110 //! implements PK_Encryptor interface 00111 typedef PK_FinalTemplate<ElGamalObjectImpl<DL_EncryptorBase<Integer>, SchemeOptions, SchemeOptions::PublicKey> > Encryptor; 00112 //! implements PK_Decryptor interface 00113 typedef PK_FinalTemplate<ElGamalObjectImpl<DL_DecryptorBase<Integer>, SchemeOptions, SchemeOptions::PrivateKey> > Decryptor; 00114 }; 00115 00116 typedef ElGamal::Encryptor ElGamalEncryptor; 00117 typedef ElGamal::Decryptor ElGamalDecryptor; 00118 00119 NAMESPACE_END 00120 00121 #endif