Cercare di memorizzare nomi utente e password in un database e mi chiedo quale sia il modo più sicuro per farlo. So che devo usare un sale da qualche parte, ma non sono sicuro di come generarlo in modo sicuro o come applicarlo per crittografare la password. Alcuni esempi di codice Python sarebbero molto apprezzati. Grazie.Il metodo più sicuro di Python per archiviare e recuperare password da un database
risposta
Memorizzare la password + sale come hash e sale. Dai un'occhiata a come Django lo fa: basic docs e source. Nel db memorizzano <type of hash>$<salt>$<hash>
in un singolo campo char. È inoltre possibile memorizzare le tre parti in campi separati.
La funzione per impostare la password:
def set_password(self, raw_password):
import random
algo = 'sha1'
salt = get_hexdigest(algo, str(random.random()), str(random.random()))[:5]
hsh = get_hexdigest(algo, salt, raw_password)
self.password = '%s$%s$%s' % (algo, salt, hsh)
Il get_hexdigest è solo un wrapper sottile attorno ad alcuni algoritmi di hashing. Puoi usare hashlib per questo. Qualcosa di simile hashlib.sha1('%s%s' % (salt, hash)).hexdigest()
E la funzione di verificare la password:
def check_password(raw_password, enc_password):
"""
Returns a boolean of whether the raw_password was correct. Handles
encryption formats behind the scenes.
"""
algo, salt, hsh = enc_password.split('$')
return hsh == get_hexdigest(algo, salt, raw_password)
Hai un collegamento al file di codice appropriato? –
Questo è stato davvero utile. Grazie mille. – ensnare
@justin ethier: ci sei. @ensnare: sentiti libero di contrassegnarlo come accettato ;-) –
penso che sia meglio usare un pacchetto dedicato a hashing delle password per questo passlib come: http://packages.python.org/passlib/ per ragioni I spiegato qui: https://stackoverflow.com/a/10948614/893857
Grazie! passlib: veloce e facile.:-) – dlink
Ecco un modo più semplice (tratto da effbot), fornito le password con una lunghezza superiore a 8 non sarà un problema *:
import crypt
import random, string
def getsalt(chars = string.letters + string.digits):
# generate a random 2-character 'salt'
return random.choice(chars) + random.choice(chars)
per generare il Password:
crypt.crypt("password", getsalt())
*: Una password con una lunghezza superiore a 8 è spogliato da destra verso il basso per 8 caratteri lunghi
cripta hanno problemi a crittografare la password di più di 8 caratteri Penso che – llazzaro
ho risposto questa qui: https://stackoverflow.com/a/18488878/1661689, e così ha fatto @Koffie.
Non so come sottolineare abbastanza che la risposta accettata NON è sicura. È meglio del semplice testo e migliore di un hash non salato, ma è comunque estremamente vulnerabile allo al dizionario e persino agli attacchi di forza bruta. Invece, si prega di utilizzare un KDF SLOW come bcrypt (o almeno PBKDF2 con 10.000 iterazioni)
Stai suggerendo che la memorizzazione di password correttamente salate e hash è una ** pratica estremamente vulnerabile **? Non è possibile utilizzare un attacco di dizionario su hash salati. – vroomfondel
No. Sto suggerendo che una singola iterazione di SHA-1, come suggerisce il codice sopra, non è "correttamente salata e hash". Puoi * usare * un attacco di dizionario sugli hash salati, e più velocemente l'hash, più velocemente ogni pw può essere provato. Preferiresti che ci sia voluto un giorno o 64.000 giorni perché l'attacco avesse successo? L'hashing SHA-x è * molto * veloce sull'hardware personalizzato (ASIC). https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet#Impose_infeasible_verification_on_attacker http://stackoverflow.com/questions/13545677/python-passlib-what-is-the-best-value-forrounds –
@rz dice "guarda come fa Django" e poi mostra il codice che è completamente diverso. Django * lo fa correttamente: https://github.com/django/django/blob/master/django/contrib/auth/hashers.py#L216 –
un sacco di informazioni qui: http://stackoverflow.com/questions/1183161/to-sha512-hash-a- password-in-mysql-database-by-python –