Qual é a maneira mais fácil de criptografar uma senha quando eu a guardo no registro?

Neste momento, estou a escrevê-lo num texto claro.É um programa interno, por isso não é assim tão mau, mas gostava de o fazer bem. Como devo criptografar isso ao escrever para o registro e como decriptá-lo?

OurKey.SetValue("Password", textBoxPassword.Text);
Author: John Saunders, 2008-10-17

12 answers

Você não descriptografa senhas de autenticação!

Pressione-os usando algo como o fornecedor SHA256 e quando tiver de desafiar, pressione a entrada do utilizador e veja se as duas barras correspondem.

byte[] data = System.Text.Encoding.ASCII.GetBytes(inputString);
data = new System.Security.Cryptography.SHA256Managed().ComputeHash(data);
String hash = System.Text.Encoding.ASCII.GetString(data);
Deixar as senhas reversíveis é um modelo horrível. Pensei que estávamos a falar de autenticação na linha da frente. Claro que existem casos em que você deseja cifrar senhas para outras coisas que precisam ser reversíveis, mas deve seja um bloqueio de 1-way em cima de tudo (com poucas exceções).

Actualizei o algoritmo de hashing, mas para a melhor força possível queres manter um sal privado e adicioná-lo à tua entrada antes de amassar. Voltarias a fazer isto quando comparares. Isto adiciona outra camada tornando ainda mais difícil para alguém reverter.

 114
Author: Oli, 2017-05-23 11:47:27
Por favor, considere também "salgar" o seu haxixe (não um conceito culinário!). Basicamente, isso significa adicionar um texto aleatório à palavra-passe antes de O usar.

"o valor de sal ajuda a atrasar um ataque de um atacante executar um dicionário caso a sua loja credencial seja comprometida, dando-lhe tempo adicional para detectar e reagir ao compromisso."

Para guardar as senhas:

A) gerar um valor salgado Aleatório:

byte[] salt = new byte[32];
System.Security.Cryptography.RNGCryptoServiceProvider.Create().GetBytes(salt);

B) juntar o sal ao senha.

// Convert the plain string pwd into bytes
byte[] plainTextBytes = System.Text UnicodeEncoding.Unicode.GetBytes(plainText);
// Append salt to pwd before hashing
byte[] combinedBytes = new byte[plainTextBytes.Length + salt.Length];
System.Buffer.BlockCopy(plainTextBytes, 0, combinedBytes, 0, plainTextBytes.Length);
System.Buffer.BlockCopy(salt, 0, combinedBytes, plainTextBytes.Length, salt.Length);

Hash a senha combinada & salt:

// Create hash for the pwd+salt
System.Security.Cryptography.HashAlgorithm hashAlgo = new System.Security.Cryptography.SHA256Managed();
byte[] hash = hashAlgo.ComputeHash(combinedBytes);

D) adicione o sal à hash resultante.

// Append the salt to the hash
byte[] hashPlusSalt = new byte[hash.Length + salt.Length];
System.Buffer.BlockCopy(hash, 0, hashPlusSalt, 0, hash.Length);
System.Buffer.BlockCopy(salt, 0, hashPlusSalt, hash.Length, salt.Length);

E) armazene o resultado na sua base de dados do utilizador.

Esta abordagem significa que você não precisa armazenar o sal separadamente e, em seguida, recompor a hash usando o valor de sal e o valor de senha de texto simples obtido do Usuário.

Edit : à medida que o poder de computação em bruto se torna mais barato e mais rápido, o valor de hashing -- ou hashs salting -- recusou. O Jeff Atwood tem uma excelente actualização de 2012 muito longa para repetir aqui, que diz:

Isto (usando chicotes salgados) dará a ilusão de segurança mais do que qualquer segurança real. Uma vez que você precisa tanto do sal ea escolha do algoritmo de hash para gerar o hash, e para verificar o hash, é improvável que um atacante teria um, mas não o outro. Se você foi comprometido ao ponto que um atacante tem sua base de dados de senha, é é razoável presumir que eles têm ou podem ter o seu segredo, sal escondido. A primeira regra da segurança é sempre assumir e planear o pior. Você deve usar um sal, idealmente um sal aleatório para cada usuário? Claro, é ... definitivamente uma boa prática, e pelo menos permite-te disambiguação de dois usuários que têm a mesma senha. Mas hoje em dia, os sais por si só já não te podem salvar de uma pessoa disposta a passar um alguns milhares de dólares em hardware de cartão de vídeo, e se você pensa que eles can, estás em apuros.
 21
Author: DOK, 2012-04-14 16:27:37
Isto é o que você gostaria de fazer:
OurKey.SetValue("Password", StringEncryptor.EncryptString(textBoxPassword.Text));
OurKey.GetValue("Password", StringEncryptor.DecryptString(textBoxPassword.Text));
Pode fazer isso com as seguintes aulas. Esta classe é uma classe genérica é o ponto final do cliente. Ele permite o COI de vários algoritmos de criptografia usando Ninject .
public class StringEncryptor
{
    private static IKernel _kernel;

    static StringEncryptor()
    {
        _kernel = new StandardKernel(new EncryptionModule());
    }

    public static string EncryptString(string plainText)
    {
        return _kernel.Get<IStringEncryptor>().EncryptString(plainText);
    }

    public static string DecryptString(string encryptedText)
    {
        return _kernel.Get<IStringEncryptor>().DecryptString(encryptedText);
    }
}

Esta próxima classe é a classe ninject que lhe permite injectar os vários algoritmos:

public class EncryptionModule : StandardModule
{
    public override void Load()
    {
        Bind<IStringEncryptor>().To<TripleDESStringEncryptor>();
    }
}

Esta é a interface que qualquer algoritmo precisa de implementar para cifrar / descodificar cadeias de caracteres:

public interface IStringEncryptor
{
    string EncryptString(string plainText);
    string DecryptString(string encryptedText);
}
Isto é uma implementação. usando o algoritmo TripleDES:
public class TripleDESStringEncryptor : IStringEncryptor
{
    private byte[] _key;
    private byte[] _iv;
    private TripleDESCryptoServiceProvider _provider;

    public TripleDESStringEncryptor()
    {
        _key = System.Text.ASCIIEncoding.ASCII.GetBytes("GSYAHAGCBDUUADIADKOPAAAW");
        _iv = System.Text.ASCIIEncoding.ASCII.GetBytes("USAZBGAW");
        _provider = new TripleDESCryptoServiceProvider();
    }

    #region IStringEncryptor Members

    public string EncryptString(string plainText)
    {
        return Transform(plainText, _provider.CreateEncryptor(_key, _iv));
    }

    public string DecryptString(string encryptedText)
    {
        return Transform(encryptedText, _provider.CreateDecryptor(_key, _iv));
    }

    #endregion

    private string Transform(string text, ICryptoTransform transform)
    {
        if (text == null)
        {
            return null;
        }
        using (MemoryStream stream = new MemoryStream())
        {
            using (CryptoStream cryptoStream = new CryptoStream(stream, transform, CryptoStreamMode.Write))
            {
                byte[] input = Encoding.Default.GetBytes(text);
                cryptoStream.Write(input, 0, input.Length);
                cryptoStream.FlushFinalBlock();

                return Encoding.Default.GetString(stream.ToArray());
            }
        }
    }
}
Podes ver o meu vídeo e descarregar o código para isto em : http://www.wrightin.gs/2008/11/how-to-encryptdecrypt-sensitive-column-contents-in-nhibernateactive-record-video.html
 11
Author: Jamie Wright, 2008-11-07 14:31:40

Uma opção seria armazenar o hash (SHA1, MD5) da senha em vez da senha de texto claro, e sempre que quiser ver se a senha é boa, basta compará-la com esse hash.

Se você precisa de armazenamento seguro (por exemplo, para uma senha que você vai usar para se conectar a um serviço), então o problema é mais complicado.

Se for apenas para Autenticação, então seria suficiente usar o hash.

 10
Author: Bogdan Maxim, 2008-10-17 14:59:43

Se quiser ser capaz de descodificar a senha, acho que a maneira mais fácil seria usar o DPAPI (modo de armazenamento do utilizador) para cifrar/descodificar. Desta forma, você não tem que mexer com as chaves de criptografia, armazená-las em algum lugar ou código rígido em seu código - em ambos os casos alguém pode descobri-las olhando para o registro, configuração do usuário ou usando o refletor.

Caso contrário, use hashs SHA1 ou MD5 como outros disseram aqui.

 9
Author: liggett78, 2008-10-17 15:13:33
Como o ligget78 disse, o DPAPI seria uma boa forma de armazenar senhas. Verifique a classe ProtectedData no MSDN , por exemplo, a utilização.
 6
Author: Beau, 2011-03-02 19:54:26

Tom Scott acertou na sua cobertura de como (não) armazenar senhas, no computador.

Https://www.youtube.com/watch?v=8ZtInClXe1Q

  1. Se você pode evitá-lo, não tente armazenar senhas você mesmo. utilize uma plataforma de autenticação de utilizador separada, pré-estabelecida e fiável (por exemplo: fornecedores de OAuth, domínio de directório activo da sua empresa, etc.) Sim.

  2. Se você deve armazenar senhas, não siga nenhum de a orientação aqui. pelo menos, não sem consultar também publicações mais recentes e respeitáveis aplicáveis à sua língua de escolha.

Há muita gente inteligente aqui, e provavelmente até alguma boa orientação dada. Mas as chances são fortes de que, quando você ler isso, todas as respostas aqui (incluindo esta) já estarão desatualizadas.
A forma correcta de guardar as senhas muda ao longo do tempo.

provavelmente mais. frequentemente do que algumas pessoas trocam de roupa interior.


[[1] tudo o que disse, Aqui está uma orientação geral que esperamos permanecer útil por algum tempo.
  1. Não encriptar senhas. qualquer método de armazenamento que permita a recuperação dos dados armazenados é inerentemente inseguro para o propósito de manter senhas - todas as formas de criptografia incluídas.
  2. processar as senhas exactamente como foram introduzidas pelo utilizador durante a criação processo. Tudo o que fizer à senha antes de a enviar para o módulo de criptografia provavelmente irá enfraquecê-la. Fazer qualquer um dos seguintes também apenas adiciona complexidade ao processo de armazenamento e verificação de senha, o que poderia causar outros problemas (talvez até mesmo introduzir vulnerabilidades) ao longo da estrada.

    • Não converter para maiúsculas/minúsculas.
    • não remova espaços em branco.
    • Não tires caracteres ou cordas inaceitáveis.
  3. Não! muda a codificação de texto.
  4. não faças substituições de caracteres ou cadeias de caracteres.
  5. não truncem senhas de qualquer comprimento.
  6. rejeitar a criação de quaisquer senhas que não possam ser armazenadas sem modificação. reforçar o acima exposto. Se houver alguma razão para o seu mecanismo de armazenamento de senha não conseguir lidar adequadamente com certos caracteres, espaços em branco, strings, ou comprimentos de senha, em seguida, retornar um erro e deixar o usuário saber sobre o sistema limitações para que possam repetir com uma senha que se encaixe dentro delas. Para uma melhor experiência do usuário, faça uma lista dessas limitações acessível ao usuário imediatamente. Não se preocupe, quanto mais se preocupar, escondendo a lista de atacantes - eles vão descobrir facilmente o suficiente por conta própria de qualquer maneira.

  7. Use um longo, Aleatório e único sal para cada conta. as senhas de duas contas nunca devem ser as mesmas no armazenamento, mesmo que as senhas sejam realmente idêntico.
  8. Use algoritmos de hashing lentos e criptograficamente fortes que são projetados para uso com senhas. o MD5 está fora de questão. SHA-1 / SHA-2 não funciona. Mas não te vou dizer o que deves usar aqui também. (Veja a primeira bala número 2 Neste post.)
  9. iterar o máximo que puder tolerar. enquanto seu sistema pode ter coisas melhores para fazer com seus ciclos de processador do que senhas de hash o dia todo, as pessoas que vai estar a decifrar as suas senhas tem sistemas que não o fazem. torne-os o mais difíceis possível, sem o tornar "demasiado difícil" para si.

Mais importante... Não dês ouvidos a ninguém.

Vá procurar uma publicação respeitável e muito recente sobre os métodos adequados de armazenamento de senha para a sua língua de escolha. Na verdade, você deve encontrar várias publicações recentes de várias fontes separadas que estão de acordo antes de se estabelecer em um metodo.

É extremamente possível que tudo o que todos aqui disseram (incluindo eu) já tenha sido substituído por melhores tecnologias ou tornado inseguro por métodos de ataque recentemente desenvolvidos. Vai procurar algo que provavelmente não seja.
 6
Author: Iszi, 2016-07-12 16:32:15

Se é uma senha usada para autenticação pela sua aplicação, então anote a senha como os outros sugerem.

Se você está armazenando senhas para um recurso externo, muitas vezes você vai querer ser capaz de pedir ao Usuário para essas credenciais e dar-lhe a oportunidade de salvá-las de forma segura. O Windows fornece as credenciais UI (CredUI) para este fim - existem várias amostras que mostram como usar isto em.Net, incluindo este em MSDN.

 5
Author: Joe, 2008-10-17 17:21:49

Procurei por todo o lado por um bom exemplo de encriptação e processo de descodificação, mas a maioria era demasiado complexa.

De qualquer forma, há muitas razões para alguém querer decifrar alguns valores de texto, incluindo senhas. A razão pela qual eu preciso descriptografar a senha no site em que estou trabalhando atualmente é porque eles querem ter certeza de que quando alguém é forçado a mudar sua senha quando expirar que nós não os deixamos alterá-la com uma variante próxima da mesma senha que eles usaram em nos últimos x meses.

Então eu escrevi um processo que vai fazer isso de uma maneira simplificada. Espero que este código seja benéfico para alguém. Pelo que sei, posso acabar usando isso em outro momento para uma empresa/site diferente.
public string GenerateAPassKey(string passphrase)
    {
        // Pass Phrase can be any string
        string passPhrase = passphrase;
        // Salt Value can be any string(for simplicity use the same value as used for the pass phrase)
        string saltValue = passphrase;
        // Hash Algorithm can be "SHA1 or MD5"
        string hashAlgorithm = "SHA1";
        // Password Iterations can be any number
        int passwordIterations = 2;
        // Key Size can be 128,192 or 256
        int keySize = 256;
        // Convert Salt passphrase string to a Byte Array
        byte[] saltValueBytes = Encoding.ASCII.GetBytes(saltValue);
        // Using System.Security.Cryptography.PasswordDeriveBytes to create the Key
        PasswordDeriveBytes pdb = new PasswordDeriveBytes(passPhrase, saltValueBytes, hashAlgorithm, passwordIterations);
        //When creating a Key Byte array from the base64 string the Key must have 32 dimensions.
        byte[] Key = pdb.GetBytes(keySize / 11);
        String KeyString = Convert.ToBase64String(Key);

        return KeyString;
    }

 //Save the keystring some place like your database and use it to decrypt and encrypt
//any text string or text file etc. Make sure you dont lose it though.

 private static string Encrypt(string plainStr, string KeyString)        
    {            
        RijndaelManaged aesEncryption = new RijndaelManaged();
        aesEncryption.KeySize = 256;
        aesEncryption.BlockSize = 128;
        aesEncryption.Mode = CipherMode.ECB;
        aesEncryption.Padding = PaddingMode.ISO10126;
        byte[] KeyInBytes = Encoding.UTF8.GetBytes(KeyString);
        aesEncryption.Key = KeyInBytes;
        byte[] plainText = ASCIIEncoding.UTF8.GetBytes(plainStr);
        ICryptoTransform crypto = aesEncryption.CreateEncryptor();
        byte[] cipherText = crypto.TransformFinalBlock(plainText, 0, plainText.Length);
        return Convert.ToBase64String(cipherText);
    }

 private static string Decrypt(string encryptedText, string KeyString) 
    {
        RijndaelManaged aesEncryption = new RijndaelManaged(); 
        aesEncryption.KeySize = 256;
        aesEncryption.BlockSize = 128; 
        aesEncryption.Mode = CipherMode.ECB;
        aesEncryption.Padding = PaddingMode.ISO10126;
        byte[] KeyInBytes = Encoding.UTF8.GetBytes(KeyString);
        aesEncryption.Key = KeyInBytes;
        ICryptoTransform decrypto = aesEncryption.CreateDecryptor(); 
        byte[] encryptedBytes = Convert.FromBase64CharArray(encryptedText.ToCharArray(), 0, encryptedText.Length); 
        return ASCIIEncoding.UTF8.GetString(decrypto.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length)); 
    }

 String KeyString = GenerateAPassKey("PassKey");
 String EncryptedPassword = Encrypt("25Characterlengthpassword!", KeyString);
 String DecryptedPassword = Decrypt(EncryptedPassword, KeyString);
 4
Author: Deathstalker, 2011-05-27 21:18:08

Se precisar de mais do que isto, por exemplo, a segurança de um texto de ligação (para a ligação a uma base de dados), assinale este Artigo, Uma vez que oferece a melhor "opção" para isto.

A resposta do Oli também é boa, pois mostra como você pode criar um hash para uma string.

 1
Author: Bogdan Maxim, 2008-10-17 15:06:47
A NET presta serviços de criptografia de classe Sistema.Seguranca.Espaço de nomes de criptografia.
 0
Author: osp70, 2008-10-17 15:02:36

Em vez de cifrar/descodificar, deverá passar a senha através de um algoritmo de hashing, md5/sha512, ou similar. O que você faria idealmente é usar hash na senha e armazenar o hash, então quando a senha é necessária, você usa hash no item e compara os itens. Uma senha nunca será "descriptografada", simplesmente hashed e depois comparada.

 -1
Author: Jeremy B., 2008-10-17 15:01:09