0

I am having much trouble encrypting the contents of the file at path accountfile. The encryption does indeed work, as the decryption successfully output the path of accountfile of a version where the path was being saved to the file. The code runs successfully without errors, but the encrypted file that is saved ends up being blank when encrypted. How do I get the contents of ptext to be successfully encrypted?

def encrypt_account(path, filename, accountfile):
    c_file = PurePath(path).parent / (PurePath(filename).parent.name + "c.txt")
    file3 = open(c_file, 'rb')
    byteskey = file3.read(32)
    file3.close()
    ckey = bytes(byteskey)

    cipher = AES.new(ckey, AES.MODE_CBC)
    ptext = open(str(accountfile)).read()# this is the account file
    ciphertext = cipher.encrypt(pad(bytes(ptext, "utf-8"), AES.block_size))

    with open(str(path.parent / accountfile.stem) + ".enc", 'wb')as c_file:
        c_file.write(cipher.iv)
        c_file.write(ciphertext)
    #c_file.close()
    #os.remove(accountfile)
atek
  • 3
  • 2
  • Have you tried `print()`ing any of the in-between values such as `ptext` or `ciphertext`? – AKX Oct 28 '20 at 09:04
  • No, I didn't. I feel like such a moron! I forgot to close the filestream in the function that calls this one. Thanks so much for the help! – atek Oct 28 '20 at 09:46
  • Look at (and heed the warnings in) my answer nevertheless. – AKX Oct 28 '20 at 09:55
  • Absolutely, I understand. This is for a cryptography class - it isn't intended to be used anywhere critical, just so I can show I understand the concepts. – atek Oct 28 '20 at 09:59

1 Answers1

1

Here's an example that does work, but PLEASE DON'T USE IT FOR ANYTHING SENSITIVE, SINCE IT IS NOT SECURE.

Proper use of cryptography primitives is HARD; you should instead use higher-level recipes that people smarter than you and I have written and certified to be secure when used correctly. My recommendation for Python is Fernet.

With that out of the way, you can write some secret data and generate a key, then run the script and get your secret data back at you:

$ echo "Very secret data" > secret.txt
$ dd if=/dev/urandom bs=1 count=32 > key.dat
32 bytes transferred
$ python so64569401.py
b'Very secret data\n'

However, as said, this is NOT secure, since the data is not authenticated; the ciphertext can be tampered with and you won't know the data is not what you put back in. For instance, if I remove the first encryption call, then modify a single byte from the encrypted file and run the script again:

$ hexf secret.txt.enc
$ python so64569401.py
b'Very secRet data\n'

from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad


def read_key(filename) -> bytes:
    with open(filename, "rb") as f:
        key = f.read(32)
        assert len(key) == 32
        return key


def encrypt_file(filename: str, key: bytes) -> str:
    with open(filename, "rb") as f:
        data = f.read()

    cipher = AES.new(key, AES.MODE_CBC)
    cipher_data = cipher.encrypt(pad(data, AES.block_size))

    encrypted_filename = filename + ".enc"

    with open(encrypted_filename, "wb") as f:
        f.write(cipher.iv)
        f.write(cipher_data)

    return encrypted_filename


def decrypt_file(filename: str, key: bytes) -> bytes:
    with open(filename, "rb") as f:
        iv = f.read(AES.block_size)
        cipher_data = f.read()

    cipher = AES.new(key, AES.MODE_CBC, iv=iv)
    return unpad(cipher.decrypt(cipher_data), AES.block_size)


def main():
    key = read_key("key.dat")
    encrypted_filename = encrypt_file("secret.txt", key)
    decrypted_data = decrypt_file(encrypted_filename, key)
    print(decrypted_data)


if __name__ == "__main__":
    main()
AKX
  • 152,115
  • 15
  • 115
  • 172