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).
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
G
of orderq
and generatorg
. Note that either the cyclic group should be generated over a safe primep
, or the generatorg
should generate prime-order-subgroups; otherwise it is vulnerable to Small Subgroup Attacks. - Generates a random number
x
such that1 <= x <= q-1
and assigns it as the private key (Note thatq
is the group order). - Calculates
- Shares
h
,g
,q
as Public Key x
is 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:
def _generate_key():
# Assigning the largest 1024-bit safe prime as p
p = (1 << 1024) - 1093337
x = randint(2, p-2)
g = 23
q = p - 1
h = pow(g, x, p)
pubkey = PublicKey(h, p, g, q)
privkey = PrivateKey(x, p, g, q)
return (pubkey, privkey)
Bob receives Alice's Public Key and encrypts the message that he wants to send to Alice as follows:
- Selects a random number
y
such that1 <= y <= q-1
. Note that a new value ofy
is chosen for sending every message. Hence,y
is known as ephemeral key. - Chooses a message
m
such that1 < m < q-1
- Diffie Hellman Step: Calculates
- Diffie Hellman Step, also
s
is known as the shared secret: Calculates - Calculates
- Shares (c1, c2) as the ciphertext
Here is a python-2.7 implementation of the above step:
def _encrypt(message, pubkey):
h = pubkey.h
p = pubkey.p
g = pubkey.g
q = pubkey.q
m = bytes_to_long(message)
# Generating ephemeral key: `y`
y = randint(2, p-2)
c1 = pow(g, y, p)
# Computing the shared secret: `s`
s = pow(h, y, p)
c2 = (m*s) % p
return (c1, c2)
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
m
from c2, Alice does the following:
Here is a python-2.7 implementation of the above step:
def _decrypt(ciphertext, privkey):
c1, c2 = ciphertext
g = privkey.g
p = privkey.p
x = privkey.x
s = pow(c1, x, p)
m = (c2*inverse(s, p)) % p
return m
Check out the full implementation/example of ElGamal encryption/decryption here