Elgamal Cryptographic System
In 1984, T. Elgamal announced a public-key scheme based on discrete logarithms, closely related to the Diffie-Hellman technique.The ElGamal cryptosystem is used in some form in a number of standards including the digital signature standard (DSS), and the S/MIME e-mail standard.
As with Diffie-Hellman, the global elements of ElGamal are a prime number q and α , which is a primitive root of q. User A generates a private/public key pair as follows:
1.Generate a random integer XA , such that 1<XA<q−1.
2.Compute YA=αXA(modq)
3. A’s private key is XA ;A’s pubic key is [q,α,YA]
Any user B that has access to A’s public key can encrypt a message as follows:
1. Represent the message M as an integer in the range 0≤M≤q−1. Longer messages are sent as a sequence of blocks, with each block being an integer less than q
2. Choose a random integer k such that 1≤k≤q−1
3.Compute a one-time key K=(YA)k(modq)
4.Encrypt M as the pair of integers (C1,C2) , where
C1=αk(modq); C2=KM(modq)
User A recovers the plaintext as follows:
1. Recover the key by computing K=(C1)XA(modq).
2.Compute M=(C2K−1(modq)
We can restate the ElGamal process as follows, using Figure below
1. Bob generates a random integer k.
2. Bob generates a one-time key K using Alice’s public-key components YA,q, and k.
3. Bob encrypts k using the public-key component α, yielding C1 . C1 provides sufficient information for Alice to recover K.
4. Bob encrypts the plaintext message M using K.
5. Alice recovers K from C1 using her private key .
6. Alice uses K−1 to recover the plaintext message from C2.
Thus K, functions as a one-time key, used to encrypt and decrypt the message
Let us demonstrate why the ElGamal scheme works. First, we show how K is recovered by the decryption process:
K=(YA)k(modq) K is defined during the encryption process
K=(αXA(modq))k(modq) substitute using YA=αXA(modq)
K=αkXA(modq) by the rules of modular arithmetic
K=(C1)XA(modq) substitute using C1=αk(modq)
Next, using K , we recover the plaintext as
C2=KM(modq)
(C2K−1)(modq)=KMK−1(modq)=M(modq)=M
Example:
For example, let us start with the prime field GF(19); that is, q=19. It has primitive roots {2, 3, 10, 13, 14, 15}. We choose α=10.
1.Alice chooses XA=5.
2.Then YA=αXA(modq)=105(mod19)=3
3.Alice’s private key is 5 and Alice’s public key is {q,α,YA}={19,10,3}.
2.Then K=(YA)k(modq)=36(mod19)=729(mod19)=7.
3.So
C1=αk(modq)=106(mod19)=11
C2=KM(modq)=7∗17(mod19)=119(mod19)=5
4. Bob sends the ciphertext (11,5).
1.Alice calculates K=(C1)XA(modq)=115(mod19)=161051(mod19)=7.
2.Then K−1 in GF(19) is 7−1(mod19)=11.
3.Finally,M=(C2K−1)(modq)=5∗11(mod19)=55(mod19)=17.
If a message must be broken up into blocks and sent as a sequence of encrypted blocks, a unique value of k should be used for each block. If k is used for more than one block, knowledge of one block M1 of the message enables the user to compute other blocks as follows. Let
C1,1=αk(modq);C2,1=KM1(modq)
C1,2=αk(modq);C2,2=KM2(modq)
Then,C2,1C2,2=KM1(modq)KM2(modq)=M1(modq)M2(modq)
If M1 is known, then M2 is easily computed asM2=(C2,1)−1C2,2M1(modq)
The security of Elgamal is based on the difficulty of computing discrete logarithms. To recover A’s private key, an adversary would have to compute XA=dlogα,q(YA). Alternatively, to recover the one-time key K, an adversary would have to determine the random number k, and this would require computing the discrete logarithm k=dlogα,q(C1). These calculations are regarded as infeasible if q is at least 300 decimal digits and q−1 has at least one “large” prime factor.
Python code - Elgamal Crypto System
import random
from sympy import mod_inverse
# Function to calculate modular exponentiation
# Function to generate keys
def generate_keys(p, g):
# Private key
#xa = random.randint(1, p - 2) # x < p-1
xa=5
# Public key
ya = pow(g, xa, p)
return (p, g, ya), xa # (Public Key, Private Key)
# Function to encrypt a message
def encrypt(public_key, m):
p, g, ya = public_key
#k = random.randint(1, p - 2) # k < p-1
k=6
K= pow(ya, k, p)
c1=pow(g,k,p)
c2=(K*m) %p
return c1, c2
# Function to decrypt a message
def decrypt(private_key,p,cipher):
xa=private_key
c1=cipher[0]
K=pow(c1,xa,p)
K_inv=mod_inverse(K,p)
c2 = cipher[1]
m=(c2*K_inv) % p
return m
# Example usage
if __name__ == "__main__":
# Prime number p and generator g
p = 19 # A prime number
g = 10 # A generator for Z_p*
# Generate keys
public_key, private_key = generate_keys(p, g)
print("Public Key:", public_key)
print("Private Key:", private_key)
# Message to be encrypted
message = 17 # Message should be less than p
print("Original Message:", message)
# Encrypt the message
cipher = encrypt(public_key, message)
print("Encrypted Message:", cipher)
# Decrypt the message
decrypted_message = decrypt(private_key,p, cipher)
print("Decrypted Message:", decrypted_message)
Output:
Public Key: (19, 10, 3) Private Key: 5
Original Message: 17
Encrypted Message: (11, 5)
Decrypted Message: 17
Comments
Post a Comment