File indexing completed on 2025-01-18 09:55:02
0001
0002
0003
0004
0005
0006 #ifndef CRYPTOPP_ELGAMAL_H
0007 #define CRYPTOPP_ELGAMAL_H
0008
0009 #include "cryptlib.h"
0010 #include "modexppc.h"
0011 #include "integer.h"
0012 #include "gfpcrypt.h"
0013 #include "pubkey.h"
0014 #include "misc.h"
0015 #include "oids.h"
0016 #include "dsa.h"
0017 #include "asn.h"
0018
0019 NAMESPACE_BEGIN(CryptoPP)
0020
0021
0022
0023 class CRYPTOPP_NO_VTABLE ElGamalBase :
0024 public DL_KeyAgreementAlgorithm_DH<Integer, NoCofactorMultiplication>,
0025 public DL_KeyDerivationAlgorithm<Integer>,
0026 public DL_SymmetricEncryptionAlgorithm
0027 {
0028 public:
0029 virtual ~ElGamalBase() {}
0030
0031 void Derive(const DL_GroupParameters<Integer> &groupParams, byte *derivedKey, size_t derivedLength, const Integer &agreedElement, const Integer &ephemeralPublicKey, const NameValuePairs &derivationParams) const
0032 {
0033 CRYPTOPP_UNUSED(groupParams); CRYPTOPP_UNUSED(ephemeralPublicKey);
0034 CRYPTOPP_UNUSED(derivationParams);
0035 agreedElement.Encode(derivedKey, derivedLength);
0036 }
0037
0038 size_t GetSymmetricKeyLength(size_t plainTextLength) const
0039 {
0040 CRYPTOPP_UNUSED(plainTextLength);
0041 return GetGroupParameters().GetModulus().ByteCount();
0042 }
0043
0044 size_t GetSymmetricCiphertextLength(size_t plainTextLength) const
0045 {
0046 unsigned int len = GetGroupParameters().GetModulus().ByteCount();
0047 if (plainTextLength <= GetMaxSymmetricPlaintextLength(len))
0048 return len;
0049 else
0050 return 0;
0051 }
0052
0053 size_t GetMaxSymmetricPlaintextLength(size_t cipherTextLength) const
0054 {
0055 unsigned int len = GetGroupParameters().GetModulus().ByteCount();
0056 CRYPTOPP_ASSERT(len >= 3);
0057
0058 if (cipherTextLength == len)
0059 return STDMIN(255U, len-3);
0060 else
0061 return 0;
0062 }
0063
0064 void SymmetricEncrypt(RandomNumberGenerator &rng, const byte *key, const byte *plainText, size_t plainTextLength, byte *cipherText, const NameValuePairs ¶meters) const
0065 {
0066 CRYPTOPP_UNUSED(parameters);
0067 const Integer &p = GetGroupParameters().GetModulus();
0068 unsigned int modulusLen = p.ByteCount();
0069
0070 SecByteBlock block(modulusLen-1);
0071 rng.GenerateBlock(block, modulusLen-2-plainTextLength);
0072 std::memcpy(block+modulusLen-2-plainTextLength, plainText, plainTextLength);
0073 block[modulusLen-2] = (byte)plainTextLength;
0074
0075 a_times_b_mod_c(Integer(key, modulusLen), Integer(block, modulusLen-1), p).Encode(cipherText, modulusLen);
0076 }
0077
0078 DecodingResult SymmetricDecrypt(const byte *key, const byte *cipherText, size_t cipherTextLength, byte *plainText, const NameValuePairs ¶meters) const
0079 {
0080 CRYPTOPP_UNUSED(parameters);
0081 const Integer &p = GetGroupParameters().GetModulus();
0082 unsigned int modulusLen = p.ByteCount();
0083
0084 if (cipherTextLength != modulusLen)
0085 return DecodingResult();
0086
0087 Integer m = a_times_b_mod_c(Integer(cipherText, modulusLen), Integer(key, modulusLen).InverseMod(p), p);
0088
0089 m.Encode(plainText, 1);
0090 unsigned int plainTextLength = plainText[0];
0091 if (plainTextLength > GetMaxSymmetricPlaintextLength(modulusLen))
0092 return DecodingResult();
0093 m >>= 8;
0094 m.Encode(plainText, plainTextLength);
0095 return DecodingResult(plainTextLength);
0096 }
0097
0098 virtual const DL_GroupParameters_GFP & GetGroupParameters() const =0;
0099 };
0100
0101
0102
0103
0104
0105
0106 template <class BASE, class SCHEME_OPTIONS, class KEY>
0107 class ElGamalObjectImpl :
0108 public DL_ObjectImplBase<BASE, SCHEME_OPTIONS, KEY>,
0109 public ElGamalBase
0110 {
0111 public:
0112 virtual ~ElGamalObjectImpl() {}
0113
0114 size_t FixedMaxPlaintextLength() const {return this->MaxPlaintextLength(FixedCiphertextLength());}
0115 size_t FixedCiphertextLength() const {return this->CiphertextLength(0);}
0116
0117 const DL_GroupParameters_GFP & GetGroupParameters() const {return this->GetKey().GetGroupParameters();}
0118
0119 DecodingResult FixedLengthDecrypt(RandomNumberGenerator &rng, const byte *cipherText, byte *plainText) const
0120 {return Decrypt(rng, cipherText, FixedCiphertextLength(), plainText);}
0121
0122 protected:
0123 const DL_KeyAgreementAlgorithm<Integer> & GetKeyAgreementAlgorithm() const {return *this;}
0124 const DL_KeyDerivationAlgorithm<Integer> & GetKeyDerivationAlgorithm() const {return *this;}
0125 const DL_SymmetricEncryptionAlgorithm & GetSymmetricEncryptionAlgorithm() const {return *this;}
0126 };
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139 template <class BASE>
0140 struct DL_PublicKey_ElGamal : public BASE
0141 {
0142 virtual ~DL_PublicKey_ElGamal() {}
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154 virtual OID GetAlgorithmID() const {
0155 return ASN1::elGamal();
0156 }
0157 };
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170 template <class BASE>
0171 struct DL_PrivateKey_ElGamal : public BASE
0172 {
0173 virtual ~DL_PrivateKey_ElGamal() {}
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185 virtual OID GetAlgorithmID() const {
0186 return ASN1::elGamal();
0187 }
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206 bool Validate(RandomNumberGenerator &rng, unsigned int level) const
0207 {
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218 CRYPTOPP_ASSERT(this->GetAbstractGroupParameters().Validate(rng, level));
0219 bool pass = this->GetAbstractGroupParameters().Validate(rng, level);
0220
0221 const Integer &p = this->GetGroupParameters().GetModulus();
0222 const Integer &q = this->GetAbstractGroupParameters().GetSubgroupOrder();
0223 const Integer &x = this->GetPrivateExponent();
0224
0225
0226 CRYPTOPP_ASSERT(x.IsPositive());
0227 CRYPTOPP_ASSERT(x < p-1);
0228 pass = pass && x.IsPositive() && x < p-1;
0229
0230 if (level >= 1)
0231 {
0232
0233 CRYPTOPP_ASSERT(Integer::Gcd(x, q) == Integer::One());
0234 pass = pass && Integer::Gcd(x, q) == Integer::One();
0235 }
0236 return pass;
0237 }
0238 };
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261 struct ElGamalKeys
0262 {
0263
0264 typedef DL_CryptoKeys_ElGamal::GroupParameters GroupParameters;
0265
0266 typedef DL_PrivateKey_ElGamal<DL_CryptoKeys_ElGamal::PrivateKey> PrivateKey;
0267
0268 typedef DL_PublicKey_ElGamal<DL_CryptoKeys_ElGamal::PublicKey> PublicKey;
0269 };
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283 struct ElGamal
0284 {
0285 typedef DL_CryptoSchemeOptions<ElGamal, ElGamalKeys, int, int, int> SchemeOptions;
0286 typedef SchemeOptions::PrivateKey PrivateKey;
0287 typedef SchemeOptions::PublicKey PublicKey;
0288
0289
0290
0291
0292
0293 CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "ElgamalEnc/Crypto++Padding";}
0294
0295
0296 typedef SchemeOptions::GroupParameters GroupParameters;
0297
0298 typedef PK_FinalTemplate<ElGamalObjectImpl<DL_EncryptorBase<Integer>, SchemeOptions, SchemeOptions::PublicKey> > Encryptor;
0299
0300 typedef PK_FinalTemplate<ElGamalObjectImpl<DL_DecryptorBase<Integer>, SchemeOptions, SchemeOptions::PrivateKey> > Decryptor;
0301 };
0302
0303 typedef ElGamal::Encryptor ElGamalEncryptor;
0304 typedef ElGamal::Decryptor ElGamalDecryptor;
0305
0306 NAMESPACE_END
0307
0308 #endif