webentwicklung-frage-antwort-db.com.de

Asp.net-Identitätskennwort-Hashing

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ät

namespace 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?

33
Edward Wilson

"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.

34
jd4u

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:

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);
57
Andy Brown

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.

8
Joerg Krause