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<q1.
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  0Mq1. 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 1kq1
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=(C2K1(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 K1 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)
(C2K1)(modq)=KMK1(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.

Alice generates a key pair as follows:
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}.

Suppose Bob wants to send the message with the value M=17. Then:

1.Bob chooses k=6.
2.Then K=(YA)k(modq)=36(mod19)=729(mod19)=7.
3.So
C1=αk(modq)=106(mod19)=11
C2=KM(modq)=717(mod19)=119(mod19)=5
4. Bob sends the ciphertext (11,5).

For decryption:

1.Alice calculates K=(C1)XA(modq)=115(mod19)=161051(mod19)=7.
2.Then K1 in GF(19) is 71(mod19)=11.
3.Finally,M=(C2K1)(modq)=511(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 as

M2=(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 q1 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

Popular posts from this blog

Cryptographic Algorithms CST 393 KTU CS Honour Notes Semester V -Dr Binu V P

OSI Security Architecture

Data Encryption Standard - DES Algorithm