Tool zum ver- und entschlüsseln von Dateien und Ordnern

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Antworten
Jankie
User
Beiträge: 592
Registriert: Mittwoch 26. September 2018, 14:06

Hey,

ich habe ein Tool geschrieben, mit dem man Dateien und Ordner AES verschlüsseln kann und es funktioniert soweit wie ich es mir vorstelle. Allerdings bin ich nicht wirklich sehr erfahren und wollte deshalb fragen ob sich jemand Zeit nehmen kann um mal über den Code drüber zu schauen und ggf. Verbesserungen/Hinweise rückmelden kann, da ich gleube ich einige Sachen sehr umständlich gemacht habe. Würde mich sehr freuen.


Code: Alles auswählen

import pyAesCrypt
import os
import getpass
import shutil

BUFFER_SIZE = 64 * 1024


def get_filename_and_password():
    filename = input("Name der Datei: ")
    password = getpass.getpass("Passwort: ")
    return filename, password
       
    
def encrypt_file(filename, password):
    try:
        pyAesCrypt.encryptFile(filename, f"{filename}.aes", password, BUFFER_SIZE)
        print("Datei erfolgreich verschlüsselt!")
        if input("Soll die unverschlüsselte Ursprungsdatei gelöscht werden (j/n)?: ") == "j":
            os.remove(filename)
            print("Datei gelöscht!")
    except OSError:
        print("Datei nicht gefunden.")

def decrypt_file(filename, password):
    try:
        pyAesCrypt.decryptFile(filename, filename[:-4], password, BUFFER_SIZE)
        print("Datei erfolgreich entschlüsselt!")
        if input("Soll die verschlüsselte Ursprungsdatei gelöscht werden (j/n)?: ") == "j":
            os.remove(filename)
            print("Datei gelöscht!")
    except ValueError:
        print("Falsches Passwort!")
    except OSError:
        print("Datei nicht gefunden.")


def zip_and_encrypt_folder(filename, password):
    try:
        shutil.make_archive(filename, 'zip', ".", filename)
        pyAesCrypt.encryptFile(f"{filename}.zip", f"{filename}.aes", password, BUFFER_SIZE)
        print("Datei erfolgreich verschlüsselt!")
        if input("Sollen die unverschlüsselten Ursprungsdateien gelöscht werden (j/n)?: ") == "j":
            os.remove(f"{filename}.zip")
            shutil.rmtree(filename)
            print("Dateien gelöscht!")
    except OSError:
        print("Datei nicht gefunden.")
    except FileNotFoundError:
        print("Datei nicht gefunden.")


def decrypt_and_unzip_folder(filename, password):
    try:
        pyAesCrypt.decryptFile(filename, f"{filename[:-4]}.zip", password, BUFFER_SIZE)
        shutil.unpack_archive(f"{filename[:-4]}.zip")
        print("Archiv erfolgreich entpackt!")
        if input("Sollen die verschlüsselten Ursprungsdateien gelöscht werden (j/n)?: ") == "j":
            os.remove(f"{filename[:-4]}.zip")
            os.remove(filename)
            print("Dateien gelöscht!")
    except ValueError:
        print("Falsches Passwort!")
    except OSError:
        print("Datei nicht gefunden.")


def main():
    auswahl = int(input("""
Was möchtest du tun?
    
1 - Datei verschlüsseln
2 - Datei entschlüsseln
3 - Ordner archivieren und verschlüsseln
4 - Ordner entpacken und entschlüsseln

>"""))
    if auswahl == 1:
        filename, password = get_filename_and_password()
        encrypt_file(filename, password)    
        
    if auswahl == 2:
        filename, password = get_filename_and_password()
        decrypt_file(filename, password)
        
    if auswahl == 3:
        filename, password = get_filename_and_password()
        zip_and_encrypt_folder(filename, password)
        
    if auswahl == 4:
        filename, password = get_filename_and_password()
        decrypt_and_unzip_folder(filename, password)
        
        
if __name__ == '__main__':
    main()
Benutzeravatar
__blackjack__
User
Beiträge: 13103
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Jankie: Wenn der Benutzer keine Zahl eingibt, bricht das Programm mit einer Ausnahme ab. ☹️

Wenn die Eingabe ausserhalb von 1 bis 4 liegt, macht das Programm einfach gar nichts.

Die ``if``\s im Hauptprogramm schliessen sich alle gegenseitig aus, also wäre das ein Fall für ``elif``\s, damit nicht unnötig getestet wird.

*Alle* Zweige fragen den Benutzer als erstes nach Dateiname und Passwort – den Aufruf dieser Funktion kann man also *einmal* *vor* die Zweige schreiben, und muss das nicht in jedem wiederholen.

Wenn man das heraus zieht, unterscheiden sich die Zweige nur noch dadurch welche Funktion aufgerufen wird. Da kann man die ``if``/``elif`` durch eine Liste mit Funktionen ersetzen aus der aufgrund von `auswahl` die passende ausgewählt wird:

Code: Alles auswählen

    if 1 <= auswahl <= 4:
        filename = input('Name der Datei: ')
        password = getpass.getpass('Passwort: ')
        functions = [
            encrypt_file,
            decrypt_file,
            zip_and_encrypt_folder,
            decrypt_and_unzip_folder,
        ]
        functions[auswahl - 1](filename, password)
    else:
        print('Ungültige Eingabe!')
Die Behandlung von `OSError` ist durch die Bank schlecht bis falsch. Die Ausgabe “Datei nicht gefunden” sagt nicht *welche* Datei nicht gefunden werden konnte, zudem kann die Ausnahme auch auftreten wenn die Datei zwar da ist, aber man beispielsweise nicht genügend Rechte auf die Datei oder den Ordner in dem sie liegt besitzt für das was man gerade machen will.

Die -4 bei ``filename[:-4]`` ist ein bisschen magisch. Was man hier eigentlich tun möchte ist mit `os.path.splitext()` die Dateinamensendung abtrennen – egal wie lang die ist, und auch nur wenn sie überhaupt existiert.

'.aes' würde ich auch am Anfang als Konstante definieren. Das kommt ja mehrmals im Quelltext vor.

Die Behandlung von `FileNotFoundError` ist an der Stelle sinnlos, denn das ist eine Unterklasse von `OSError`. Der Code kann also niemals erreicht werden. Da in beiden Zweigen der gleiche Code steht, kann man den toten Code einfach löschen.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten