Source code for fcrypter.aes

# -*- coding: utf-8 -*-
from __future__ import absolute_import
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from fcrypter.base.templates import Cryptor


[docs]class AESCryptorEAX(Cryptor): """ AES EAX mode file encryption through use of pycryptodome AES library For details, see https://en.wikipedia.org/wiki/EAX_mode http://web.cs.ucdavis.edu/~rogaway/papers/eax.pdf """ def __init__(self): super(AESCryptorEAX, self).__init__(tuple([16, 24, 32])) @staticmethod def _write_crypto(finput, foutput, crypt_action): while True: txt = finput.read(1024) if not txt: break foutput.write(crypt_action(txt))
[docs] def encrypt_file(self, key, f_path, encr_fpath): """ Encrypts files, then digests. Provides plaintext & ciphertext integrity More info about "Encrypt then MAC" in Bellare & Namprempre paper: Authenticated Encryption: Relations among notions and analysis of the generic composition paradigm http://cseweb.ucsd.edu/~mihir/papers/oem.pdf Since AES library doesn't provide easy way to do this in seperate actions we add 16 dummy bytes as MAC, write the encrypted content and then seek the dummy bytes and overwrite with the correct MAC This allows us to read a file for encryption in small chunks to avoid insufficient memory errors """ self.verify_supported_key_size(key) cipher = AES.new(key, AES.MODE_EAX) with open(f_path, "rb") as fin, open(encr_fpath, "wr+b") as fout: fout.write(cipher.nonce) fout.write(get_random_bytes(16)) self._write_crypto(fin, fout, cipher.encrypt) fout.seek(16) fout.write(cipher.digest())
[docs] def decrypt_file(self, key, encr_fpath, decr_fpath): """ Decrypts file and verifies integrity """ self.verify_supported_key_size(key) with open(encr_fpath, "rb") as fin, open(decr_fpath, "wb") as fout: nonce, tag = [fin.read(x) for x in (16, 16)] cipher = AES.new(key, AES.MODE_EAX, nonce) self._write_crypto(fin, fout, cipher.decrypt) cipher.verify(tag)