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 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> ¶ms, byte *derivedKey, unsigned int derivedLength, const Integer &agreedElement, const Integer &ephemeralPublicKey) const
00015 {
00016 agreedElement.Encode(derivedKey, derivedLength);
00017 }
00018
00019 unsigned int GetSymmetricKeyLength(unsigned int plainTextLength) const
00020 {
00021 return GetGroupParameters().GetModulus().ByteCount();
00022 }
00023
00024 unsigned int GetSymmetricCiphertextLength(unsigned int 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 unsigned int GetMaxSymmetricPlaintextLength(unsigned int 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, unsigned int plainTextLength, byte *cipherText) 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] = 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, unsigned int cipherTextLength, byte *plainText) 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 unsigned int FixedMaxPlaintextLength() const {return MaxPlaintextLength(FixedCiphertextLength());}
00082 unsigned int FixedCiphertextLength() const {return CiphertextLength(0);}
00083
00084 const DL_GroupParameters_GFP & GetGroupParameters() const {return 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
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 class EncryptorImpl : public ElGamalObjectImpl<DL_EncryptorBase<Integer, PK_FixedLengthEncryptor>, SchemeOptions, SchemeOptions::PublicKey>, public PublicKeyCopier<SchemeOptions>
00110 {
00111 public:
00112 void CopyKeyInto(SchemeOptions::PublicKey &key) const
00113 {key = GetKey();}
00114 };
00115
00116 class DecryptorImpl : public ElGamalObjectImpl<DL_DecryptorBase<Integer, PK_FixedLengthDecryptor>, SchemeOptions, SchemeOptions::PrivateKey>, public PrivateKeyCopier<SchemeOptions>
00117 {
00118 public:
00119 void CopyKeyInto(SchemeOptions::PublicKey &key) const
00120 {GetKey().MakePublicKey(key);}
00121 void CopyKeyInto(SchemeOptions::PrivateKey &key) const
00122 {key = GetKey();}
00123 };
00124
00125 typedef SchemeOptions::GroupParameters GroupParameters;
00126
00127 typedef PK_FinalTemplate<EncryptorImpl> Encryptor;
00128
00129 typedef PK_FinalTemplate<DecryptorImpl> Decryptor;
00130 };
00131
00132 typedef ElGamal::Encryptor ElGamalEncryptor;
00133 typedef ElGamal::Decryptor ElGamalDecryptor;
00134
00135 NAMESPACE_END
00136
00137 #endif