57 lines
		
	
	
		
			No EOL
		
	
	
		
			1.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			57 lines
		
	
	
		
			No EOL
		
	
	
		
			1.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
import random
 | 
						|
from Crypto.Util.number import getPrime
 | 
						|
 | 
						|
def elgamal_keygen(bits=512):
 | 
						|
    p = getPrime(bits)
 | 
						|
    g = random.randint(2, p-1)
 | 
						|
    x = random.randint(1, p-2)  # private key
 | 
						|
    h = pow(g, x, p)  # public key component
 | 
						|
    return (p, g, h), x
 | 
						|
 | 
						|
def elgamal_encrypt(message, pub_key):
 | 
						|
    p, g, h = pub_key
 | 
						|
    m = int.from_bytes(message.encode('utf-8'), 'big')
 | 
						|
    if m >= p:
 | 
						|
        raise ValueError("Message too large for key size")
 | 
						|
    
 | 
						|
    k = random.randint(1, p-2)
 | 
						|
    c1 = pow(g, k, p)
 | 
						|
    c2 = (m * pow(h, k, p)) % p
 | 
						|
    return (c1, c2)
 | 
						|
 | 
						|
def elgamal_decrypt(ciphertext, priv_key, pub_key):
 | 
						|
    c1, c2 = ciphertext
 | 
						|
    p, g, h = pub_key
 | 
						|
    x = priv_key
 | 
						|
    
 | 
						|
    s = pow(c1, x, p)
 | 
						|
    s_inv = pow(s, p-2, p)  # modular inverse
 | 
						|
    m = (c2 * s_inv) % p
 | 
						|
    
 | 
						|
    return m.to_bytes((m.bit_length() + 7) // 8, 'big').decode('utf-8')
 | 
						|
 | 
						|
def main():
 | 
						|
    print("Welcome to ElGamal")
 | 
						|
    ptext = input("Enter plaintext: ")
 | 
						|
    
 | 
						|
    # Generate keys
 | 
						|
    pub_key, priv_key = elgamal_keygen()
 | 
						|
    p, g, h = pub_key
 | 
						|
    
 | 
						|
    print(f"\nPublic Key (p, g, h):")
 | 
						|
    print(f"p = {hex(p)}")
 | 
						|
    print(f"g = {g}")
 | 
						|
    print(f"h = {hex(h)}")
 | 
						|
    
 | 
						|
    # Encrypt
 | 
						|
    ctext = elgamal_encrypt(ptext, pub_key)
 | 
						|
    print(f"\nCiphertext (c1, c2):")
 | 
						|
    print(f"c1 = {hex(ctext[0])}")
 | 
						|
    print(f"c2 = {hex(ctext[1])}")
 | 
						|
    
 | 
						|
    # Decrypt
 | 
						|
    decrypted = elgamal_decrypt(ctext, priv_key, pub_key)
 | 
						|
    print(f"Decrypted: {decrypted}")
 | 
						|
 | 
						|
if __name__ == '__main__':
 | 
						|
    main() |