AES + RSA Hybrid

Lesson 34: AES + RSA Hybrid encryption

Sender:

#hybrid eax mode sender

from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from Crypto.Random import get_random_bytes

from Crypto.Cipher import PKCS1_OAEP
from Crypto.PublicKey import RSA

#create random aes symmetric key
aeskey = get_random_bytes(16) #16 bytes = 128bit encryption
#get recipients public rsa key
with open('rpub.pem', 'rb') as f:
    pubkey= f.read()
rsakey = RSA.importKey(pubkey)
rsacipher = PKCS1_OAEP.new(rsakey)
e_aeskey = rsacipher.encrypt(aeskey)

#use aes key to encrypt file (AES symmetric)
with open('tux.png', 'rb') as f:
    data = f.read()

aescipher = AES.new(aeskey, AES.MODE_EAX)
e_data, tag = aescipher.encrypt_and_digest(data)


#write both encrypted aes key and encrypted file to one bundled file
with open('bundle.enc', 'wb') as f:
    f.write(e_aeskey) #256 bytes
    f.write(aescipher.nonce) #16 bytes
    f.write(tag) #16 bytes
    f.write(e_data)

Recipient:

# hybrid eax mode recipient

from Crypto.Cipher import AES

from Crypto.Cipher import PKCS1_OAEP
from Crypto.PublicKey import RSA

with open('bundle.enc', 'rb') as f:
    e_aeskey = f.read(256)
    #16 byte aes key becomes 256 bytes after rsa encryption
    nonce = f.read(16)
    tag = f.read(16)
    e_data = f.read()

with open('private.pem') as f:
    key = f.read()

privkey = RSA.importKey(key)
rsacipher = PKCS1_OAEP.new(privkey)

aeskey = rsacipher.decrypt(e_aeskey)
try:
    aescipher = AES.new(aeskey, AES.MODE_EAX, nonce)
    data = aescipher.decrypt_and_verify(e_data, tag)
except:
    print('Decryption or Authenticity failure')

with open('tux4.png', 'wb') as f:
    f.write(data)