2009-06-03 6 views
30

sto utilizzando Mysql e stavo assumendo che era meglio separare un'utenti informazioni personali e la loro login e password in due tabelle diverse e poi semplicemente riferimento tra i due .Come al meglio memorizzare le informazioni utente e utente e password

Nota: Per chiarire il mio post, comprendo le tecniche di protezione della password (hash, sale, ecc.). So solo che se seguo pratiche provenienti da altre parti della mia vita (investimenti, backup dei dati, persino archiviazione personale) che nella peggiore delle ipotesi (compresa tabella o incendio) che avere informazioni divise tra tabelle offre il potenziale per proteggere il tuo dati aggiuntivi.

+0

Giusto per chiarire; vuoi sapere come memorizzare correttamente le password nel database, o semplicemente vuoi sapere se i dati del profilo utente devono essere separati dai dati dell'account di base? Ho risposto per il primo, ma dopo aver riletto la domanda, sembra che tu voglia il secondo. – Rob

+1

La maggior parte delle risposte si concentra sul metodo di hashing e salatura delle password. Questa è una buona informazione, ma non affronta la domanda dell'OP. –

+0

Sì Memorizzerò la password usando sha1 e una salatura. – Tim

risposta

35

Non memorizzare password. Se è mai seduto su un disco, può essere rubato. Invece, memorizza gli hash delle password. Use the right hashing algorithm, come bcrypt (che include un sale).

EDIT: Il PO ha risposto che capisce il problema di cui sopra.

Non c'è alcuna necessità di memorizzare la password in una tabella fisicamente diverso da quello di login. Se una tabella di database viene compromessa, non è un grande salto accedere ad un'altra tabella in quello stesso database.

Se siete sufficientemente preoccupati per la sicurezza e la sicurezza in profondità, si potrebbe considerare la memorizzazione delle credenziali utente in un archivio dati completamente separato dai vostri dati di dominio. Un approccio, comunemente fatto, è quello di memorizzare le credenziali in un server di directory LDAP. Questo potrebbe anche essere d'aiuto con qualsiasi lavoro single-sign-on che svolgerai in seguito.

+1

Hai perfettamente ragione, MD5 non è abbastanza forte. –

+3

+1 per tutto tranne la raccomandazione SHA. SHA e MD5 sono nella stessa, insufficiente classe di algoritmi di hashing - da un punto di vista della sicurezza, entrambi impallidiscono rispetto all'hash adattivo, come citato da Rob sotto. –

+0

In realtà non risponde alla domanda. –

14

Non c'è niente di sbagliato nel metterli nello stesso tavolo. In effetti, sarebbe molto più veloce, quindi lo consiglio vivamente. Non so perché tu voglia dividerlo.

+1

dubito seriamente che sarebbe più veloce, dal momento che il controllo di nome/password e userdata sarebbe su parti molto diverse di qualsiasi applicazione, e fatto in momenti molto diversi. pensa: hai bisogno dei dati validi per ogni rifiuto di accesso? dopo averlo accettato, devi controllare la password ogni volta che leggi il profilo? ovviamente, di solito non mi preoccupo, e metto tutto insieme. ma è solo per semplicità, non per prestazioni. – Javier

+2

No, perché avresti bisogno di fare JOIN ogni volta che ottieni i dati utente. O quello o avresti molte informazioni duplicate (ad esempio, nome utente e ID memorizzati in entrambi, ecc.), Nessuna delle due è ottimale. Ad ogni modo, non c'è motivo di dividerlo in due tavoli diversi; semplicemente non ha alcun senso, sia per le prestazioni che per la semplicità. –

+1

+1 Questa è l'unica risposta (finora) che risponde alla domanda dell'OP. –

0

Dovresti memorizzarli nella stessa tabella, e utilizzare la crittografia a senso unico. MD5 funzionerà, ma è debole, quindi potresti prendere in considerazione qualcosa come SHA1 o un altro metodo. Non c'è alcun vantaggio nel memorizzare i 2 oggetti in tabelle separate.

+1

Non esiste una crittografia unidirezionale; il termine è hashing crittografico. MD5 e SHA1 sono algoritmi di hash veloci e non sono una buona idea per l'hashing della password. Si dovrebbe salare l'hash con un nonce casuale memorizzato nel database. – Rob

+0

http://en.wikipedia.org/wiki/One-way_encryption In effetti, la scelta di utilizzare un termine piuttosto che un altro non è abbastanza importante quanto l'idea veicolata, e molte persone usano il termine "Crittografia unidirezionale" 'e sono capiti comunemente. –

7

Cercherò di rispondere alla tua domanda originale. Avere tutto in una tabella va bene a meno che non si abbiano solo un sacco di informazioni personali da raccogliere. In tal caso potrebbe essere sensato dividerlo. Tale decisione dovrebbe essere presa in base alla quantità di informazioni personali con cui si ha a che fare e alla frequenza con cui è necessario accedervi.

direi che la maggior parte del tempo mi piacerebbe fare qualcosa di simile in una singola tabella:

UserID, FirstName, LastName, Email, Password, TempPassword 

Ma ... se si sta raccogliendo molto di più. Supponiamo che tu stia raccogliendo telefono, fax, data di nascita, biografia, ecc. Ecc. E se la maggior parte di queste informazioni è raramente accessibile, probabilmente la inserirò nella sua tabella e la collegherò con una relazione uno a uno. Dopo tutto, meno colonne hai su un tavolo, più veloce sarà la tua query su quel tavolo. E a volte ha senso semplificare le tabelle a cui si accede maggiormente. C'è un riscontro di prestazioni con il JOIN anche se è necessario accedere a tali informazioni personali, quindi è qualcosa che devi considerare.

EDIT - Sai cosa, ho solo pensato a qualcosa. Se si crea un indice sul nome utente o sul campo di posta elettronica (a seconda di quale si preferisce), eliminerà quasi completamente l'inconveniente di prestazioni nella creazione di così tante colonne in una tabella utente. Dico questo perché ogni volta che accedi alla clausola WHERE sarà estremamente veloce trovare il nome utente se ha un indice e non importa se hai 100 colonne in quella tabella. Quindi ho cambiato la mia opinione. Metterei tutto in un solo tavolo.;)

In entrambi i casi, poiché la sicurezza sembra essere un argomento popolare, la password dovrebbe essere un valore hash. Suggerirei SHA1 (o SHA256 se ne sei veramente preoccupato). TempPassword dovrebbe anche usare un hash ed è solo lì per la funzionalità della password dimenticata. Ovviamente con un hash non è possibile decodificare e inviare all'utente la loro password originale. Quindi, invece, si genera una password temporanea con cui è possibile accedere e quindi si costringe a cambiare nuovamente la password dopo l'accesso.

+0

Non memorizzare la password temporanea. È un buco. –

+0

La password temporanea dovrebbe essere anche un hash SHA1. Come è una buca? –

+0

cosa suggerisci invece? – nickf

3

Innanzitutto, per dichiarare (si spera) ovvio, se è possibile in alcun modo evitare di memorizzare nomi utente e password; è una grande responsabilità e se il tuo negozio di credenziali viene violato potrebbe fornire l'accesso a molti altri luoghi per gli stessi utenti (a causa della condivisione delle password).

Se è necessario archiviare le credenziali:

  • Non conservare una forma reversibile; memorizzare un hash utilizzando un algoritmo riconosciuto come SHA-256. Usa il software di crittografia da una fonte attendibile e affidabile - NON TENTARE DI ROLLARE I TUOI PROPRIETÀ, POTRESTI OTTENERLO SBAGLIATO.
  • Per ogni set di credenziali, memorizzare un salt insieme ai dati hash; questo è usato per "innescare" l'hash in modo tale che due password identiche non producano lo stesso hash - dal momento che dà via che le password sono le stesse.
  • Utilizzare un generatore casuale sicuro. La casualità debole è la causa numero uno degli errori di sicurezza relativi alla crittografia, non degli algoritmi di cifratura.

Se è necessario archiviare reversibili credenziali:

  • scegliere un buon algoritmo di crittografia - AES-256, 3DES (datato), o di un cifrario a chiave pubblica. Usa il software di crittografia da una fonte attendibile e affidabile - NON TENTARE DI ROLLARE I TUOI PROPRIETÀ, POTRESTI OTTENERLO SBAGLIATO.
  • Per ogni set di credenziali, memorizzare un valore salt (non crittografato) insieme ai dati crittografati; questo è usato per "innescare" il codice di crittografia in modo tale che due password identiche non producano lo stesso testo cifrato - dal momento che dà via che le password sono le stesse.
  • Utilizzare un generatore casuale sicuro. La casualità debole è la causa numero uno degli errori di sicurezza relativi alla crittografia, non degli algoritmi di cifratura.
  • Memorizzare le chiavi di crittografia/decrittografia separatamente dal proprio database, in un file protetto O/S, accessibile solo per il profilo runtime delle applicazioni. In questo modo, se il tuo DB viene violato (ad es. Tramite SQL injection) la tua chiave non è automaticamente vulnerabile, poiché ciò richiederebbe l'accesso all'HDD in generale. Se il tuo O/S supporta la crittografia dei file legata a un profilo, usalo - può solo aiutare ed è generalmente trasparente (ad esempio la crittografia NTFS).
  • Se possibile, memorizzare le chiavi stesse crittografate con una password primaria. Questo di solito significa la tua app. avrà bisogno di quella chiave digitata all'avvio - non è utile fornirla in un parametro da uno script poiché se l'HDD viene violato è necessario presumere che sia il file chiave sia lo script possano essere visualizzati.
  • Se il nome utente non è necessario per individuare il record dell'account, crittografare sia il nome utente che la password.
17

Le password devono essere memorizzate come hash crittografico, un'operazione non reversibile che impedisce la lettura del testo normale. Quando si autenticano gli utenti, l'immissione della password viene sottoposta allo stesso processo di hashing e gli hash vengono confrontati.

Evitare l'uso di un hash veloce ed economico come MD5 o SHA1; l'obiettivo è rendere costoso per un utente malintenzionato calcolare le tabelle arcobaleno (in base alle collisioni hash); un hash veloce contrasta questo. L'uso di un costoso hash non è un problema per gli scenari di autenticazione, poiché non avrà alcun effetto su una singola esecuzione dell'hash.

Oltre all'hashing, salare l'hash con un valore generato casualmente; un nonce, che viene quindi memorizzato nel database e concatenato con i dati prima dell'hash. Ciò aumenta il numero di combinazioni possibili che devono essere generate durante il calcolo delle collisioni, e quindi aumenta la complessità complessiva nel tempo della generazione di tabelle arcobaleno.

La colonna dell'hash della password può essere una lunghezza fissa; il tuo hash crittografico dovrebbe produrre valori che possono essere codificati in una lunghezza fissa, che sarà la stessa per tutti gli hash.

Ove possibile, evitare di attivare il proprio meccanismo di autenticazione della password; utilizzare una soluzione esistente, ad esempio bcrypt.

Un'eccellente spiegazione di come gestire le password e di cosa è necessario preoccuparsi è disponibile al numero http://www.matasano.com/log/958/enough-with-the-rainbow-tables-what-you-need-to-know-about-secure-password-schemes.

Come nota finale, si ricorda che se un utente malintenzionato ottiene l'accesso al proprio database, la sua preoccupazione immediata dovrebbe probabilmente riguardare qualsiasi informazione sensibile o di identificazione personale a cui possa avere accesso e qualsiasi danno possa aver fatto.

+2

Il post del blog è stato spostato su http://chargen.matasano.com/chargen/2007/9/7/enough-with-the-rainbow-tables-what- you-need-to-know-about-s.html – jwhitlock

+1

+1 per 'bcrypt' – dave1010

+0

non utilizzare mai bcrypt vedere qui http://bugs.debian.org/700758 – nikoss

2

Nella mia esperienza personale, archiviare le informazioni personali e le informazioni di accesso nei singoli database è la migliore pratica in questo caso. La ragione per cui dovrebbe verificarsi un'iniezione SQL è limitata (a meno che l'infiltrato non conosca il layout interno del/i database/i) alla tabella a cui appartengono i dati, invece di fornire l'accesso all'intero conglomerato di dati.

Tuttavia, si noti che ciò potrebbe comportare la necessità di eseguire più query, quindi un impatto sulle prestazioni.

+2

O si potrebbe essere un programmatore attento e prevenire attacchi di SQL injection in primo luogo. ;) –

+0

Ovviamente = P Naturalmente, per ogni contromisura implementata, esiste comunque un'elusione. Così può anche ridurre le perdite e rendere più difficile ottenere informazioni non correlate. – Jason

2

Tutti questi dati hanno sempre una relazione 1: 1 con l'utente? Se riesci a consentire agli utenti di disporre di più indirizzi, numeri di telefono e così via, potresti voler suddividere le informazioni personali in una tabella separata.