C# Password Hash in SQL + C#

I N X S

Captain
Registriert
Jan. 2007
Beiträge
3.442
Huhu,

möchte ne kleine Loginfunktion implementieren und bräuchte dafür das Wissen, wie ich Passwörter verschlüsselt in einer SQL Datenbank ablegen kann und diese dann wieder mit dem Programmcode entschlüsseln kann.

Leider hat mir die Google Suche nichts gebracht, wär nett, wenn jemand nen SNippet oder nen Tut hätte.

Grüße
 
Um was geht es dir jetzt? Das speichern in der Datenbank oder das verschlüsseln des Passworts oder sogar beides? Für das Verschlüsseln spuckt Google eine Menge aus.
 
Nur als Randinfo: Bitte nicht SHA1 und MD5 nutzen, die sind mittlerweile unsicher und leider noch viel zu sehr verbreitet.
 
Entschlüsseln ist da die falsche Methode. Du musst die 2 Hashes vergleichen.


Account anlegen: Passwort->Hash->DB
Account login: Passwort->Hash->Vergleich mit DB

Ein Salt ist eine Zeichenfolge, die dir dann noch einmal erhöhte Sicherheit gewährt. Da gibt es auch mehrere Ansätze.
 
Ich habe das bisher immer so gelöst, dass ich einen MD5-Hash des Passworts gespeichert habe, und dann beim Einloggen den MD5 des Passwort-Textfelds berechnet und mit dem Wert in der DB verglichen habe.

Ist leider VB-Code, aber sollte ja kein Problem darstellen:
Code:
Dim theMD5Provider As New MD5CryptoServiceProvider
Dim theUTF8Encoder As New UTF8Encoding
Dim thePasswordByteCode() As Byte = theMD5Provider.ComputeHash( _
    theUTF8Encoder.GetBytes(<Passwort im Klartext>) _
)

Dim thePasswordCode As String = ""
For i As Integer = 0 To 15
    Dim eachHex As String = Hex(thePasswordByteCode(i)).ToLower
    If eachHex.Length = 1 Then
        eachHex = "0" + eachHex
    End If
    thePasswordCode = thePasswordCode + eachHex
Next
Das ganze ist natürlich nicht optimal, vor allem wenn Du das in einer Webanwendung benutzt, sollte das Passwort nicht unverschlüsselt übermittelt werden und solche Dinge, aber vielleicht hilft das ja.

Edit: und wie schon von anderen angemerkt, ist MD5 etwas in die Jahre gekommen. Wobei ich denke, das ganze stellt nur ein Problem dar, wenn unbefugte auf deine Datenbank kommen, und dort den Hash auslesen können. Und dann hast Du ganz andere Sicherheitsprobleme, als knackbare MD5-Hashes :D
 
Zuletzt bearbeitet:
@captmcneil: Dein Ansatz ist in Ordnung, aber wie erwähnt, bitte kein MD5 oder Sha1. Und einen Salt sollte man auch einbauen. Cepheus77 hat oben ne Klasse gepostet (wenn ich mir die Postzeit anguck, haste den bei deinem Beitrag wohl noch nicht gesehen :-))
 
Huhu,

ist nur ne alternative für user die nicht in userem Active Directory sind. die können sich nen neuen account erstellen um nen "Bericht" abzuschicken.

das mit den Hash werten vergleichen ist ne gute idee, ich denke ich muss noch nicht so auf sicherheit achten erstmal. Ich möchte erstmal verstehen, wie das ganze funktioniert ;)

ich werd das mal mit dem vergleichen der hashes probieren und euch rückmeldung geben.
 
@captmcneil: Dein Ansatz ist in Ordnung, aber wie erwähnt, bitte kein MD5 oder Sha1. Und einen Salt sollte man auch einbauen. Cepheus77 hat oben ne Klasse gepostet (wenn ich mir die Postzeit anguck, haste den bei deinem Beitrag wohl noch nicht gesehen :-))

100%ige Sicherheit gibts nich und wirds nie geben, jede Verschlüsselung ist "knackbar". Wenn dir MD5 und SHA zu unsicher sind, schlag ihm doch eine in deinen Augen sichere Verschlüsselung vor...

/Edit: Da die Übertragung des Passworts bisher sowieso im Klartext erfolgt, wäre hier erstmal mit Sicherheit anzusetzen und nicht am Server (sprich SSL).
 
Zuletzt bearbeitet:
haze4real schrieb:
Wenn dir MD5 und SHA zu unsicher sind, schlag ihm doch eine in deinen Augen sichere Verschlüsselung vor...

Damit hat er auch absolut Recht. Einfach nicht Sha1 oder MD5 benutzen. Es gibt durchaus andere Sha Algorythmen, Edit: AES bezog sich nicht auf die Hashes. Ich meinte damit den Datenstrom :) (Etwas verkorkster Satz, gebe ich ja zu)

Eine SSL Verbindung zum Server ist leicht aufgebaut.

Die Methoden und Objekte sind alle im .NET Framework enthalten.
 
Zuletzt bearbeitet:
Ob er Recht hat oder nicht ist meiner Meinung nach irrelevant, sobald jemand unbefugten Zugriff auf den Server hat ist es mit der Sicherheit vorbei. Da muss man noch nichtmal irgendwelche Passwörter von Benutzern entschlüsseln...

Es gibt 2 Dinge die abzusichern sind 1. der Server 2. die Übertragung, wie die Passwörter gespeichert werden ist im Endeffekt nicht so relevant eine einfache Verschlüsselung ist ausreichend.

/edit: bzgl. AES: wo speicherst du den Schlüssel? in der Datenbank? Hartkodiert? in diesem Fall wäre es noch unsicherer als jede Hashfunktion. AES kann man zur Absicherung der Übertragung benutzten mit temporären Schlüsseln die via RSA getauscht werden...
 
Zuletzt bearbeitet:
Ich habe nie von einem unerlaubten Zugriff auf den Server gesprochen. Ich habe das Thema rund um die Hashes aufgegriffen. Den Rest hast du dir aus den Fingern gesogen :)

Thema AES: Das kommt auf die Implementierung an. USB Dongle für die einzelnen User z.B.
Das ist ja auch Nebensache und ist auch nicht erwünscht, wie ich das so lese. :)
 
Zuletzt bearbeitet:
Schön, dass das hier zu ner Grundsatzdiskussion geworden ist :D
ich benutz erstmal MD5, vllt wernd ich später auf AES oder so umsteigen.

Aber mal ne andere Frage: Da ich ja register und login alles selbst schreibe, wie fragt ihr die states ab?
ne neue klasse "LoginState" die public static variablen haben, die speichert, ob der user eingeloggt ist mit namen und email?

ich hab nämlich 4 verschiedene arten. Active Directory Gruppenzugehörigkeit User und Admin. Wenn keines von beiden, dann ist man Unregistred und man hat dann erst die möglichkeit sich einzuloggen bzw. nen neuen account zu erstellen.
 
Ne der Grundsatzdiskussion wollte ich aus dem Weg gehen.

Du kannst einfach eine Enum benutzen, die deine verschiedenen States enthält, wenn du diese in der Login Session speichern möchtest, klar. Eine eigene Klasse würde ich dafür jetzt nicht schreiben, es sei denn du brauchst noch Funktionalität dahinter.
 
Tut mir leid wenn ich deinen Thread nochmal missbrauche.

Ich habe nie von einem unerlaubten Zugriff auf den Server gesprochen. Ich habe das Thema rund um die Hashes aufgegriffen. Den Rest hast du dir aus den Fingern gesogen
Kann schon sein das du nicht von unerlaubten Zugriff auf den Server gesprochen hast, aber was bringt dir die sicherste Verschlüsselung der Welt wenn jemand unbefugten Zugriff auf den Server hat? Was bringt dir das sicherste Schloss in deiner Haustüre, wenn du ein riesiges Loch in der Wand hast?

Thema AES: Das kommt auf die Implementierung an. USB Dongle für die einzelnen User z.B.
Es macht nicht wirklich einen Unterschied ob du das Passwort/den Schlüssel manuell eingibst oder hierfür einen Dongle verwendest, das Passwort/der Schlüssel muss auf beiden Seiten der Verschlüsselung bekannt sein.

Ne der Grundsatzdiskussion wollte ich aus dem Weg gehen.
Dann solltest du davon Abstand nehmen von sicher/unsicher zu reden, man kann eben nicht von Gebäudesicherheit sprechen ohne das Loch in der Wand zu beachten.

MD5 ist für den Zweck vollkommen ausreichend.

/edit: hier nochmal die Erstellung eines Hashes in C#:
Code:
			MD5 md5 = new MD5CryptoServiceProvider();
			byte[] hash = md5.ComputeHash(Encoding.Unicode.GetBytes("passwort"));
			string b64hash = Convert.ToBase64String(hash); // optional kannst den Hash auch als byte[] in die Datenbank speichern...

Noch eine wichtige Anmerkung, auf keinen Fall ein Encoding verwenden z.B. Encoding.Unicode.GetString() um aus einem byte[] einen String zu "machen", ausser es handelt sich bei dem byte[] um einen in dieser Kodierung kodierten String, was im Falle der Hashfunktionen nicht der Fall ist! Base64 ist die gebräuchliche Variante um ein byte[] in einem String auszugeben oder eben als Hex-String kodiert wie es captmcneil vorgeschlagen hat.
 
Zuletzt bearbeitet:
Oh je, hier werden einige Dinge verwechselt. AES ist ein Verschlüsselungsverfahren, MD5 und Co sind Hashverfahren. Mag zwar ähnlich aussehen, sind aber zwei verschiedene Dinge.

Bei Verschlüsselungsverfahren unterscheidet man zwischen asymmetrischen und symmetrischen Kryptosystemen. AES wäre der erste Fall, sprich man hat einen Schlüssel mit dem man ver- und entschlüsseln kann. Kannste mit deiner Haustür vergleichen. Der zweite Fall ist zum Beispiel RSA. Dort hat man einen private und einen public key. Mit deinem public key kann jeder Nachrichten verschlüsseln, die an dich sind. Und nur du kannst sie mit deinem private key wieder entschlüsseln.
So, aber nun muss beachtet werden, dass ein Verschlüsselungsverfahren Nachrichten (einfach betrachtet) nur umwandelt und man dort die Nachricht auch wieder (mit passendem Schlüssel) zurückwandeln kann. Bei einem Hashverfahren ist dies nicht so (auch wenn man durchaus wieder den Klartext erhalten kann, dazu gleich mehr).

Ein Hashverfahren nimmt also eine Nachricht und wandelt diese immer nach dem selben Schema auf einen gleichlangen Hashwert ab. Dadurch kommt es irgendwann auch zu Kollisionen und es kann passieren, dass Nachricht A den selben Hash wie Nachricht B bekommt (du hast schließlich unendlich viele Nachrichten, aber nur einen begrenzten Hashwertraum). Würdest du also einen Hashwert knacken, bekommste irgendwann ne Nachricht raus, von der du aber nicht ausgehen kannst, dass es auch die gewünschte Nachricht war. Es könnte ja auch Nachricht C entstehen, die zwar den gleichen Hashwert hat, aber nicht die ursprüngliche Nachricht war.

So und zur Sicherheit von Hashwerten. md5 und sha1 sind unsicher. Wird dir jeder, der etwas Ahnung davon hat, bestätigen. Dies liegt einmal daran, dass es bereits riesige md5 und sha1 Datenbanken gibt - sowie extrem große Rainbowtables, und Forscher ziemlich effiziente Verfahren gefunden haben um eine Kollision zu ermitteln, was bei moderneren Hashverfahren nicht der Fall ist (wie schon erwähnt sind die neuere Sha's noch geeignet, ich nutze ganz gern auch mal Whirlpool). Eine Abbildung auf längere Hashwerte mag zwar auf den ersten Blick besser erscheinen, doch können auch Hashverfahren mit weniger Bitlänge durchaus effizienter sein.

Außerdem sollten die Salts noch erwähnt werden und warum man diese benutzen sollte. Ein Salt ist ein (meist) zufälliger String der für jedes Passwort (im besten Fall) anders ist und irgendwo in der Datenbank o.Ä. mit abgelegt ist. Salts sind nämlich nicht dafür da, dass Passwort einfach zu verlängern, sondern um Wörterbuchattacken auszuschließen. Weiterhin erkennt man nicht, ob zwei verschiedene Passwörter identisch sind, denn: PasswortXY+SaltA != PasswortXY+SaltB

100%ige Sicherheit gibts nich und wirds nie geben, jede Verschlüsselung ist "knackbar".
Hat auch niemand behauptet... man spricht hier auch wenn nur von "mit sehr hoher Wahrscheinlichkeit" etc.

Wenn dir MD5 und SHA zu unsicher sind, schlag ihm doch eine in deinen Augen sichere Verschlüsselung vor...
Hättest du mal den Code oben angeschaut, hättest du gesehen, dass dort weitere Sha Verfahren mit drin sind. Wären die auch so extrem unsicher wie MD5 und SHA1, dann hät ich es erwähnt. Aber okay, gute Verfahren sind momentan noch (Sha256), Sha512 und Whirlpool.

Und ja, SSL ist natürlich von Vorteil, stand hier aber erstmal nicht zur Debatte. Bei md5 kannste das Passwort auch gleich als Plaintext speichern.

@I N X S: Mag zwar sein, dass Sicherheit aktuell noch nicht so die große Rolle spielt, aber da es nicht allzu viel Aufwand ist, kannst du die Passwörter schon vernünftig ablegen.

(Hoffe die Sache ist nun etwas klarer).
 
Ich würde Hier reinschauen!
Je nach dem was du brauchst... Symmetrisch oder Asymmetrisch!
 
@S3PSiS: Hast schon recht, wenn er Hashfunktionen benutzt sollte er gleich den "sichersten" Hashalgorithmus verwenden unter dem Aspekt das es in .NET kaum einen Unterschied macht welchen man verwendet (insofern dieser im .NET Framework implementiert ist) und eine Umstellung des Algorithmuses nicht ohne weiteres möglich ist (bzw. ohne Benutzereinwirkung). Muss auch zugeben das ich es etwas missverstanden habe im Bezug auf Hash vs. Verschlüsselung
 
Zuletzt bearbeitet:
@haze4real: Hm, versteh ich gerade nicht so was du meinst. NET ist ja in dem Fall nur die Programmiersprache, was mit dem Hashverfahren wenig gemein hat. Die Algorithmen zu den Verfahren sind ja festgelegt und werden nur an die Sprachen angepasst, wodurch ein NET Hash XY der selbe Hash XY bei C, Java, wie-auch-immer gibt.
Vielleicht hab ich dich auch nur falsch verstanden. :-)
 
Zurück
Oben