Ich habe gerade einen Artikel von David Hayden über das Hashing von Benutzerkennwörtern durchgesehen .
Ich kann wirklich nicht verstehen, was er erreichen will.
Hier ist sein Code:
private static string CreateSalt(int size)
{
//Generate a cryptographic random number.
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] buff = new byte[size];
rng.GetBytes(buff);
// Return a Base64 string representation of the random number.
return Convert.ToBase64String(buff);
}
private static string CreatePasswordHash(string pwd, string salt)
{
string saltAndPwd = String.Concat(pwd, salt);
string hashedPwd =
FormsAuthentication.HashPasswordForStoringInConfigFile(
saltAndPwd, "sha1");
return hashedPwd;
}
Gibt es eine andere C # -Methode zum Hashing von Passwörtern und zum Hinzufügen von Salt?
SHA1
ist nicht Crypto-Grade, daher sollten Sie mindestens verwendenSHA256
, das 256 Bit oder 32 Bytes ausgibt. ABER 256 Bit können NICHT einfach in Basis 64 konvertiert werden, da jedes Base64-Zeichen 6 Bit codiert und 256 nicht vollständig durch 6 teilbar ist. Sie benötigen also einen gemeinsamen Nenner von 6 (für Base64) und 8 (für Bits in einem Byte). über 256 Bit, das sind 264 Bits oder 33 Bytes. TLDR: Verwenden Sie 33.Antworten:
Eigentlich ist das bei den String-Konvertierungen etwas seltsam - was der Mitgliedschaftsanbieter tut, um sie in Konfigurationsdateien zu speichern. Hashes und Salze sind binäre Blobs. Sie müssen sie nicht in Zeichenfolgen konvertieren, es sei denn, Sie möchten sie in Textdateien ablegen.
In meinem Buch Beginning ASP.NET Security (oh, endlich eine Ausrede, um das Buch zu pimpen) mache ich Folgendes
Die Salzbildung ist als Beispiel in der Frage. Sie können Text mit in Byte-Arrays konvertieren
Encoding.UTF8.GetBytes(string)
. Wenn Sie einen Hash in seine Zeichenfolgendarstellung konvertieren müssen, können SieConvert.ToBase64String
und verwendenConvert.FromBase64String
zurückkonvertieren.Sie sollten beachten, dass Sie den Gleichheitsoperator nicht für Byte-Arrays verwenden können. Er überprüft Referenzen und sollte daher einfach beide Arrays durchlaufen, um jedes Byte auf diese Weise zu überprüfen
Verwenden Sie immer ein neues Salz pro Passwort. Salze müssen nicht geheim gehalten werden und können neben dem Hash selbst aufbewahrt werden.
quelle
return array1.Length == array2.Length && !array1.Where((t, i) => t != array2[i]).Any();
Was Blowdart gesagt hat, aber mit etwas weniger Code. Verwenden Sie Linq oder,
CopyTo
um Arrays zu verketten.Mit Linq können Sie auch Ihre Byte-Arrays auf einfache Weise vergleichen.
Bevor Sie dies jedoch implementieren, sollten Sie dies überprüfen diesen Beitrag . Für das Passwort-Hashing möchten Sie möglicherweise einen langsamen Hash-Algorithmus, keinen schnellen.
Zu diesem Zweck gibt es die
Rfc2898DeriveBytes
Klasse, die langsam ist (und langsamer gemacht werden kann) und den zweiten Teil der ursprünglichen Frage dahingehend beantworten kann, dass sie ein Passwort und Salt nehmen und einen Hash zurückgeben kann. Weitere Informationen finden Sie in dieser Frage . Hinweis: Stack Exchange verwendet dasRfc2898DeriveBytes
Kennwort-Hashing (Quellcode hier ).quelle
Ich habe gelesen, dass Hashing-Funktionen wie SHA256 nicht wirklich zum Speichern von Passwörtern gedacht sind: https://patrickmn.com/security/storing-passwords-securely/#notpasswordhashes
Stattdessen wurden adaptive Schlüsselableitungsfunktionen wie PBKDF2, bcrypt oder scrypt verwendet. Hier ist eine PBKDF2-basierte Version, die Microsoft für PasswordHasher in der Microsoft.AspNet.Identity-Bibliothek geschrieben hat:
Beachten Sie, dass hierfür das Nuget-Paket Microsoft.AspNetCore.Cryptography.KeyDerivation installiert sein muss, für das .NET Standard 2.0 (.NET 4.6.1 oder höher) erforderlich ist. Frühere Versionen von .NET finden Sie in der Crypto- Klasse aus der System.Web.Helpers-Bibliothek von Microsoft.
Update Nov 2015
Aktualisierte Antwort zur Verwendung einer Implementierung aus einer anderen Microsoft-Bibliothek, die PBKDF2-HMAC-SHA256-Hashing anstelle von PBKDF2-HMAC-SHA1 verwendet (Hinweis PBKDF2-HMAC-SHA1 ist immer noch sicher, wenn iterCount hoch genug ist). Sie können die Quelle überprüfen, aus der der vereinfachte Code kopiert wurde, da er tatsächlich die Validierung und Aktualisierung von Hashes übernimmt, die aus der vorherigen Antwort implementiert wurden. Dies ist nützlich, wenn Sie iterCount in Zukunft erhöhen müssen.
quelle
PBKDF2SubkeyLength
20 Bytes reduzieren . Das ist die natürliche Größe von SHA1 und eine Erhöhung darüber hinaus verlangsamt den Verteidiger, ohne den Angreifer zu verlangsamen. 2) Ich empfehle, die Anzahl der Iterationen zu erhöhen. Ich empfehle 10.000 bis 100.000, abhängig von Ihrem Leistungsbudget. 3) Ein konstanter Zeitvergleich würde auch nicht schaden, hat aber keine großen praktischen Auswirkungen.Salz wird verwendet, um dem Hash eine zusätzliche Komplexität zu verleihen und das Brute-Force-Cracken zu erschweren.
Aus einem Artikel über Sitepoint :
In .NET gibt es keine Methode, die dies automatisch ausführt. Sie müssen sich also für die oben beschriebene Lösung entscheiden.
quelle
Ich habe eine Klasse mit der folgenden Methode erstellt:
Eingabe validieren
`
quelle
Bah, das ist besser! http://sourceforge.net/projects/pwdtknet/ und es ist besser, weil ..... es Key Stretching durchführt UND HMACSHA512 verwendet :)
quelle
Ich habe eine Bibliothek SimpleHashing.Net erstellt , um das Hashing mit den von Microsoft bereitgestellten zu vereinfachen. Gewöhnliche SHA reichen nicht mehr aus, um Passwörter sicher zu speichern.
Die Bibliothek verwendet die Idee des Hash-Formats von Bcrypt, aber da es keine offizielle MS-Implementierung gibt, bevorzuge ich die Verwendung der im Framework verfügbaren Elemente (dh PBKDF2), aber es ist ein bisschen zu schwierig.
Dies ist ein kurzes Beispiel für die Verwendung der Bibliothek:
quelle
So mache ich das .. Ich erstelle den Hash und speichere ihn mit der
ProtectedData
API:quelle
Ich habe alle Antworten gelesen und denke, dass diese genug sind, insbesondere @ Michael- Artikel mit langsamem Hashing und guten @ CodesInChaos- Kommentaren, aber ich habe beschlossen, mein Code-Snippet zum Hashing / Validieren freizugeben, das möglicherweise nützlich ist und keine [ Microsoft.AspNet.Cryptography] erfordert .KeyDerivation ].
Bitte achten Sie auf die SlowEquals-Funktion, die so wichtig ist. Schließlich hoffe ich auf diese Hilfe und bitte zögern Sie nicht, mich über bessere Ansätze zu beraten.
quelle
Verwenden Sie die
System.Web.Helpers.Crypto
NuGet-Paket von Microsoft. Es fügt dem Hash automatisch Salz hinzu.Sie haben ein Passwort wie folgt:
var hash = Crypto.HashPassword("foo");
Sie überprüfen ein Passwort wie folgt:
var verified = Crypto.VerifyHashedPassword(hash, "foo");
quelle
Wenn Sie keinen asp.net- oder .net-Kern verwenden, gibt es auch eine einfache Möglichkeit in> = .Net Standard 2.0-Projekten.
Zuerst können Sie die gewünschte Größe der Hash-, Salt- und Iterationsnummer festlegen, die sich auf die Dauer der Hash-Generierung bezieht:
Um das Passwort Hash und Salt zu generieren, können Sie Folgendes verwenden:
Um zu überprüfen, ob das vom Benutzer eingegebene Kennwort gültig ist, können Sie anhand der Werte in Ihrer Datenbank Folgendes überprüfen:
Der folgende Komponententest zeigt die Verwendung:
Microsoft Rfc2898DeriveBytes-Quelle
quelle
Als Antwort auf diesen Teil der ursprünglichen Frage "Gibt es eine andere C # -Methode zum Hashing von Kennwörtern" können Sie dies mit ASP.NET Identity v3.0 https://www.nuget.org/packages/Microsoft.AspNet.Identity erreichen. EntityFramework / 3.0.0-rc1-final
quelle
quelle
quelle