1#ifndef CRYPTOPP_ELGAMAL_H 2#define CRYPTOPP_ELGAMAL_H 3 4#include "modexppc.h" 5#include "dsa.h" 6 7NAMESPACE_BEGIN(CryptoPP) 8 9class CRYPTOPP_NO_VTABLE ElGamalBase : public DL_KeyAgreementAlgorithm_DH<Integer, NoCofactorMultiplication>, 10 public DL_KeyDerivationAlgorithm<Integer>, 11 public DL_SymmetricEncryptionAlgorithm 12{ 13public: 14 void Derive(const DL_GroupParameters<Integer> &groupParams, byte *derivedKey, size_t derivedLength, const Integer &agreedElement, const Integer &ephemeralPublicKey, const NameValuePairs &derivationParams) const 15 { 16 agreedElement.Encode(derivedKey, derivedLength); 17 } 18 19 size_t GetSymmetricKeyLength(size_t plainTextLength) const 20 { 21 return GetGroupParameters().GetModulus().ByteCount(); 22 } 23 24 size_t GetSymmetricCiphertextLength(size_t plainTextLength) const 25 { 26 unsigned int len = GetGroupParameters().GetModulus().ByteCount(); 27 if (plainTextLength <= GetMaxSymmetricPlaintextLength(len)) 28 return len; 29 else 30 return 0; 31 } 32 33 size_t GetMaxSymmetricPlaintextLength(size_t cipherTextLength) const 34 { 35 unsigned int len = GetGroupParameters().GetModulus().ByteCount(); 36 if (cipherTextLength == len) 37 return STDMIN(255U, len-3); 38 else 39 return 0; 40 } 41 42 void SymmetricEncrypt(RandomNumberGenerator &rng, const byte *key, const byte *plainText, size_t plainTextLength, byte *cipherText, const NameValuePairs ¶meters) const 43 { 44 const Integer &p = GetGroupParameters().GetModulus(); 45 unsigned int modulusLen = p.ByteCount(); 46 47 SecByteBlock block(modulusLen-1); 48 rng.GenerateBlock(block, modulusLen-2-plainTextLength); 49 memcpy(block+modulusLen-2-plainTextLength, plainText, plainTextLength); 50 block[modulusLen-2] = (byte)plainTextLength; 51 52 a_times_b_mod_c(Integer(key, modulusLen), Integer(block, modulusLen-1), p).Encode(cipherText, modulusLen); 53 } 54 55 DecodingResult SymmetricDecrypt(const byte *key, const byte *cipherText, size_t cipherTextLength, byte *plainText, const NameValuePairs ¶meters) const 56 { 57 const Integer &p = GetGroupParameters().GetModulus(); 58 unsigned int modulusLen = p.ByteCount(); 59 60 if (cipherTextLength != modulusLen) 61 return DecodingResult(); 62 63 Integer m = a_times_b_mod_c(Integer(cipherText, modulusLen), Integer(key, modulusLen).InverseMod(p), p); 64 65 m.Encode(plainText, 1); 66 unsigned int plainTextLength = plainText[0]; 67 if (plainTextLength > GetMaxSymmetricPlaintextLength(modulusLen)) 68 return DecodingResult(); 69 m >>= 8; 70 m.Encode(plainText, plainTextLength); 71 return DecodingResult(plainTextLength); 72 } 73 74 virtual const DL_GroupParameters_GFP & GetGroupParameters() const =0; 75}; 76 77template <class BASE, class SCHEME_OPTIONS, class KEY> 78class ElGamalObjectImpl : public DL_ObjectImplBase<BASE, SCHEME_OPTIONS, KEY>, public ElGamalBase 79{ 80public: 81 size_t FixedMaxPlaintextLength() const {return this->MaxPlaintextLength(FixedCiphertextLength());} 82 size_t FixedCiphertextLength() const {return this->CiphertextLength(0);} 83 84 const DL_GroupParameters_GFP & GetGroupParameters() const {return this->GetKey().GetGroupParameters();} 85 86 DecodingResult FixedLengthDecrypt(RandomNumberGenerator &rng, const byte *cipherText, byte *plainText) const 87 {return Decrypt(rng, cipherText, FixedCiphertextLength(), plainText);} 88 89protected: 90 const DL_KeyAgreementAlgorithm<Integer> & GetKeyAgreementAlgorithm() const {return *this;} 91 const DL_KeyDerivationAlgorithm<Integer> & GetKeyDerivationAlgorithm() const {return *this;} 92 const DL_SymmetricEncryptionAlgorithm & GetSymmetricEncryptionAlgorithm() const {return *this;} 93}; 94 95struct ElGamalKeys 96{ 97 typedef DL_CryptoKeys_GFP::GroupParameters GroupParameters; 98 typedef DL_PrivateKey_GFP_OldFormat<DL_CryptoKeys_GFP::PrivateKey> PrivateKey; 99 typedef DL_PublicKey_GFP_OldFormat<DL_CryptoKeys_GFP::PublicKey> PublicKey; 100}; 101 102//! ElGamal encryption scheme with non-standard padding 103struct ElGamal 104{ 105 typedef DL_CryptoSchemeOptions<ElGamal, ElGamalKeys, int, int, int> SchemeOptions; 106 107 static const char * StaticAlgorithmName() {return "ElgamalEnc/Crypto++Padding";} 108 109 typedef SchemeOptions::GroupParameters GroupParameters; 110 //! implements PK_Encryptor interface 111 typedef PK_FinalTemplate<ElGamalObjectImpl<DL_EncryptorBase<Integer>, SchemeOptions, SchemeOptions::PublicKey> > Encryptor; 112 //! implements PK_Decryptor interface 113 typedef PK_FinalTemplate<ElGamalObjectImpl<DL_DecryptorBase<Integer>, SchemeOptions, SchemeOptions::PrivateKey> > Decryptor; 114}; 115 116typedef ElGamal::Encryptor ElGamalEncryptor; 117typedef ElGamal::Decryptor ElGamalDecryptor; 118 119NAMESPACE_END 120 121#endif 122