Qual é o algoritmo de hash padrão usado pela associação do ASP.NET?

Qual é o algoritmo de hash padrão usado pela associação do ASP.NET? E como posso mudar isso?

EDIT: não use o provedor de associação como-é porque é horrivelmente inadequada em termos de proteger senhas do usuário

À luz do fato de que pesquisando “algoritmo de hashing de provedor de associação” revela essa resposta como o primeiro resultado, e o evangelho que será inferido, cabe a mim avisar as pessoas sobre como usar o Provedor de Associação e usar hashes como SHA-1 , MD5 etc para ofuscar senhas em bancos de dados.

tl; dr

Use uma function de derivação de chave como bcrypt, scrypt ou (se você precisar de conformidade com FIPS) PBKDF2 com um fator de trabalho suficiente para exigir que o tempo de hashing para uma única senha seja o mais próximo de 1000ms ou mais.

Os hashs são fáceis de forçar a força bruta nos dias de hoje, com amplos exemplos de violações de dados na história recente. Para evitar que as senhas de seus usuários acabem no pastebin na próxima invasão, garanta que as senhas sejam criptografadas com uma function que leve um tempo suficientemente longo para computar!

Em vez de provedor de associação, tente IdentityReboot ou as implementações mais recentes da Microsoft que Troy Hunt fala pelo menos.

Também é interessante que, nos mesmos resultados do google mencionados acima, eu encontre um tutorial mostrando às pessoas preciosamente como é fácil forçar esses hashes de senha usando ferramentas populares como JtR ou Hashcat. Em um equipamento de GPU personalizado, o SHA1 pode ser quebrado a uma taxa impressionante de 48867 milhões de hashes por segundo ! Com um dictionary gratuito como rockyou ou algo semelhante , uma pessoa motivada com seu database terá rapidamente a maioria das senhas de seus usuários. Como desenvolvedor, é sua responsabilidade ética fazer o que for necessário para proteger a segurança das senhas de seus usuários.


O hashing padrão é SHA1, mas eles também o salgam e 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); } 

Se você quiser saber mais sobre como alterá-lo, eu ainda preciso descobrir (a menos que você use um provedor personalizado, veja abaixo), no entanto SHA-1 é muito bom por agora. Se você estiver olhando para inverter isso ou pesquisa a partir desses caras fizeram algum trabalho sobre isso: http://forums.asp.net/p/1336657/2899172.aspx

Essa pergunta de SO ajudará a reverter ou duplicar essa técnica se isso for necessário. Reimplementar a associação do ASP.NET e o hash de senha do usuário em Ruby

Se você estiver fazendo um provedor personalizado, poderá criar seus algoritmos e methods de hash e criptografia.

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

http://msdn.microsoft.com/pt-br/library/aa479048.aspx

A resposta acima por Ryan Christensen não está completa. A parte em que converte o sal em byte [] não está correta.

Este é um exemplo de trabalho que implementei em uma solução para um 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); } 

O tipo de algoritmo de hash padrão é SHA1. Existem duas maneiras de mudar isso.

1) Se você estiver trabalhando com o IIS 7, poderá atualizar isso usando a configuração “Chave do Computador” (mostrada abaixo). Isso permite escolher o método de criptografia em uma lista de opções disponíveis e especificar as chaves ou as opções de geração de chaves.

Página de configuração da chave de máquina da ferramenta de administração do IIS 7

2) Se você estiver trabalhando com o IIS 6, poderá alterar o tipo de algoritmo de hash usando o elemento membership no arquivo web.config:

  ...  

De acordo com a documentação, o valor da string do atributo hashAlgorithmType pode ser qualquer um dos tipos de algoritmos de hashing .Net fornecidos. Um pouco de escavação mostra que os valores válidos para ASP.Net 2, 3 e 3.5 são MD5 , RIPEMD160 , SHA1 , SHA256 , SHA384 , SHA512 . A parte importante aqui é que todas essas classs herdam do HashAlgorithm .

O valor do atributo hashAlgorithmType também pode ser uma input do elemento cryptoNameMapping no arquivo machine.config. Você poderia usar isso se você precisar de um algoritmo de hash de terceiros. O arquivo machine.config normalmente pode ser encontrado em C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG se você estiver usando o ASP.Net 2 ou posterior. Você pode ler mais sobre como configurar esses valores aqui .

O algoritmo de hash padrão foi alterado para HMACSHA256 no .NET 4.0 Framework.

Observe que, diferentemente do SHA-1, o HMAC SHA-256 é um hash com chave. Se seus hashes estão se comportando de forma não determinística, você provavelmente não definiu uma chave, forçando-a a usar uma chave aleatória. Algo semelhante ao seguinte seria o culpado (que é o que eu passei uma hora descobrindo: p).

 HashAlgorithm.Create(Membership.HashAlgorithmType) 

Se você deseja que ele funcione com um provedor existente, você pode reverter para os antigos padrões usando este guia .

Há uma correção no algoritmo de hash, você deve usar:

 byte[] src = Convert.FromBase64String(salt); 

ao invés de

 byte[] src = Encoding.Unicode.GetBytes(salt); 

Leia o artigo http://svakodnevnica.com.ba/index.php?option=com_kunena&func=view&catid=4&id=4&Itemid=5&lang=en#6

Eu append um trecho mostrando o código como na resposta de Rawbert acima em 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 é o código de trabalho de um aplicativo ativo