String de hash em c #

97

Tenho um problema ao tentar inserir uma string hash c#.

Já tentei alguns sites, mas a maioria deles está usando arquivos para obter o hash. Outros que são para strings são um pouco complexos. Encontrei exemplos de autenticação do Windows para web como este:

FormsAuthentication.HashPasswordForStoringInConfigFile(tbxPassword.Text.Trim(), "md5")

Preciso usar um hash para tornar uma string que contém um nome de arquivo mais segura. Como eu posso fazer isso?

Exemplo:

string file  = "username";
string hash = ??????(username); 

Devo usar outro algoritmo de hash e não "md5"?

Edy Cu
fonte

Respostas:

192
using System.Security.Cryptography;

public static byte[] GetHash(string inputString)
{
    using (HashAlgorithm algorithm = SHA256.Create())
        return algorithm.ComputeHash(Encoding.UTF8.GetBytes(inputString));
}

public static string GetHashString(string inputString)
{
    StringBuilder sb = new StringBuilder();
    foreach (byte b in GetHash(inputString))
        sb.Append(b.ToString("X2"));

    return sb.ToString();
}

Notas Adicionais

  • Como MD5 e SHA1 são algoritmos obsoletos e inseguros , esta solução usa SHA256. Alternativamente, você pode usar BCrypt ou Scrypt conforme indicado nos comentários.
  • Além disso, considere " salgar " seus hashes e use algoritmos criptográficos comprovados, conforme apontado nos comentários.
Dmitry Polomoshnov
fonte
46
NÃO USE MD5 OU SHA1 , eles são algoritmos obsoletos e inseguros. Use SHA256 no mínimo ou melhor ainda use BCrypt ou Scrypt.
Muhammad Rehan Saeed
1
Veja este exemplo de uso de SCrypt: stackoverflow.com/questions/20042977/…
Muhammad Rehan Saeed
7
@Muh Pode ser facilmente usado para somas de verificação, porque é muito mais rápido que o SHA512. Mas, na verdade, para armazenar senhas, não é recomendado, o que é correto.
LuckyLikey de
7
O que isso b.ToString("X2")significa?
Bilal Fazlani
1
@BilalFazlani veja stackoverflow.com/questions/20750062/…
Hezi
62

A maneira mais rápida de obter uma string hash para fins de armazenamento de senha é um código a seguir:

    internal static string GetStringSha256Hash(string text)
    {
        if (String.IsNullOrEmpty(text))
            return String.Empty;

        using (var sha = new System.Security.Cryptography.SHA256Managed())
        {
            byte[] textData = System.Text.Encoding.UTF8.GetBytes(text);
            byte[] hash = sha.ComputeHash(textData);
            return BitConverter.ToString(hash).Replace("-", String.Empty);
        }
    }

Observações:

  • se o método for invocado frequentemente, a criação da shavariável deve ser refatorada em um campo de classe;
  • a saída é apresentada como string hexadecimal codificada;
andrew.fox
fonte
SHA1Managedaula não é muito cara. ele consome cerca de 130 bytes e os inicializa com algum valor estático, mas isso é tudo. portanto, não deve haver um problema de desempenho na maioria dos casos.
Earth Engine
1
Também SHA1Managedé IDisposablee, portanto, precisa envolver seu uso em um usingbloco.
Earth Engine
O Disposemétodo de propósito é limpar o buffer interno. Caso contrário, haverá risco de ataque à memória.
Earth Engine
3
@MuhammadRehanSaeed quando eu disse que SHA1Managednão é caro, quero dizer que sua criação não é. Além disso, um algoritmo de hash não é necessariamente caro. Só tem que ser (extremamente) caro quando você quer encontrar uma colisão.
Earth Engine
1
@King_Fisher - é impossível! O hash é uma função unilateral, as informações são perdidas. Se você precisar descriptografar, use o método de criptografia sem hash. BTW, criptografar senhas é uma prática ruim.
andrew.fox
8

Eu realmente não entendo todo o escopo da sua pergunta, mas se tudo que você precisa é um hash da string, então é muito fácil entender.

Basta usar o método GetHashCode.

Como isso:

string hash = username.GetHashCode();
Cyril Gupta
fonte
1
Sim, é isso que procuro. Mas o código é um grande erro. Mostrar gravação como int hash = "nome de usuário" .GetHasCode ();
Edy Cu
3
Por que você colocou o nome de usuário entre aspas duplas? Isso obterá o hash da palavra 'nome de usuário' e agora o que está na variável de nome de usuário.
Cyril Gupta,
16
não armazene valores de GetHashCode, é diferente para 32x e 64x
Slava,
14
Essa é uma maneira ruim de criar um hash de senha. Com GetHashCode () você não pode assumir que o mesmo número será gerado em computadores diferentes. Use o método hash Sha1 ou algo assim (postarei um exemplo mais tarde)
andrew.fox
2
Deve-se observar que GetHashCodenão é um algoritmo de hash criptograficamente seguro. Use SHA256 no mínimo ou ainda melhor use BCrypt ou Scrypt para um algoritmo seguro.
Muhammad Rehan Saeed
5

Acho que o que você está procurando não é hash, mas criptografia. Com o hash, você não poderá recuperar o nome do arquivo original da variável "hash". Com criptografia, você pode, e é seguro.

Consulte AES em ASP.NET com VB.NET para obter mais informações sobre criptografia em .NET.

Pieter van Ginkel
fonte
sim, acho que é criptografia, mas gostaria apenas de comparar o hash de resultado. Depois de redirecionar a página.
Edy Cu
Com o que você deseja comparar o nome do arquivo com hash?
Pieter van Ginkel,
1
//Secure & Encrypte Data
    public static string HashSHA1(string value)
    {
        var sha1 = SHA1.Create();
        var inputBytes = Encoding.ASCII.GetBytes(value);
        var hash = sha1.ComputeHash(inputBytes);
        var sb = new StringBuilder();
        for (var i = 0; i < hash.Length; i++)
        {
            sb.Append(hash[i].ToString("X2"));
        }
        return sb.ToString();
    }
Soufiane Neffar
fonte
3
NÃO USE SHA1 a partir deste link, SHA1 é um algoritmo obsoleto e inseguro. Use SHA256 no mínimo, ou ainda melhor, use BCrypt ou Scrypt.
Muhammad Rehan Saeed
Veja este exemplo de uso de SCrypt: stackoverflow.com/questions/20042977/…
Muhammad Rehan Saeed
1

Se o desempenho não for uma preocupação importante, você também pode usar qualquer um destes métodos:
(Caso queira que a string hash esteja em maiúsculas, substitua "x2"por "X2".)

public static string SHA256ToString(string s) 
{
    using (var alg = SHA256.Create())
        return string.Join(null, alg.ComputeHash(Encoding.UTF8.GetBytes(s)).Select(x => x.ToString("x2")));
}

ou:

public static string SHA256ToString(string s)
{            
    using (var alg = SHA256.Create())
        return alg.ComputeHash(Encoding.UTF8.GetBytes(s)).Aggregate(new StringBuilder(), (sb, x) => sb.Append(x.ToString("x2"))).ToString();
}
Babak
fonte
0

O caminho mais curto e rápido de todos os tempos. Apenas 1 linha!

    public static string StringSha256Hash(string text) =>
        string.IsNullOrEmpty(text) ? string.Empty : BitConverter.ToString(new System.Security.Cryptography.SHA256Managed().ComputeHash(System.Text.Encoding.UTF8.GetBytes(text))).Replace("-", string.Empty);
Erçin Dedeoğlu
fonte
Outra versão de 1 linha usando StringBuilder & Linq public static string Hash (string value) => string.IsNullOrEmpty (value)? valor: SHA256.Create (). ComputeHash (Encoding.UTF8.GetBytes (value)). Aggregate (new StringBuilder (), (sb, b) => sb.Append (b.ToString ("X2"))). ToString ();
Paul