#ifndef ELGAMAL_H #define ELGAMAL_H #include "nbtheory.h" class ElGamalCryptoPublicKey : public PK_WithPrecomputation { public: ElGamalCryptoPublicKey(const Integer &p, const Integer &g, const Integer &y); ElGamalCryptoPublicKey(BufferedTransformation &bt); ~ElGamalCryptoPublicKey(); void DEREncode(BufferedTransformation &bt) const; void Precompute(unsigned int precomputationStorage=16); void LoadPrecomputation(BufferedTransformation &storedPrecomputation); void SavePrecomputation(BufferedTransformation &storedPrecomputation) const; void Encrypt(RandomNumberGenerator &rng, const byte *plainText, unsigned int plainTextLength, byte *cipherText); unsigned int MaxPlainTextLength() const {return STDMIN(255U, modulusLen-3);} unsigned int CipherTextLength() const {return 2*modulusLen;} protected: ElGamalCryptoPublicKey() {} void RawEncrypt(const Integer &k, const Integer &m, Integer &a, Integer &b) const; unsigned int ExponentBitLength() const; Integer p, g, y; unsigned int modulusLen; ModExpPrecomputation gpc, ypc; }; class ElGamalCryptoPrivateKey : public ElGamalCryptoPublicKey, public PK_FixedLengthDecryptor { public: ElGamalCryptoPrivateKey(const Integer &p, const Integer &g, const Integer &y, const Integer &x); ElGamalCryptoPrivateKey(RandomNumberGenerator &rng, unsigned int pbits); // generate a random private key, given p and g ElGamalCryptoPrivateKey(RandomNumberGenerator &rng, const Integer &p, const Integer &g); ~ElGamalCryptoPrivateKey(); ElGamalCryptoPrivateKey(BufferedTransformation &bt); void DEREncode(BufferedTransformation &bt) const; unsigned int Decrypt(const byte *cipherText, byte *plainText); protected: void RawDecrypt(const Integer &a, const Integer &b, Integer &m) const; Integer x; }; class ElGamalSigPublicKey : public PK_WithPrecomputation { public: ElGamalSigPublicKey(const Integer &p, const Integer &q, const Integer &g, const Integer &y); ElGamalSigPublicKey(BufferedTransformation &bt); void DEREncode(BufferedTransformation &bt) const; void Precompute(unsigned int precomputationStorage=16); void LoadPrecomputation(BufferedTransformation &storedPrecomputation); void SavePrecomputation(BufferedTransformation &storedPrecomputation) const; bool Verify(const byte *message, unsigned int messageLen, const byte *signature); // message length for signature is unlimited, but only message digests should be signed unsigned int MaxMessageLength() const {return 0xffff;} unsigned int SignatureLength() const {return 2*qLen;} const Integer& GetPrime() { return p; } const Integer& GetParameterQ() { return q; } const Integer& GetParameterG() { return g; } const Integer& GetParameterY() { return y; } protected: ElGamalSigPublicKey() {} bool RawVerify(const Integer &m, const Integer &a, const Integer &b) const; unsigned int ExponentBitLength() const; Integer p, q, g, y; unsigned int qLen; ModExpPrecomputation gpc, ypc; }; class ElGamalSigPrivateKey : public ElGamalSigPublicKey, public PK_WithPrecomputation { public: ElGamalSigPrivateKey(const Integer &p, const Integer &q, const Integer &g, const Integer &y, const Integer &x); ElGamalSigPrivateKey(RandomNumberGenerator &rng, unsigned int pbits); // generate a random private key, given p and g ElGamalSigPrivateKey(RandomNumberGenerator &rng, const Integer &p, const Integer &q, const Integer &g); ElGamalSigPrivateKey(BufferedTransformation &bt); void DEREncode(BufferedTransformation &bt) const; void Sign(RandomNumberGenerator &rng, const byte *message, unsigned int messageLen, byte *signature); const Integer& GetParameterX() { return x; } protected: void RawSign(RandomNumberGenerator &rng, const Integer &m, Integer &a, Integer &b) const; Integer x; }; #endif