58 lines
		
	
	
		
			No EOL
		
	
	
		
			1.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			58 lines
		
	
	
		
			No EOL
		
	
	
		
			1.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
from Crypto.PublicKey import ECC
 | 
						|
from Crypto.Cipher import AES
 | 
						|
from Crypto.Hash import SHA256
 | 
						|
import binascii
 | 
						|
 | 
						|
 | 
						|
def ecc_keygen(curve: str = 'P-256') -> ECC.EccKey:
 | 
						|
    return ECC.generate(curve=curve)
 | 
						|
 | 
						|
 | 
						|
def ecc_encrypt(plaintext: str, recipient_public_key: ECC.EccKey):
 | 
						|
    eph_private = ECC.generate(curve=recipient_public_key.curve)
 | 
						|
    shared_point = recipient_public_key.pointQ * eph_private.d
 | 
						|
    shared_x = int(shared_point.x)
 | 
						|
    aes_key = SHA256.new(shared_x.to_bytes(32, 'big')).digest()
 | 
						|
 | 
						|
    cipher = AES.new(aes_key, AES.MODE_GCM)
 | 
						|
    ciphertext, tag = cipher.encrypt_and_digest(plaintext.encode('utf-8'))
 | 
						|
 | 
						|
    return {
 | 
						|
        'ephemeral_pub_der': eph_private.public_key().export_key(format='DER'),
 | 
						|
        'nonce': cipher.nonce,
 | 
						|
        'tag': tag,
 | 
						|
        'ciphertext': ciphertext,
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
def ecc_decrypt(enc: dict, recipient_private_key: ECC.EccKey) -> str:
 | 
						|
    eph_public = ECC.import_key(enc['ephemeral_pub_der'])
 | 
						|
    shared_point = eph_public.pointQ * recipient_private_key.d
 | 
						|
    shared_x = int(shared_point.x)
 | 
						|
    aes_key = SHA256.new(shared_x.to_bytes(32, 'big')).digest()
 | 
						|
 | 
						|
    cipher = AES.new(aes_key, AES.MODE_GCM, nonce=enc['nonce'])
 | 
						|
    plaintext = cipher.decrypt_and_verify(enc['ciphertext'], enc['tag'])
 | 
						|
    return plaintext.decode('utf-8')
 | 
						|
 | 
						|
 | 
						|
def main():
 | 
						|
    print('Welcome to ECC (ECIES-style)')
 | 
						|
    ptext = input('Enter plaintext: ')
 | 
						|
 | 
						|
    priv_key = ecc_keygen()
 | 
						|
    pub_key = priv_key.public_key()
 | 
						|
 | 
						|
    print('\nPublic Key (Qx, Qy):')
 | 
						|
    print('Qx =', hex(int(pub_key.pointQ.x)))
 | 
						|
    print('Qy =', hex(int(pub_key.pointQ.y)))
 | 
						|
 | 
						|
    enc = ecc_encrypt(ptext, pub_key)
 | 
						|
    print("\nYour ciphertext (hex):", binascii.hexlify(enc['ciphertext']).decode())
 | 
						|
 | 
						|
    decrypted = ecc_decrypt(enc, priv_key)
 | 
						|
    print('Your decrypted plaintext:', decrypted)
 | 
						|
 | 
						|
 | 
						|
if __name__ == '__main__':
 | 
						|
    main() |