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() |