Das neue ASP.net Identity-Projekt enthält einige nützliche Codes und Schnittstellen für die Sicherheit von Websites. Um ein benutzerdefiniertes System mithilfe der Schnittstellen zu implementieren (anstelle der in der MVC 5-Vorlage enthaltenen Standardimplementierung von Entity Framework), ist ein IPasswordHasher
erforderlich.
IPasswordHasher
Schnittstelle in der ASP.net-Identitätnamespace Microsoft.AspNet.Identity
{
public interface IPasswordHasher
{
string HashPassword(string password);
PasswordVerificationResult VerifyHashedPassword(string hashedPassword, string providedPassword);
}
}
Ist es möglich, Password Salting für eine sicherere Verschlüsselung in ASP.net Identity und über diese Schnittstelle zu verwenden?
"Ist es möglich, Password Salting für eine sicherere Verschlüsselung in ASP.net Identity und über diese Schnittstelle zu verwenden?"
Ja, die Schnittstelle ist für die neue Implementierung von PasswordHasher vorgesehen, die bereits im Core Framework vorhanden ist.
Beachten Sie auch, dass die Standardimplementierung bereits Salt + Bytes verwendet.
Nachdem Sie ein benutzerdefiniertes PasswordHasher
erstellt haben (sagen Sie MyPasswordHasher
), können Sie es einer UserManager-Instanz wie userManager.PasswordHasher=new MyPasswordHasher()
zuweisen.
Siehe ein Beispiel für einen solchen IPasswordHasher
Um ein benutzerdefiniertes System mithilfe der Schnittstellen zu implementieren (anstelle der in der MVC 5-Vorlage enthaltenen Standardimplementierung von Entity Framework), ist ein IPasswordHasher erforderlich.
Für die Implementierung eines alternativen Systems von EF - müssen Sie alle Core-Schnittstellen implementieren. - Die Implementierung von IPasswordHasher ist nicht erforderlich. PasswordHasher ist bereits in der Implementierung des Core Frameworks enthalten.
GESUNDHEITSWARNUNG für die folgende Antwort: Ermitteln Sie, welche Version von ASP.Net Identity Sie verwenden. Sie sollten direkt auf den Quellcode verweisen, wenn es sich um eine der neueren Versionen aus dem Github-Repository handelt.
Während ich dies schreibe, unterscheidet sich die aktuelle Version ( .0.0-rc1 /.../ PasswordHasher.cs ) des Passwort-Handlers erheblich von der unten stehenden Antwort. Diese neuere Version unterstützt mehrere Hash-Algorithmus-Versionen und ist dokumentiert als (und kann sich bis zu dem Zeitpunkt, an dem Sie dies lesen, weiter ändern):
Version 2:
- PBKDF2 mit HMAC-SHA1, 128-Bit-Salt, 256-Bit-Unterschlüssel, 1000 Iterationen.
- (Siehe auch: SDL-Kryptorichtlinien v5.1, Teil III)
- Format:
{ 0x00, salt, subkey }
Version 3:
- PBKDF2 mit HMAC-SHA256, 128-Bit-Salt, 256-Bit-Unterschlüssel, 10000 Iterationen.
- Format:
{ 0x01, prf (UInt32), iter count (UInt32), salt length (UInt32), salt, subkey }
- (Alle UInt32s sind Big-Endian gespeichert.)
Die ursprüngliche Antwort ist weiterhin gültig für die ursprüngliche Version von ASP.Net Identity und lautet wie folgt:
@ jd4u ist richtig, aber um ein bisschen mehr Licht zu werfen, würde das nicht in einen Kommentar für seine Antwort passen:
Microsoft.AspNet.Identity.PasswordHasher : IPasswordHasher
Salzt schon für dich, Rfc2898DeriveBytes
verwendet, um das Salz und den Hash zu erzeugen.Microsoft.AspNet.Identity.UserManager<TUser>
verwendet Microsoft.AspNet.Identity.PasswordHasher
als konkretes IPasswordHasher
PasswordHasher
ist wiederum ein wirklich einfacher Wrapper für (letztendlich) System.Security.Cryptography.Rfc2898DeriveBytes
Wenn Sie also Rfc2898DeriveBytes
Verwenden möchten, verwenden Sie einfach PasswordHasher
- das ganze schwere Heben ist (hoffentlich richtig) bereits für Sie erledigt.
Details
Der vollständige Code, den PasswordHasher (derzeit) verwendet, hat eine sehr ähnliche Wirkung:
int saltSize = 16;
int bytesRequired = 32;
byte[] array = new byte[1 + saltSize + bytesRequired];
int iterations = SOME; // 1000, afaik, which is the min recommended for Rfc2898DeriveBytes
using (var pbkdf2 = new Rfc2898DeriveBytes(password, saltSize, iterations))
{
byte[] salt = pbkdf2.Salt;
Buffer.BlockCopy(salt, 0, array, 1, saltSize);
byte[] bytes = pbkdf2.GetBytes(bytesRequired);
Buffer.BlockCopy(bytes, 0, array, saltSize+1, bytesRequired);
}
return Convert.ToBase64String(array);
Beim Update von der Mitgliedschaft auf AspNet.Identity ist ein Problem aufgetreten. Die Rfc2898-Hashes unterscheiden sich von den zuvor verwendeten. Das hat gute Gründe, aber das Ändern der Hashes würde erfordern, dass alle Benutzer ihre Passwörter zurücksetzen. Als Lösung macht diese benutzerdefinierte Implementierung es abwärtskompatibel:
public class MyPasswordHasher : PasswordHasher {
public FormsAuthPasswordFormat FormsAuthPasswordFormat { get; set; }
public MyPasswordHasher(FormsAuthPasswordFormat format) {
FormsAuthPasswordFormat = format;
}
public override string HashPassword(string password) {
return FormsAuthentication.HashPasswordForStoringInConfigFile(password, FormsAuthPasswordFormat.ToString());
}
public override PasswordVerificationResult VerifyHashedPassword(string hashedPassword, string providedPassword) {
var testHash = FormsAuthentication.HashPasswordForStoringInConfigFile(providedPassword, FormsAuthPasswordFormat.ToString());
return hashedPassword.Equals(testHash) ? PasswordVerificationResult.Success : PasswordVerificationResult.Failed;
}
}
Sobald Sie Ihre UserManager-Instanz erstellt haben, legen Sie einfach den Hash-Wert fest:
Usermanager.PasswordHasher = new MyPasswordHasher(FormsAuthPasswordFormat.SHA1);
Der Code beschwert sich, dass die HashPasswordForStoringInConfigFile
-Methode veraltet ist, aber das ist in Ordnung, da wir wissen, dass die ganze Übung darin besteht, die alte Technologie loszuwerden.