I'm currently writing my own little password manager
Questo è il tuo primo errore. Qualcosa di questo complesso ha molte insidie che a volte anche gli esperti cadono, senza molta esperienza in quest'area non hai la possibilità di fare qualcosa di simile alla sicurezza.
stores the key in an SHA256 hash
Uh oh ...
Questo non significa necessariamente che stai facendo qualcosa di sbagliato, ma nutro forti dubbi sul fatto che tu stia andando bene. Immagino tu stia parlando di una password principale che viene sottoposta a hashing qui? La password principale deve essere trasformata in una chiave utilizzando una KDF come PBKDF2, bcrypt o Argon2, quindi questa chiave viene utilizzata per crittografare le password memorizzate.
Se vuoi avere un modo per verificare che la password sia corretta, la memorizzazione di un hash della chiave dovrebbe andare bene, ma NON DEVE memorizzare la chiave stessa ... se si memorizza il chiave chiunque abbia accesso al tuo spazio di archiviazione ha tutto ciò di cui hanno bisogno per decifrare tutte le password!
Se non stai parlando di hashing di una password principale e intendi una vera chiave generata casualmente allora non ho idea di cosa stai provando a realizzare qui, ma non dovresti usare un KDF lento con un grande numero di iterazioni.
In alternativa è possibile eseguire il hashing della password master due volte, una volta per memorizzare come hash per verificare successivamente che la password inserita dall'utente sia corretta e utilizzarla nuovamente come chiave per la crittografia. A seconda di come è fatto, potrebbe andare da un difetto di progettazione a dare via completamente la chiave.
Modifica: dopo aver visto il codice completo sembra essere una quarta opzione: memorizzi un hash della password per verificare in seguito se la password inserita è corretta, quindi hai hash questo hash da usare come la chiave, che è quasi pessima quanto memorizzare la chiave stessa.
I create the hash by doing the following:
def sha256_rounds(raw, rounds=100001):
obj = hashlib.sha256()
for _ in xrange(rounds):
obj.update(raw)
raw = obj.digest()
return obj.digest()
Non è chiaro quale sia raw
qui, ma suppongo che sia la password. Quello che stai facendo è un hash non salato usando SHA256. Non provare a creare il tuo KDF!
After it is created it is stored with the following:
key = base64.urlsafe_b64encode(provided_key)
length = len(key)
with open(key_file, "a+") as key_:
front_salt, back_salt = os.urandom(16), os.urandom(16)
key_.write("{}{}{}:{}".format(front_salt, key, back_salt, length))
Quindi, stai creando la chiave taggando la password, quindi aggiungendo un salt in modo casuale alla parte anteriore e posteriore? Non solo concatenare 2 diversi sali davanti e dietro non standard, non sta facendo nulla qui perché è fatto dopo che il KDF è già finito! Stai solo aggiungendo alcuni valori casuali per il gusto di averli lì.
Per mostrare quanto sia pessimo (a partire dal commit 609fdb5ce976c7e5aa1832670505da60012b73bc), tutto ciò che serve per scaricare tutte le password memorizzate senza che richiedono una password principale è questa:
from encryption.aes_encryption import AESCipher
from lib.settings import store_key, MAIN_DIR, DATABASE_FILE, display_formatted_list_output
from sql.sql import create_connection, select_all_data
conn, cursor = create_connection(DATABASE_FILE)
display_formatted_list_output(select_all_data(cursor, "encrypted_data"), store_key(MAIN_DIR))
Anche se può essere una buona esperienza di apprendimento provare a creare un gestore di password, per favore per favore non usarlo mai per qualcosa da remoto importante. Come suggerisce @Xenos, non sembra che tu abbia abbastanza esperienza che la creazione di un proprio gestore di password sarebbe davvero utile in ogni caso, sarebbe probabilmente una migliore opportunità di apprendimento per dare un'occhiata a un gestore di password open source esistente.