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