3
\$\begingroup\$

I'n written this small file encryption module to work on my skills with the os module. It's my very first time using it to navigate files and file structures, so I'm sure some things can be improved. I used the following file structure to ensure it works with multiple directories:

File Structure

.
├── files
│   ├── files
│   │   ├── test.txt
│   │   ├── test2.txt
│   │   └── test3.txt
│   ├── files2
│   │   ├── files
│   │   │   ├── test.txt
│   │   │   ├── test2.txt
│   │   │   └── test3.txt
│   │   ├── test.txt
│   │   ├── test2.txt
│   │   └── test3.txt
│   ├── test.txt
│   ├── test2.txt
│   └── test3.txt
├── key.py
└── virus.py

It works flawlessly. I'm looking for feedback on a couple topics:

  1. os module: Are there other functions in the os module that could be used to accomplish the same thing, but easier or faster?
  2. file management: Is there a faster way to work with files than I did? The time it takes is noticeable ( 0s < time < 1s for a file of ~2500 characters) but I'm sure it gets longer with bigger files.
"""
File Encryption & Decryption
"""

import os
from cryptography.fernet import Fernet

from key import KEY

DIRECTORY = "files"
FERNET = Fernet(KEY)

def crypt(encrypt=True) -> None:
    """
    Encrypts/Decrypts the files in DIRECTORY
    """

    for root, _, files in os.walk(DIRECTORY, topdown=True):
        for name in files:
            file = os.path.join(root, name)

            with open(file, "rb") as in_file:
                data = in_file.read()

            data = FERNET.encrypt(data) if encrypt else FERNET.decrypt(data)

            with open(file, "wb") as out_file:
                out_file.write(data)

if __name__ == '__main__':

    # Encrypt #
    crypt()

    # Decrypt #
    crypt(encrypt=False)
\$\endgroup\$

1 Answer 1

4
\$\begingroup\$

Some suggestions:

  1. Boolean arguments are a code smell. Especially in a case like this you'd want to have separate encrypt and decrypt functions, which both reuse a third function which does all the bookkeeping. In this case the third function could just take the FERNET.encrypt or FERNET.decrypt method as an argument, and apply it to the data.
  2. For this to be generally usable you'll want to add some argument parsing, possibly with argparse, to be able to pass an arbitrary path to work with.
  3. The key should not be in code - it's just data, and should be stored in the original key format. If it's just a /dev/urandom dump with no structure to it that would be a .bin format, but I'm not familiar with Fernet. The code would normally be told about the key by passing a path argument or by passing the contents on standard input.

Generally I wouldn't worry about encryption and decryption taking a long time. If your key is too long (algorithm-specific) it could slow down the algorithm considerably, but many algorithms can be considered quite slow with common inputs. I don't know why you chose Fernet specifically, but there are many algorithms available, and you might want to evaluate them for strength and speed.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.