From a3b6ece7ab341b5b14135baeccea7d5e4c086771 Mon Sep 17 00:00:00 2001 From: weidai Date: Fri, 4 Oct 2002 17:31:41 +0000 Subject: Initial revision --- elgamal.h | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 elgamal.h (limited to 'elgamal.h') diff --git a/elgamal.h b/elgamal.h new file mode 100644 index 00000000..a2f6ffb7 --- /dev/null +++ b/elgamal.h @@ -0,0 +1,137 @@ +#ifndef CRYPTOPP_ELGAMAL_H +#define CRYPTOPP_ELGAMAL_H + +#include "modexppc.h" +#include "dsa.h" + +NAMESPACE_BEGIN(CryptoPP) + +class ElGamalBase : public DL_KeyAgreementAlgorithm_DH, + public DL_KeyDerivationAlgorithm, + public DL_SymmetricEncryptionAlgorithm +{ +public: + void Derive(const DL_GroupParameters ¶ms, byte *derivedKey, unsigned int derivedLength, const Integer &agreedElement, const Integer &ephemeralPublicKey) const + { + agreedElement.Encode(derivedKey, derivedLength); + } + + unsigned int GetSymmetricKeyLength(unsigned int plainTextLength) const + { + return GetGroupParameters().GetModulus().ByteCount(); + } + + unsigned int GetSymmetricCiphertextLength(unsigned int plainTextLength) const + { + unsigned int len = GetGroupParameters().GetModulus().ByteCount(); + if (plainTextLength <= GetMaxSymmetricPlaintextLength(len)) + return len; + else + return 0; + } + + unsigned int GetMaxSymmetricPlaintextLength(unsigned int cipherTextLength) const + { + unsigned int len = GetGroupParameters().GetModulus().ByteCount(); + if (cipherTextLength == len) + return STDMIN(255U, len-3); + else + return 0; + } + + void SymmetricEncrypt(RandomNumberGenerator &rng, const byte *key, const byte *plainText, unsigned int plainTextLength, byte *cipherText) const + { + const Integer &p = GetGroupParameters().GetModulus(); + unsigned int modulusLen = p.ByteCount(); + + SecByteBlock block(modulusLen-1); + rng.GenerateBlock(block, modulusLen-2-plainTextLength); + memcpy(block+modulusLen-2-plainTextLength, plainText, plainTextLength); + block[modulusLen-2] = plainTextLength; + + a_times_b_mod_c(Integer(key, modulusLen), Integer(block, modulusLen-1), p).Encode(cipherText, modulusLen); + } + + DecodingResult SymmetricDecrypt(const byte *key, const byte *cipherText, unsigned int cipherTextLength, byte *plainText) const + { + const Integer &p = GetGroupParameters().GetModulus(); + unsigned int modulusLen = p.ByteCount(); + + if (cipherTextLength != modulusLen) + return DecodingResult(); + + Integer m = a_times_b_mod_c(Integer(cipherText, modulusLen), Integer(key, modulusLen).InverseMod(p), p); + + m.Encode(plainText, 1); + unsigned int plainTextLength = plainText[0]; + if (plainTextLength > GetMaxSymmetricPlaintextLength(modulusLen)) + return DecodingResult(); + m >>= 8; + m.Encode(plainText, plainTextLength); + return DecodingResult(plainTextLength); + } + + virtual const DL_GroupParameters_GFP & GetGroupParameters() const =0; +}; + +template +class ElGamalObjectImpl : public DL_ObjectImplBase, public ElGamalBase +{ +public: + unsigned int FixedMaxPlaintextLength() const {return MaxPlaintextLength(FixedCiphertextLength());} + unsigned int FixedCiphertextLength() const {return CiphertextLength(0);} + + const DL_GroupParameters_GFP & GetGroupParameters() const {return GetKey().GetGroupParameters();} + + DecodingResult FixedLengthDecrypt(const byte *cipherText, byte *plainText) const + {return Decrypt(cipherText, FixedCiphertextLength(), plainText);} + +protected: + const DL_KeyAgreementAlgorithm & GetKeyAgreementAlgorithm() const {return *this;} + const DL_KeyDerivationAlgorithm & GetKeyDerivationAlgorithm() const {return *this;} + const DL_SymmetricEncryptionAlgorithm & GetSymmetricEncryptionAlgorithm() const {return *this;} +}; + +struct ElGamalKeys +{ + typedef DL_CryptoKeys_GFP::GroupParameters GroupParameters; + typedef DL_PrivateKey_GFP_OldFormat PrivateKey; + typedef DL_PublicKey_GFP_OldFormat PublicKey; +}; + +//! ElGamal encryption scheme with non-standard padding +struct ElGamal +{ + typedef DL_CryptoSchemeOptions SchemeOptions; + + static const char * StaticAlgorithmName() {return "ElgamalEnc/Crypto++Padding";} + + class EncryptorImpl : public ElGamalObjectImpl, SchemeOptions, SchemeOptions::PublicKey>, public PublicKeyCopier + { + public: + void CopyKeyInto(SchemeOptions::PublicKey &key) const + {key = GetKey();} + }; + + class DecryptorImpl : public ElGamalObjectImpl, SchemeOptions, SchemeOptions::PrivateKey>, public PrivateKeyCopier + { + public: + void CopyKeyInto(SchemeOptions::PublicKey &key) const + {GetKey().MakePublicKey(key);} + void CopyKeyInto(SchemeOptions::PrivateKey &key) const + {key = GetKey();} + }; + + typedef SchemeOptions::GroupParameters GroupParameters; + //! implements PK_Encryptor interface + typedef PK_FinalTemplate Encryptor; + //! implements PK_Decryptor interface + typedef PK_FinalTemplate Decryptor; +}; + +typedef ElGamal::Encryptor ElGamalEncryptor; +typedef ElGamal::Decryptor ElGamalDecryptor; + +NAMESPACE_END + +#endif -- cgit v1.2.1