PDA

View Full Version : [C#] Approccio per criptare password


rizzotti91
14-12-2012, 12:21
Salve, ho l'esigenza di creare un form di login con due login:
1) Accesso con username e password al database, se questo va a buon fine, verrà visualizzato il secondo login;
2) Accesso al programma tramite una password definita dall'utente stesso dall'interno del programma.

Le domande che ho da farvi sono:
- Va bene utilizzare un file TXT criptato per la password o in ogni caso è meglio usare un file di tipo BINARY?
- Suppongo che per criptare la password devo "semplicemente" criptare il textbox/variabile, salvare su file e quando faccio il login devo criptare il testo inserito per confrontarlo con quello contenuto nel file (o è meglio de-criptare quello del file e confrontarlo con quello inserito dall'utente?).

Mi sapete consigliare qualche link o direttamente parti di codice in cui posso vedere come effettuare la crittografia di una determinata variabile?
Grazie :)

Braccop
14-12-2012, 15:52
http://msdn.microsoft.com/it-it/library/system.web.security.formsauthentication.hashpasswordforstoringinconfigfile.aspx

dovrebbe fare al caso tuo. ovviamente parliamo di hashing e non di encryption reversibile, che e' la prassi comune per le password.

demos88
14-12-2012, 16:08
Di norma, solo l'utente conosce la password in chiaro, e nessun altro (benchè meno il server, che se te lo hackerano sei morto, ovviamente mi riferisco a realtà aziendali grosse).
Sul server (in un file, o in database solitamente) è memorizzato l'hash della password. Fino a qualche tempo fa era scontato l'uso dell'md5, ora in molti casi si usa anche lo SHA-1 e SHA-2.
Quale algoritmo di hashing usi non cambia comunque la logica:
- l'utente è il solo a conoscere la password
- il form riceve la password in chiaro e ne calcola subito l'hash
- l'hash calcolato viene confrontato con l'hash memorizzato
- se gli hash coincidono, permetti l'accesso, altrimenti no.

Una delle peculiarità di un buon hash, è l'estrema difficoltà di ricavare la password a partire dall'hash, per cui l'hash non è necessario criptarlo a sua volta, perchè di per se è considerabile come un codice già criptato.
Quindi riguardo la tua ultima domanda: no, non è pensabile descriptare l'hash, fai solo il confronto tra l'hash calcolato dai dati inseriti dall'utente e l'hash memorizzato.
In C# per lo sha-2:

using(SHA256 shaM = new SHA256Managed()) {
result = shaM.ComputeHash(data);
}
Qui la descrizione della classe: http://msdn.microsoft.com/en-us/library/system.security.cryptography.sha256.aspx

rizzotti91
14-12-2012, 16:19
Grazie mille ad entrambi per le risposte.
Dopo aver letto la prima mi ero messo a cercare e guarda caso ho creato del codice che sfrutta l'SHA256 che è quello da te consigliatomi, quindi tanto meglio, grazie ancora :D

rizzotti91
14-12-2012, 16:38
Mi sono venute in mente due domandine, di cui una forse è un pochino OT ma non credo valga la pena aprire un nuovo topic perché è semplice :)

- La password "hashata" la memorizzo in un normale campo varchar? Se si che dimensione massima devo mettere? L'SHA256 ha una lunghezza sempre uguale indipendentemente dalla password che inserisco?

- Nel campo varchar di Mysql fa differenza se metto come dimensione 30 o 50? Perchè mi sembra di aver letto che è un'allocazione dinamica in base a quanti caratteri si mandano..

tomminno
14-12-2012, 16:55
Di norma, solo l'utente conosce la password in chiaro, e nessun altro (benchè meno il server, che se te lo hackerano sei morto, ovviamente mi riferisco a realtà aziendali grosse).

Prova a dover fare un SSO e poi ne riparliamo della password in hash :D

rizzotti91
14-12-2012, 16:57
Prova a dover fare un SSO e poi ne riparliamo della password in hash :D

Spiegheresti in poche parole a me che sono incompetente? :D

Braccop
14-12-2012, 17:01
Mi sono venute in mente due domandine, di cui una forse è un pochino OT ma non credo valga la pena aprire un nuovo topic perché è semplice :)

- La password "hashata" la memorizzo in un normale campo varchar? Se si che dimensione massima devo mettere? L'SHA256 ha una lunghezza sempre uguale indipendentemente dalla password che inserisco?

- Nel campo varchar di Mysql fa differenza se metto come dimensione 30 o 50? Perchè mi sembra di aver letto che è un'allocazione dinamica in base a quanti caratteri si mandano..

1)si, la dimensione dell'hash e' fissa, dipende pero' dall'encoding in cui viene salvata (es: hex o base64)

2)no non cambia niente tra 30 e 50, solo che se provi a inserire nel campo da 30 una lunghezza superiore va in errore

rizzotti91
14-12-2012, 17:09
1)si, la dimensione dell'hash e' fissa, dipende pero' dall'encoding in cui viene salvata (es: hex o base64)

2)no non cambia niente tra 30 e 50, solo che se provi a inserire nel campo da 30 una lunghezza superiore va in errore

Grazie :)

1) Io uso questa classe:
public string ComputeHash(string input, HashAlgorithm algorithm)
{
Byte[] inputBytes = Encoding.UTF8.GetBytes(input);

Byte[] hashedBytes = algorithm.ComputeHash(inputBytes);

return BitConverter.ToString(hashedBytes);
}
Quindi di che dimensione deve essere il campo?

2) Quindi mi confermi che a livello di utilizzo memoria non cambia nulla?

Grazie ancora :)

tomminno
14-12-2012, 18:27
Spiegheresti in poche parole a me che sono incompetente? :D

SSO sta per single sign on e si usa in ambito enterprise per far accedere l'utente a sistemi eterogenei con una sola login. Dato però che i vari sistemi da integrare richiedono la password in chiaro per autenticare non puoi memorizzarla come hash altrimenti tutto il meccanismo non funziona.
Era solo per portare un esempio di come anche in ambito enterprise le password si tengano cifrate e non solo in hash.

rizzotti91
14-12-2012, 18:31
Ok grazie.
Se io invece avessi in mente di creare una tabella di utenti e password in un database ed in base a delle scelte che effettua l'amministratore vengano nascoste funzioni,pulsanti,form,textbox etc. a dei determinati utenti, l'approccio dell'SHA256 è ancora valido?

Nel caso in cui volessi fare una cosa del genere per gestire questi "permessi" interni al programma in modo da oscurare intere parti a determinati utenti avete consigli sul come farlo?

PS un'ultima cosa riguardo l'SHA256: ho visto che alcuni aggiungono anche i salt, cosa sono? E' consigliato metterli?

Braccop
14-12-2012, 19:20
il salt e' un' aggiunta che viene fatta alla password per rendere + difficile a un eventuale cracker decifrarla

per esempio prima di salvarti la password hashata la concateni con un'altra stringa a tuo piacimento.

ultimamente ho letto di chi consiglia di salvare il salt (dato che ti servira' ogni volta per ricalcolare l'hash da verificare) nel database, diverso per ogni singolo utente ma a mio avviso e' inutile dato che se qualcuno dovesse riuscire ad entrare in possesso dell'hash avrebbe accesso anche al salt.

personalmente quindi uso un salt "hardcoded" nel codice, possibilmente dichiarato in un unico punto, per comodita' e pulizia

tomminno
14-12-2012, 19:25
Ok grazie.
Se io invece avessi in mente di creare una tabella di utenti e password in un database ed in base a delle scelte che effettua l'amministratore vengano nascoste funzioni,pulsanti,form,textbox etc. a dei determinati utenti, l'approccio dell'SHA256 è ancora valido?

Nel caso in cui volessi fare una cosa del genere per gestire questi "permessi" interni al programma in modo da oscurare intere parti a determinati utenti avete consigli sul come farlo?

PS un'ultima cosa riguardo l'SHA256: ho visto che alcuni aggiungono anche i salt, cosa sono? E' consigliato metterli?

Quello di cui hai bisogno è di definire dei ruoli per gli utenti in modo da personalizzare le funzionalità. Come conservi le password non ha niente a che vedere con questo.
A quanto pare però ti servirebbe un db più che un file di testo.
Il salt (valore random aggiunto alla stringa da cifrare) non è applicabile nel caso delle password con hash, ma si usa quando si cifrano in modo che 2 password uguali non siano memorizzate con lo stesso valore. Nel caso degli hash non ha molto senso in quanto non potresti ricostruire la stringa da confrontare, a meno di non usare un salt costante che non serve a niente.

rizzotti91
14-12-2012, 20:05
Ok grazie ad entrambi.
Per verificare se esiste l'utente "giovannino" nel database (non il record nella tabella, ma l'utente vero e proprio), devo semplicemente provare a fare una query su un DB e vedere se mi fa connettere o meno oppure c'è qualche altro modo più "elegante"? Grazie :)

demos88
15-12-2012, 08:48
Prova a dover fare un SSO e poi ne riparliamo Vabbè ne passa tra l'autenticare il login a un sito/forum e un SSO, non ci ho manco pensato :asd:
Penserei comunque che nei SSO la password venga criptata ma mantenuta solo per un limitato periodo di tempo, se non addirittura tenuta solo in sessione o tenuta come cookie a scadenza breve (mi pare che le linee guida oracle suggeriscano una cosa del genere)
Ok grazie ad entrambi.
Per verificare se esiste l'utente "giovannino" nel database (non il record nella tabella, ma l'utente vero e proprio), devo semplicemente provare a fare una query su un DB e vedere se mi fa connettere o meno oppure c'è qualche altro modo più "elegante"? Grazie :)
Quando al login fai il select per estrarre i dati dell'utente, vedi subito se la query ti ritorna una o zero righe. Nel secondo caso l'utente non esiste.

rizzotti91
15-12-2012, 11:31
Non mi sono fatto capire :D
Non intendo verificare se esiste la riga corrispondente... mi riferisco proprio all'utente del Database, per esempio il root... se oltre a root mi creo altri utenti, come verifico se esistono in MySQL? Semplicemente vedendo quante righe mi restituisce?

demos88
15-12-2012, 13:40
Non mi sono fatto capire :D
Non intendo verificare se esiste la riga corrispondente... mi riferisco proprio all'utente del Database, per esempio il root... se oltre a root mi creo altri utenti, come verifico se esistono in MySQL? Semplicemente vedendo quante righe mi restituisce?
edit: ah ho capito ora...
Se hai già effettuato l'accesso al db (come root o altro utente che ne abbia privilegi), puoi eseguire la query:
SELECT user FROM mysql.user WHERE user='<utente da verificare>';
Se ritorna zero righe, allora l'utente non esiste. Puoi anche non porre condizioni WHERE per visualizzare tutti gli utenti.
Se invece non puoi/vuoi accedere al DB e devi testare l'esistenza dell'utente dall'esterno, allora si, penso che dovrai tentare la connessione e vedere se ha successo o meno.

rizzotti91
22-12-2012, 13:26
Problemino: su Windows XP mi dice che l'algoritmo criptografico usato (SHA256) non è supportato, che fare?

tomminno
22-12-2012, 14:15
Problemino: su Windows XP mi dice che l'algoritmo criptografico usato (SHA256) non è supportato, che fare?

Devi usare SHA256Managed. Le classi CryptoServiceProvider utilizzano il sistema di cifratura dell'os e xp non supporta sha256

rizzotti91
22-12-2012, 14:40
Devi usare SHA256Managed. Le classi CryptoServiceProvider utilizzano il sistema di cifratura dell'os e xp non supporta sha256

Grazie mille per la risposta, ho provato e funziona :D

Quindi ho pensato di passare direttamente all'SHA512 :D

rizzotti91
23-12-2012, 01:37
Ragazzi ho visto la classe Bcrypt che dovrebbe essere migliore dell'SHA512, confermate?
Ho una domanda: sto memorizzando la password concatenando alla fine della stessa una mia parola personale e mettendo come parametro nel generate salt, il numero 12. Ovviamente più il numero aumenta più il tempo per generarla cresce.
Bene, siccome raramente nel programma che sto facendo dovrò generare password, il numero di salt che specifico in fase di inserimento peggiorano anche il tempo di decifrazione della stessa in fase di login?
Grazie.

Braccop
23-12-2012, 10:48
imho non accanirti + di tanto sul lato hashing delle password... sha256 o 512 + un salt e' piu' che sufficiente, anche perche' tieni conto che se la webapp e' realizzata bene nessuno verra' mai in possesso del database...

piuttosto concentrati sulle tecniche per proteggerti da sql injection (query parametrizzate) e xss scripting

rizzotti91
23-12-2012, 12:11
imho non accanirti + di tanto sul lato hashing delle password... sha256 o 512 + un salt e' piu' che sufficiente, anche perche' tieni conto che se la webapp e' realizzata bene nessuno verra' mai in possesso del database...

piuttosto concentrati sulle tecniche per proteggerti da sql injection (query parametrizzate) e xss scripting

L'applicazione non è una webapp, ma funziona in locale..

rizzotti91
19-03-2013, 04:20
Scusate se uppo la discussione ma trattandosi sempre di crittografia e di c# non credo sia necessario aprirne una nuova :)

Ho la necessita di trasferire dei file che cripto con AES e mi chiedevo se all'atto pratico ci sia differenza nell'usare una password del tipo: "1234123464138" oppure una "AZ_234.-[]{"
Ovviamente sono semplicemente esempi, ma mi interesserebbe capire se a livello di sicurezza cambia qualcosa :)

banryu79
19-03-2013, 10:44
Scusate se uppo la discussione ma trattandosi sempre di crittografia e di c# non credo sia necessario aprirne una nuova :)

Ho la necessita di trasferire dei file che cripto con AES e mi chiedevo se all'atto pratico ci sia differenza nell'usare una password del tipo: "1234123464138" oppure una "AZ_234.-[]{"
Ovviamente sono semplicemente esempi, ma mi interesserebbe capire se a livello di sicurezza cambia qualcosa :)
Non sono la persona più adatta a risponderti, poichè non sono un esperto di sicurezza, però provo lo stesso a fornirti qualche indicazione (spero utile) che mi deriva dalla mia esperieza come utente di un software [KeePass] per la gestione personale delle password (ho un sacco di account online e non voglio ne impazzire a inventrami nuove password ogni volta ne usare delle stringhe banali facili da tenere a mente).

Questo software ha un Password Generator in cui l'utente può definire la lunghezza della password e i set di caratteri da utilizzare per generarla; può poi chiedere al generatore una sorta di "preview" per vedere che tipo di password saltano fuori.

Ogni password riporta una metrica della sua "qualità" in termini di numero di bit (più è alto più sicura è la password).

Ho fatto una prova con due generatori; entrambi per password lunghe 16 caratteri, il primo col solo set delle cifre (0,1,2...) il secondo più articolato, con: tutti gli alfanumerici (0,1,2...a,b,c,...A,B,C...) il carattere meno (-), l'underline (_) le parentesi "[,]{,},(,)" e il punto (.)

Il risultato?
Che le password partorite dal primo generatore viaggiavano sui 31-37 bit mentre quelle del secondo generatore sugli 83-95 bit.
Quindi più è ricco l'alfabeto, più le password generate sono, in media, più "robuste".



Qualche link (credo) utile a 360° sulll'argomento:
- http://psychology.wichita.edu/surl/usabilitynews/81/Passwords.asp
- http://stackoverflow.com/questions/55556/password-generation-best-practice
- http://www.schneier.com/blog/archives/2007/01/choosing_secure.html


@EDIT: Forse era il caso di aprire un nuovo thread, dopotutto questo aspetto è agnostico rispetto al particolare linguaggio di programmazione.

rizzotti91
19-03-2013, 14:18
Ti ringrazio per la risposta molto esaustiva :)

C'è un limite per la lunghezza della stringa passata come password usando la crittografia con EAS con il C# e la classe Criptography?

banryu79
20-03-2013, 08:18
Ti ringrazio per la risposta molto esaustiva :)
Oddio, molto esaustiva... Più che altro molto prolissa :D


C'è un limite per la lunghezza della stringa passata come password usando la crittografia con EAS con il C# e la classe Criptography?
E qui mi ritiro con disonore: non ne ho idea.
Però se ci fosse per questioni di implementazione, probabilmente la cosa sarebbe documentata: in attesa di una risposta io andrei a spulciare la documentazione.