Pergunta

Qual é o seu método/tipo de dados preferido para armazenar senhas em um banco de dados (de preferência SQL Server 2005). A maneira como tenho feito isso em vários de nossos aplicativos é usar primeiro as bibliotecas de criptografia .NET e depois armazená -las no banco de dados como binário (16). Esse é o método preferido ou devo usar um tipo de dados diferente ou alocar mais espaço do que 16?

Foi útil?

Solução

Eu armazenei o equivalente a hash salgado da senha no banco de dados e nunca a própria senha, sempre comparo o hash com o gerado do que o usuário passou.

É muito perigoso armazenar os dados de senha literal em qualquer lugar. Isso impossibilita a recuperação, mas quando alguém esquece ou perde uma senha, você pode executar algumas verificações e criar uma nova senha.

Outras dicas

O método preferido: nunca armazene senhas em seu banco de dados. Apenas hashes dos mesmos. Adicione sal a gosto.

Eu faço a mesma coisa que você descreveu, exceto que é armazenada como uma string. I base64 codifica o valor binário criptografado. A quantidade de espaço para alocar depende do algoritmo de criptografia/força da cifra.

Eu acho que você está fazendo certo (dado que você usa um Sal).

  1. Armazene o hash da palavra-saltada, como o BCRYPT (NOWN+PWD). Você pode preferir o BCRYPT a SHA1 ou MD5, porque ele pode ser sintonizado para ter o ataque com a CPU, tornando-se assim um ataque de força bruta por mais tempo.
  2. Adicione um captcha ao formulário de login após alguns erros de login (para evitar ataques de força bruta)
  3. Se o seu aplicativo tiver um link "Esquecer minha senha", verifique se não envia a nova senha por e -mail, mas deve enviar um link para uma página (segura), permitindo ao usuário definir uma nova senha (possivelmente apenas após a confirmação de algumas informações pessoais, como a data de nascimento do usuário, por exemplo). Além disso, se o seu aplicativo permitir ao usuário definir uma nova senha, verifique se você exige que o usuário confirme a senha atual.
  4. E, obviamente, proteja o formulário de login (normalmente com https) e os próprios servidores

Com essas medidas, as senhas do seu usuário serão bastante bem protegidas contra:

  1. => ataques de dicionário offline
  2. => ataques ao vivo do dicionário
  3. => Ataques de negação de serviço
  4. => Todos os tipos de ataques!

Como o resultado de uma função de hash é uma série de byte na faixa de 0 a 255 (ou -128 a 127, dependendo da assinatura do seu tipo de dados de 8 bits), armazená-lo como um campo binário bruto faz com que mais sentido , como é a representação mais compacta e não requer etapas adicionais de codificação e decodificação.

Alguns bancos de dados ou drivers não têm um ótimo suporte para tipos de dados binários, ou às vezes os desenvolvedores simplesmente não estão familiarizados com eles para se sentirem confortáveis. Nesse caso, o uso de uma codificação binária a texto como base-64 ou base-85 e armazenamento do texto resultante em um campo de caracteres é aceitável.

O tamanho do campo necessário é determinado pela função de hash que você usa. O MD5 sempre produz 16 bytes, o SHA-1 sempre produz 20 bytes. Depois de selecionar uma função de hash, geralmente você está preso a ela, pois a mudança requer uma redefinição de todas as senhas existentes. Portanto, usar um campo de tamanho variável não compra nada para você.


Em relação à "melhor" maneira de realizar o hash, tentei fornecer muitas respostas a outras perguntas sobre esse tópico:

Eu uso o hash sha do nome de usuário, um GUID na configuração da web e a senha, armazenada como Varchar (40). Se eles desejam força / dicionário bruto, precisarão invadir o servidor da Web para o GUID também. O nome de usuário quebra a criação de uma tabela de arco -íris em todo o banco de dados se encontrar a senha. Se um usuário deseja alterar seu nome de usuário, apenas redefini a senha ao mesmo tempo.

System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(
    username.ToLower().Trim(),
    ConfigurationManager.AppSettings("salt"),
    password
);

Um hash simples da senha, ou mesmo (SALT + senha) geralmente não é adequado.

Vejo:

http://www.matasano.com/log/958/enough-with-the-rainbow-tables-what-you-need-to-now-about-secure-sassword-schemes/

e

http://gom-jabbar.org/articles/2008/12/03/why-you-hould-use-bcrypt-to-store-your-passwords

Ambos recomendam os algoritmos BCRYPT. As implementações gratuitas podem ser encontradas on -line para os idiomas mais populares.

Você pode usar vários hashes no seu banco de dados, ele requer um pouco de esforço extra. Vale a pena embora, se você acha que há a mais remota chance, precisará suportar formatos adicionais no futuro. Frequentemente usarei entradas de senha como

{hashid} $ {sal} $ {hashed senha}

Onde "Hashid" é apenas algum número que eu uso internamente para reconhecer isso, por exemplo, estou usando o SHA1 com um padrão de hash específico; "Salt" é um sal aleatório codificado por 64; e "Hashed senha" é um hash codificado de base64. Se você precisar migrar hashes, poderá interceptar as pessoas com um formato de senha antigo e fazê -las alterar sua senha na próxima vez em que fizer login.

Como outros mencionaram, você quer ter cuidado com seus hashes, pois é fácil fazer algo que não é realmente seguro, por exemplo, H (sal, senha) é muito mais fraco que H (senha, sal), mas ao mesmo tempo você deseja Equilibre o esforço colocado nisso com o valor do conteúdo do site. Muitas vezes, uso h (h (senha, sal), senha).

Finalmente, o custo do uso de senhas codificadas por Base64 é modesto quando comparado aos benefícios de poder usar várias ferramentas que esperam dados de texto. Sim, eles devem ser mais flexíveis, mas você está pronto para dizer ao seu chefe que ele não pode usar sua ferramenta favorita de terceiros, porque deseja economizar alguns bytes por registro? :-)

Editado para adicionar outro comentário: se eu sugerisse deliberadamente usar um algoritmo que queimou até 1/10 de segundo hash de cada senha, teria sorte de ser ridicularizado no escritório do meu chefe. (Não tem tanta sorte? Ele anotaria algo para discutir na minha próxima revisão anual.) Queimar esse tempo não é um problema quando você tem dezenas, ou mesmo centenas de usuários. Se você estiver pressionando 100k usuários, geralmente terá várias pessoas fazendo login ao mesmo tempo. Você precisa de algo rápido e forte, não lento e forte. "Mas e as informações do cartão de crédito?" é falso, na melhor das hipóteses, já que as informações de cartão de crédito armazenadas não devem estar perto do seu banco de dados regulares e seriam criptografadas pelo aplicativo de qualquer maneira, não por usuários individuais.

Se você estiver trabalhando com o ASP.NET, poderá usar a API de associação embutida.

Ele suporta muitos tipos de opções de armazenamento, incluindo; Hash de uma maneira, criptografia bidirecional, md5 + sal. http://www.asp.net/learn/security para mais informações.

Se você não precisa de nada muito chique, isso é ótimo para sites.

Se você não está usando asp.net aqui está um bom link para alguns artigos de 4Guys e CodeProject

http://aspnet.4guysfromrolla.com/articles/081705-1.aspx http://aspnet.4guysfromrolla.com/articles/103002-1.aspx http://www.codeproject.com/kb/security/simpleEncrypion.aspx

Como sua pergunta é sobre método e tamanho de armazenamento, abordarei isso.

O tipo de armazenamento pode ser uma representação binária ou de texto (Base64 é a mais comum). O binário é menor, mas acho mais fácil trabalhar com texto. Se você estiver fazendo por salga de usuário (salto diferente por senha), é mais fácil armazenar Salt+Hash como uma única corda combinada.

O tamanho é dependente do algoritmo de hash. A saída do MD5 é sempre 16 bytes, o SHA1 é sempre 20 bytes. SHA-256 e SHA-512 são 32 e 64 bytes, respectivamente. Se você estiver usando a codificação de texto, precisará de um pouco mais de armazenamento, dependendo do método de codificação. Costumo usar a base64 porque o armazenamento é relativamente barato. Base64 exigirá aproximadamente 33% de campo maior.

Se você tiver salga por usuário, também precisará de espaço para o hash. Juntando tudo de 64 bits de sal + sha1 hash (160 bits) base64 codificado leva 40 caracteres, então eu o guardo como char (40).

Por fim, se você quiser fazer isso corretamente, não deve usar um único hash, mas uma função de derivação -chave como RBKDF2. Os hashes sha1 e md5 são incrivelmente rápidos. Mesmo um único aplicativo rosqueado pode hash cerca de 30k a 50k senhas por segundo, que até 200 mil senhas por segundo na máquina quad core. As GPUs podem hash 100x a 1000x quantas senhas por segundo. Com velocidades como o ataque de força bruta se torna um método de intrusão aceitável. O RBKDF2 permite especificar o número de iterações para ajustar o quão "lento" é o seu hash. O ponto não é trazer o sistema de joelhos, mas escolher várias iterações para que você limite o limite superior da taxa de transferência de hash (digamos 500 hashes por segundo). Um método de prova futura seria incluir o número de iterações no campo Senha (iterações + sal + hash). Isso permitiria que o aumento das iterações no futuro acompanhasse os processadores mais poderosos. Para ser ainda mais flexível, use varchar para permitir hashes potencialmente maiores/alternativos no futuro.

A implementação do .NET é RFC2892DeriveByteshttp://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes.aspx

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top