tables - asp.net core identity
Asp.net identidad contraseƱa hash (3)
El nuevo proyecto de identidad de ASP.net ha aportado algunos códigos e interfaces útiles para la seguridad del sitio web. Para implementar un sistema personalizado utilizando las interfaces (en lugar de utilizar la implementación estándar de Entity Framework incluida en la plantilla de MVC 5) se necesita un IPasswordHasher
.
Interfaz IPasswordHasher
en ASP.net Identity
namespace Microsoft.AspNet.Identity
{
public interface IPasswordHasher
{
string HashPassword(string password);
PasswordVerificationResult VerifyHashedPassword(string hashedPassword, string providedPassword);
}
}
¿Es posible utilizar el descifrado de contraseñas para un cifrado más seguro en ASP.net Identity y a través de esta interfaz?
"¿Es posible utilizar el descifrado de contraseñas para un cifrado más seguro en ASP.net Identity y a través de esta interfaz?"
Sí, la interfaz se proporciona para la nueva implementación de PasswordHasher ya presente en Core framework.
También tenga en cuenta que la implementación predeterminada ya está utilizando Salt + Bytes.
Después de crear PasswordHasher
personalizado (digamos MyPasswordHasher
), puede asignarlo a la instancia de userManager.PasswordHasher=new MyPasswordHasher()
como userManager.PasswordHasher=new MyPasswordHasher()
Vea un ejemplo de tales IPasswordHasher
Para implementar un sistema personalizado utilizando las interfaces (en lugar de utilizar la implementación estándar de Entity Framework incluida en la plantilla de MVC 5) se necesita un IPasswordHasher.
Para implementar un sistema alternativo desde EF, - Deberá implementar todas las interfaces Core. - La implementación de IPasswordHasher no es necesaria. PasswordHasher ya se proporciona en Core framework como su implementación.
Me encontré con un problema al actualizar de Membresía a AspNet.Identity. Los hash Rfc2898 son diferentes de los utilizados anteriormente. Eso es por una buena razón, pero cambiar los valores hash requeriría que todos los usuarios restablezcan sus contraseñas. Como solución, esta implementación personalizada hace que sea compatible con versiones anteriores:
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;
}
}
Una vez que haya creado su instancia de UserManager, simplemente configure el hasher:
Usermanager.PasswordHasher = new MyPasswordHasher(FormsAuthPasswordFormat.SHA1);
El código se queja de que el método HashPasswordForStoringInConfigFile
está en desuso, pero está bien, ya que sabemos que todo el ejercicio consiste en deshacerse de la tecnología anterior.
AVISO DE SALUD para la respuesta a continuación: sepa qué versión de identidad de ASP.Net está usando. Debería consultar el código fuente directamente si es una de las versiones más nuevas del repositorio github.
Mientras escribo esto, la versión actual ( 3.0.0-rc1/.../PasswordHasher.cs ) del manejador de contraseñas es significativamente diferente a la respuesta a continuación. Esta versión más reciente admite múltiples versiones de algoritmos hash y está documentada como (y puede cambiar aún más cuando la lea):
Versión 2:
- PBKDF2 con HMAC-SHA1, sal de 128 bits, subclave de 256 bits, 1000 iteraciones.
- (Ver también: SDL crypto guidelines v5.1, Parte III)
- Formato:
{ 0x00, salt, subkey }
Versión 3:
- PBKDF2 con HMAC-SHA256, sal de 128 bits, subclave de 256 bits, 10000 iteraciones.
- Formato:
{ 0x01, prf (UInt32), iter count (UInt32), salt length (UInt32), salt, subkey }
- (Todos los UInt32 se almacenan en big-endian).
La respuesta original sigue siendo válida para la versión original de ASP.Net Identity , y es la siguiente:
@ jd4u es correcto, pero arrojar un poco más de luz que no cabría en un comentario por su respuesta:
-
Microsoft.AspNet.Identity.PasswordHasher : IPasswordHasher
ya sales para usted,- más importante aún, usa
Rfc2898DeriveBytes
para generar la sal y el hash, - que usa PBKDF2 estándar de la industria ( discusión del SE aquí , recomendación de OWASP para PBKDF2 aquí ).
- más importante aún, usa
- La implementación predeterminada de
Microsoft.AspNet.Identity.UserManager<TUser>
usaMicrosoft.AspNet.Identity.PasswordHasher
como unaIPasswordHasher
concreta -
PasswordHasher
a su vez es un contenedor realmente simple para (en última instancia)System.Security.Cryptography.Rfc2898DeriveBytes
Entonces, si va a usar Rfc2898DeriveBytes
, simplemente use PasswordHasher
; todo el trabajo pesado ya está hecho (con suerte, correcto) para usted.
Detalles
El código completo que PasswordHasher (actualmente) usa finalmente hace algo muy parecido a:
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);