ElGamal Encryption
Prerequisites:
Cyclic Groups, Generators
Basic Number Theory (Euler's Theorem, Fermat's Little Theorem)
ElGamal Encryption System is an Asymmetric Key Encryption System based on Discrete Logarithm Problem (DLP) and Diffie-Hellman Key Exchange.
For illustrative purposes, we will consider Alice as the receiver and Bob as the sender.
There are different steps involved while encrypting or decrypting data with ElGamal, let's list them first and then study each of them in detail:
Key Generation: Alice generates a public and private key and shares the public key.
Encryption: Bob uses Alice's public to encrypt message that he wants to send to Alice, and hence generates a pair of ciphertext (c1, c2). Shares the ciphertext pair.
Decryption: Alice then uses her private key to decrypt the ciphertext (c1, c2).
Key Generation
This is the first step in the process of transferring a messages securely, between Alice and Bob. In this step, Alice does the following:
Selects a Cyclic Group
Gof orderqand generatorg. Note that either the cyclic group should be generated over a safe primep, or the generatorgshould generate prime-order-subgroups; otherwise it is vulnerable to Small Subgroup Attacks.Generates a random number
xsuch that1 <= x <= q-1and assigns it as the private key (Note thatqis the group order).Calculates

Shares
h,g,qas Public Keyxis the Private Key which only Alice should know, and that's where the security of the encryption system lies.
Here is a python-2.7 implementation of the above step:
Encryption
Bob receives Alice's Public Key and encrypts the message that he wants to send to Alice as follows:
Selects a random number
ysuch that1 <= y <= q-1. Note that a new value ofyis chosen for sending every message. Hence,yis known as ephemeral key.Chooses a message
msuch that1 < m < q-1Diffie Hellman Step: Calculates

Diffie Hellman Step, also
sis known as the shared secret: Calculates
Calculates

Shares (c1, c2) as the ciphertext
Here is a python-2.7 implementation of the above step:
Decryption
Alice receives (c1, c2), we can write them as:

Alice then calculates the following to get the shared secret
s:
To get back the message
mfrom c2, Alice does the following:
Here is a python-2.7 implementation of the above step:
Check out the full implementation/example of ElGamal encryption/decryption here