¿Cuál es el algoritmo hash predeterminado que usa la membresía ASP.NET?
authentication membership (6)
EDITAR: no utilice el proveedor de membresía tal como está, ya que es terriblemente inadecuado en términos de protección de contraseñas del usuario
En vista del hecho de que googlear el "algoritmo de hash del proveedor de membresía" presenta esta respuesta como el primer resultado y el evangelio que se deducirá, me corresponde advertir a las personas sobre el uso del Proveedor de Membresía de esta manera y usar hashes como SHA-1 , MD5 etc. para ocultar contraseñas en bases de datos.
tl; dr
Utilice una función de derivación de claves como bcrypt, scrypt o (si necesita cumplimiento de FIPS) PBKDF2 con un factor de trabajo suficiente para necesitar el tiempo de hash para que una contraseña sea tan cercana a 1000 ms o más.
Los hashes son fáciles de usar en estos días con abundantes ejemplos de violaciones de datos en la historia reciente. Para evitar que las contraseñas de tus usuarios terminen en pastebin en el siguiente hack, asegúrate de que las contraseñas sean hash con una función que requiere un tiempo suficientemente largo para computar.
En lugar de ser un proveedor de membresía, pruebe IdentityReboot o las implementaciones más nuevas de Microsoft de las que Troy Hunt habla al menos.
También es interesante que en los mismos resultados de google mencionados anteriormente encuentre un tutorial que muestra a las personas lo fácil que es forzar estos hashes de contraseñas utilizando herramientas populares como JtR o Hashcat. En una plataforma de GPU personalizada, SHA1 se puede descifrar a una velocidad asombrosa de 48867 millones de hashes por segundo . Con un diccionario gratuito como Rockyou o similar , una persona motivada con su base de datos tendrá rápidamente la mayoría de las contraseñas de sus usuarios. Como desarrollador, es su responsabilidad ética hacer lo que sea necesario para proteger la seguridad de las contraseñas de sus usuarios.
El hashing predeterminado es SHA1 pero también lo sal y lo base64:
public string EncodePassword(string pass, string salt)
{
byte[] bytes = Encoding.Unicode.GetBytes(pass);
byte[] src = Encoding.Unicode.GetBytes(salt);
byte[] dst = new byte[src.Length + bytes.Length];
Buffer.BlockCopy(src, 0, dst, 0, src.Length);
Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length);
HashAlgorithm algorithm = HashAlgorithm.Create("SHA1");
byte[] inArray = algorithm.ComputeHash(dst);
return Convert.ToBase64String(inArray);
}
Si desea saber más acerca de cómo cambiarlo, todavía tengo que averiguarlo (a menos que use un proveedor personalizado, vea más abajo), sin embargo SHA-1 es bastante bueno por ahora. Si está buscando revertirlo o buscarlo, estos muchachos trabajaron en eso: http://forums.asp.net/p/1336657/2899172.aspx
Esta pregunta SO ayudará a revertir o duplicar esta técnica, si eso es lo que podría ser necesario. Reimplementar la membresía de ASP.NET y la contraseña de usuario Hashing en Ruby
Si está creando un proveedor personalizado, puede crear sus algoritmos y algoritmos de cifrado y hash.
private byte[] ConvertPasswordForStorage(string Password)
{
System.Text.UnicodeEncoding ue =
new System.Text.UnicodeEncoding();
byte[] uePassword = ue.GetBytes(Password);
byte[] RetVal = null;
switch (_PasswordFormat)
{
case MembershipPasswordFormat.Clear:
RetVal = uePassword;
break;
case MembershipPasswordFormat.Hashed:
HMACSHA1 SHA1KeyedHasher = new HMACSHA1();
SHA1KeyedHasher.Key = _ValidationKey;
RetVal = SHA1KeyedHasher.ComputeHash(uePassword);
break;
case MembershipPasswordFormat.Encrypted:
TripleDESCryptoServiceProvider tripleDes = new
TripleDESCryptoServiceProvider();
tripleDes.Key = _DecryptionKey;
tripleDes.IV = new byte[8];
MemoryStream mStreamEnc = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream(mStreamEnc,
tripleDes.CreateEncryptor(),
CryptoStreamMode.Write);
cryptoStream.Write(uePassword, 0, uePassword.Length);
cryptoStream.FlushFinalBlock();
RetVal = mStreamEnc.ToArray();
cryptoStream.Close();
break;
}
return RetVal;
}
private string GetHumanReadablePassword(byte[] StoredPassword)
{
System.Text.UnicodeEncoding ue = new System.Text.UnicodeEncoding();
string RetVal = null;
switch (_PasswordFormat)
{
case MembershipPasswordFormat.Clear:
RetVal = ue.GetString(StoredPassword);
break;
case MembershipPasswordFormat.Hashed:
throw new ApplicationException(
"Password cannot be recovered from a hashed format");
case MembershipPasswordFormat.Encrypted:
TripleDESCryptoServiceProvider tripleDes =
new TripleDESCryptoServiceProvider();
tripleDes.Key = _DecryptionKey;
tripleDes.IV = new byte[8];
CryptoStream cryptoStream =
new CryptoStream(new MemoryStream(StoredPassword),
tripleDes.CreateDecryptor(), CryptoStreamMode.Read);
MemoryStream msPasswordDec = new MemoryStream();
int BytesRead = 0;
byte[] Buffer = new byte[32];
while ((BytesRead = cryptoStream.Read(Buffer, 0, 32)) > 0)
{
msPasswordDec.Write(Buffer, 0, BytesRead);
}
cryptoStream.Close();
RetVal = ue.GetString(msPasswordDec.ToArray());
msPasswordDec.Close();
break;
}
return RetVal;
}
¿Cuál es el algoritmo hash predeterminado que usa la membresía ASP.NET? ¿Y cómo puedo cambiarlo?
Adjunto un fragmento que muestra el código como en la respuesta anterior de Rawbert en F #
open System
open System.Security.Cryptography
open System.Text
module PasswordHelper =
let EncodePassword(pass : string, salt : string) =
let bytes = Encoding.Unicode.GetBytes(pass)
let src = Convert.FromBase64String(salt)
let dst : byte array = Array.zeroCreate (src.Length + bytes.Length)
Buffer.BlockCopy(src, 0, dst, 0, src.Length)
Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length)
let algorithm = HashAlgorithm.Create("SHA1")
let inArray = algorithm.ComputeHash(dst)
Convert.ToBase64String(inArray)
Este es el código de trabajo de una aplicación activa
El algoritmo hash predeterminado cambió a HMACSHA256 en .NET 4.0 Framework.
Tenga en cuenta que a diferencia de SHA-1, HMAC SHA-256 es un hash con clave. Si sus valores hash se comportan de manera no determinista, es probable que no haya establecido una clave, forzándola a utilizar una aleatoria. Algo similar a lo siguiente sería el culpable (que es lo que acabo de pasar una hora averiguando: p).
HashAlgorithm.Create(Membership.HashAlgorithmType)
Si desea que funcione con un proveedor existente, puede revertirlo a los valores predeterminados anteriores utilizando esta guía .
El tipo de algoritmo hash predeterminado es SHA1. Hay dos formas en que puede cambiar esto.
1) Si está trabajando con IIS 7, puede actualizar esto usando la configuración de "Clave de la máquina" (que se muestra a continuación). Esto le permite elegir el método de encriptación de una lista de opciones disponibles y especificar las claves o las opciones de generación de claves.
2) Si está trabajando con IIS 6, puede cambiar el tipo de algoritmo hash utilizando el elemento membership en el archivo web.config:
<membership
defaultProvider="provider name"
userIsOnlineTimeWindow="number of minutes"
hashAlgorithmType="SHA1">
<providers>...</providers>
</membership>
De acuerdo con la documentación, el valor de cadena del atributo hashAlgorithmType puede ser cualquiera de los tipos de algoritmos de hash de .Net proporcionados. Un poco de excavación muestra que los valores válidos para ASP.Net 2, 3 y 3.5 son MD5
, RIPEMD160
, SHA1
, SHA256
, SHA384
, SHA512
. La parte importante aquí es que todas estas clases heredan de HashAlgorithm
.
El valor del atributo hashAlgorithmType también puede ser una entrada del elemento cryptoNameMapping en el archivo cryptoNameMapping . Puede usar esto si necesita un algoritmo de hashing de terceros. El archivo machine.config normalmente se puede encontrar en C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/CONFIG
si está utilizando ASP.Net 2 o posterior. Puede leer más sobre cómo establecer estos valores here .
Hay una corrección en el algoritmo hash, debe usar:
byte[] src = Convert.FromBase64String(salt);
en lugar de
byte[] src = Encoding.Unicode.GetBytes(salt);
Lea el artículo http://svakodnevnica.com.ba/index.php?option=com_kunena&func=view&catid=4&id=4&Itemid=5&lang=en#6
La respuesta anterior de Ryan Christensen no está completa. La parte donde convierte la sal en un byte [] no es correcta.
Este es un ejemplo de trabajo que he implementado en una solución para un cliente:
public string Hash(string value, string salt)
{
byte[] bytes = Encoding.Unicode.GetBytes(value);
byte[] src = Convert.FromBase64String(salt);
byte[] dst = new byte[src.Length + bytes.Length];
Buffer.BlockCopy(src, 0, dst, 0, src.Length);
Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length);
HashAlgorithm algorithm = HashAlgorithm.Create("SHA1");
byte[] inArray = algorithm.ComputeHash(dst);
return Convert.ToBase64String(inArray);
}