108 lines
		
	
	
	
		
			2.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			108 lines
		
	
	
	
		
			2.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
import random
 | 
						|
from math import gcd, lcm
 | 
						|
from sympy import isprime, randprime
 | 
						|
 | 
						|
 | 
						|
def generate_prime(bits=512):
 | 
						|
    # Use sympy's randprime for efficiency
 | 
						|
    return randprime(2 ** (bits - 1), 2**bits)
 | 
						|
 | 
						|
 | 
						|
def generate_keypair(bits=512):
 | 
						|
    p = generate_prime(bits)
 | 
						|
    q = generate_prime(bits)
 | 
						|
 | 
						|
    n = p * q
 | 
						|
    n_squared = n * n
 | 
						|
    lambda_n = lcm(p - 1, q - 1)
 | 
						|
 | 
						|
    g = n + 1
 | 
						|
 | 
						|
    def L(x):
 | 
						|
        return (x - 1) // n
 | 
						|
 | 
						|
    # Convert to int to avoid sympy Integer type issues
 | 
						|
    mu = pow(int(L(pow(g, int(lambda_n), n_squared))), -1, n)
 | 
						|
 | 
						|
    public_key = (n, g)
 | 
						|
    private_key = (int(lambda_n), mu)
 | 
						|
 | 
						|
    return public_key, private_key
 | 
						|
 | 
						|
 | 
						|
def encrypt(public_key, plaintext):
 | 
						|
    n, g = public_key
 | 
						|
    n_squared = n * n
 | 
						|
 | 
						|
    while True:
 | 
						|
        r = random.randint(1, n - 1)
 | 
						|
        if gcd(r, n) == 1:
 | 
						|
            break
 | 
						|
 | 
						|
    ciphertext = (pow(g, plaintext, n_squared) * pow(r, n, n_squared)) % n_squared
 | 
						|
 | 
						|
    return ciphertext
 | 
						|
 | 
						|
 | 
						|
def decrypt(public_key, private_key, ciphertext):
 | 
						|
    n, g = public_key
 | 
						|
    lambda_n, mu = private_key
 | 
						|
    n_squared = n * n
 | 
						|
 | 
						|
    def L(x):
 | 
						|
        return (x - 1) // n
 | 
						|
 | 
						|
    plaintext = (L(pow(ciphertext, lambda_n, n_squared)) * mu) % n
 | 
						|
 | 
						|
    return plaintext
 | 
						|
 | 
						|
 | 
						|
def homomorphic_add(public_key, ciphertext1, ciphertext2):
 | 
						|
    n, g = public_key
 | 
						|
    n_squared = n * n
 | 
						|
 | 
						|
    result = (ciphertext1 * ciphertext2) % n_squared
 | 
						|
 | 
						|
    return result
 | 
						|
 | 
						|
 | 
						|
def main():
 | 
						|
    print("Paillier Encryption Scheme Implementation\n")
 | 
						|
 | 
						|
    print("Generating keypair...")
 | 
						|
    public_key, private_key = generate_keypair(bits=512)
 | 
						|
    print("Keys generated successfully.\n")
 | 
						|
 | 
						|
    # Get user input for the integers
 | 
						|
    try:
 | 
						|
        m1 = int(input("Enter the first integer: "))
 | 
						|
        m2 = int(input("Enter the second integer: "))
 | 
						|
    except ValueError:
 | 
						|
        print("Invalid input. Please enter valid integers.")
 | 
						|
        return
 | 
						|
 | 
						|
    print(f"\nOriginal integers: {m1} and {m2}")
 | 
						|
    print(f"Expected sum: {m1 + m2}\n")
 | 
						|
 | 
						|
    print("Encrypting integers...")
 | 
						|
    c1 = encrypt(public_key, m1)
 | 
						|
    c2 = encrypt(public_key, m2)
 | 
						|
    print(f"Ciphertext of {m1}: {c1}")
 | 
						|
    print(f"Ciphertext of {m2}: {c2}\n")
 | 
						|
 | 
						|
    print("Performing homomorphic addition on encrypted values...")
 | 
						|
    c_sum = homomorphic_add(public_key, c1, c2)
 | 
						|
    print(f"Encrypted sum: {c_sum}\n")
 | 
						|
 | 
						|
    print("Decrypting the result...")
 | 
						|
    decrypted_sum = decrypt(public_key, private_key, c_sum)
 | 
						|
    print(f"Decrypted sum: {decrypted_sum}\n")
 | 
						|
 | 
						|
    if decrypted_sum == m1 + m2:
 | 
						|
        print("✓ Verification successful! The decrypted sum matches the original sum.")
 | 
						|
    else:
 | 
						|
        print("✗ Verification failed! The decrypted sum does not match.")
 | 
						|
 | 
						|
 | 
						|
if __name__ == "__main__":
 | 
						|
    main()
 |