web-dev-qa-db-fra.com

Hachage de mot de passe d'identité Asp.net

Le nouveau projet d'identité ASP.net a apporté du code et des interfaces utiles pour la sécurité des sites Web. Pour implémenter un système personnalisé à l'aide des interfaces (au lieu d'utiliser l'implémentation Entity Framework standard incluse dans le modèle MVC 5), un IPasswordHasher est requis.

IPasswordHasher interface dans ASP.net Identity

namespace Microsoft.AspNet.Identity
{
    public interface IPasswordHasher
    {
         string HashPassword(string password);
         PasswordVerificationResult VerifyHashedPassword(string hashedPassword, string providedPassword);
    }
}

Est-il possible d'utiliser le salage de mot de passe pour un cryptage plus sécurisé dans ASP.net Identity et via cette interface?

33
Edward Wilson

"Est-il possible d'utiliser le salage de mot de passe pour un cryptage plus sécurisé dans ASP.net Identity et via cette interface?"

Oui, l'interface est fournie pour la nouvelle implémentation de PasswordHasher déjà présente dans le framework Core.

Notez également que l'implémentation par défaut utilise déjà Salt + Bytes.

Après avoir créé un PasswordHasher personnalisé (par exemple MyPasswordHasher), vous pouvez l'affecter à l'instance UserManager comme userManager.PasswordHasher=new MyPasswordHasher()

Voir un exemple d'un tel IPasswordHasher

Pour implémenter un système personnalisé à l'aide des interfaces (au lieu d'utiliser l'implémentation Entity Framework standard incluse dans le modèle MVC 5), un IPasswordHasher est requis.

Pour implémenter un système alternatif à partir d'EF, - Vous devez implémenter toutes les interfaces Core. - L'implémentation d'IPasswordHasher n'est pas requise. PasswordHasher est déjà fourni dans le framework Core lors de sa mise en œuvre.

34
jd4u

AVERTISSEMENT DE SANTÉ pour la réponse ci-dessous: savoir quelle version de l'identité ASP.Net vous utilisez. Vous devez vous référer directement au code source s'il s'agit d'une des versions les plus récentes du référentiel github.

Au moment où j'écris ceci, la version actuelle ( .0.0-rc1 /.../ PasswordHasher.cs ) du gestionnaire de mot de passe est significativement différente de la réponse ci-dessous. Cette nouvelle version prend en charge plusieurs versions d'algorithme de hachage et est documentée comme (et peut changer davantage au moment où vous lisez ceci):

Version 2:

  • PBKDF2 avec HMAC-SHA1, sel 128 bits, sous-clé 256 bits, 1000 itérations.
  • (Voir aussi: SDL crypto guidelines v5.1, Part III)
  • Format: { 0x00, salt, subkey }

Version 3:

  • PBKDF2 avec HMAC-SHA256, sel 128 bits, sous-clé 256 bits, 10000 itérations.
  • Format: { 0x01, prf (UInt32), iter count (UInt32), salt length (UInt32), salt, subkey }
  • (Tous les UInt32 sont stockés en big-endian.)

La réponse d'origine est toujours valide pour la version originale de ASP.Net Identity, et est la suivante:


@ jd4u est correct, mais pour apporter un peu plus de lumière qui ne rentrerait pas dans un commentaire pour sa réponse:

Donc, si vous allez utiliser Rfc2898DeriveBytes, Utilisez simplement PasswordHasher - tout le gros du travail est déjà fait (si tout va bien) pour vous.

Détails

Le code complet que PasswordHasher (actuellement) utilise finalement fait quelque chose de très proche de:

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

J'ai rencontré un problème lors de la mise à jour de l'appartenance à AspNet.Identity. Les hachages Rfc2898 sont différents de ceux utilisés auparavant. C'est pour une bonne raison, mais pour changer les hachages, tous les utilisateurs devraient réinitialiser leurs mots de passe. En tant que solution, cette implémentation personnalisée la rend rétrocompatible:

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;
   }
}

Une fois que vous avez créé votre instance UserManager, définissez simplement le hachage:

Usermanager.PasswordHasher = new MyPasswordHasher(FormsAuthPasswordFormat.SHA1);

Le code se plaint que la méthode HashPasswordForStoringInConfigFile est déconseillée, mais c'est très bien car nous savons que tout l'exercice consiste à se débarrasser de l'ancienne technologie.

8
Joerg Krause