Diz-se atualmente que o MD5 é parcialmente inseguro. Levando isso em consideração, gostaria de saber qual mecanismo usar para proteção de senha.
Esta pergunta, o "hash duplo" é uma senha menos segura do que apenas uma vez? sugere que o hash várias vezes pode ser uma boa ideia, enquanto Como implementar a proteção por senha para arquivos individuais? sugere o uso de sal.
Estou usando PHP. Eu quero um sistema de criptografia de senha seguro e rápido. Hashing de uma senha um milhão de vezes pode ser mais seguro, mas também mais lento. Como conseguir um bom equilíbrio entre velocidade e segurança? Além disso, eu prefiro que o resultado tenha um número constante de caracteres.
- O mecanismo de hash deve estar disponível em PHP
- Deve ser seguro
- Ele pode usar sal (neste caso, todos os sais são igualmente bons? Existe alguma maneira de gerar bons sais?)
Além disso, devo armazenar dois campos no banco de dados (um usando MD5 e outro usando SHA, por exemplo)? Tornaria mais seguro ou não seguro?
Caso eu não tenha sido claro o suficiente, quero saber quais funções de hash usar e como escolher um bom sal para ter um mecanismo de proteção por senha rápido e seguro.
Perguntas relacionadas que não cobrem completamente minha pergunta:
Qual é a diferença entre SHA e MD5 no PHP
Simple Password Encryption
Métodos seguros de armazenamento de chaves, senhas para o asp.net
Como você implementaria senhas salgadas no Tomcat 5.5
Respostas:
TL; DR
Não é
\0
, o que pode enfraquecer seriamente a segurança.)Dos
Por que senhas hash, afinal?
O objetivo por trás do hash de senhas é simples: impedir o acesso malicioso a contas de usuários comprometendo o banco de dados. Portanto, o objetivo do hash de senha é impedir um hacker ou cracker, gastando muito tempo ou dinheiro para calcular as senhas em texto simples. E tempo / custo são os melhores impedimentos em seu arsenal.
Outro motivo pelo qual você deseja um hash bom e robusto nas contas de usuário é dar a você tempo suficiente para alterar todas as senhas no sistema. Se seu banco de dados estiver comprometido, você precisará de tempo suficiente para pelo menos bloquear o sistema, se não alterar todas as senhas no banco de dados.
Jeremiah Grossman, CTO da Whitehat Security, declarou no blog White Hat Security após uma recente recuperação de senha que exigia a quebra de força bruta de sua proteção por senha:
(Ênfase minha.)
O que faz uma boa senha, afinal?
Entropia . (Não que eu assine totalmente o ponto de vista de Randall.)
Em resumo, entropia é quanta variação existe dentro da senha. Quando uma senha é apenas letras romanas em minúsculas, são apenas 26 caracteres. Isso não é muita variação. As senhas alfanuméricas são melhores, com 36 caracteres. Mas permitir maiúsculas e minúsculas, com símbolos, tem aproximadamente 96 caracteres. Isso é muito melhor do que apenas letras. Um problema é que, para tornar nossas senhas memoráveis, inserimos padrões - o que reduz a entropia. Opa!
A entropia de senha é aproximada facilmente. O uso de toda a gama de caracteres ascii (aproximadamente 96 caracteres digitáveis) gera uma entropia de 6,6 por caractere, que com 8 caracteres para uma senha ainda é muito baixa (52,679 bits de entropia) para segurança futura. Mas a boa notícia é: senhas mais longas e senhas com caracteres unicode aumentam realmente a entropia de uma senha e dificultam a quebra.
Há uma discussão mais longa sobre entropia de senha no site Crypto StackExchange . Uma boa pesquisa no Google também gera muitos resultados.
Nos comentários, conversei com o @popnoodles, que apontou que a imposição de uma política de senha com comprimento X com X muitas letras, números, símbolos etc. pode reduzir a entropia, na verdade, tornando o esquema de senha mais previsível. Eu concordo. A aleatoriedade, o mais aleatória possível, é sempre a solução mais segura, mas menos memorável.
Até onde eu sei, criar a melhor senha do mundo é um Catch-22. Não é memorável, previsível, muito curto, caracteres unicode demais (difíceis de digitar em um dispositivo Windows / Mobile), muito longo, etc. Nenhuma senha é realmente boa o suficiente para nossos propósitos, portanto, devemos protegê-los como se eles fossem estavam em Fort Knox.
Melhores Práticas
Bcrypt e scrypt são as melhores práticas atuais. O Scrypt será melhor do que o bcrypt a tempo, mas ainda não viu a adoção como padrão pelo Linux / Unix ou pelos servidores da web e ainda não teve análises detalhadas de seu algoritmo publicadas. Mas, ainda assim, o futuro do algoritmo parece promissor. Se você estiver trabalhando com Ruby, há uma gema scrypt que o ajudará, e o Node.js agora tem seu próprio pacote scrypt . Você pode usar o Scrypt no PHP via extensão Scrypt ou Libsodium (ambas estão disponíveis no PECL).
Eu recomendo a leitura da documentação para a função crypt, se você quiser entender como usar o bcrypt, encontrar um bom wrapper ou usar algo como PHPASS para uma implementação mais antiga . Eu recomendo um mínimo de 12 rodadas de bcrypt, se não 15 a 18.
Mudei de idéia sobre o uso do bcrypt quando soube que o bcrypt usa apenas o cronograma de chaves do blowfish, com um mecanismo de custo variável. O último permite aumentar o custo da força bruta de uma senha, aumentando a agenda de chaves já dispendiosa do blowfish.
Práticas médias
Quase não consigo mais imaginar essa situação. O PHPASS suporta PHP 3.0.18 a 5.3, portanto é utilizável em quase todas as instalações imagináveis - e deve ser usado se você não tiver certeza de que seu ambiente suporta bcrypt.
Mas suponha que você não possa usar bcrypt ou PHPASS. O que então?
Tente uma implementação do PDKBF2 com o número máximo de rodadas que seu ambiente / aplicativo / percepção do usuário pode tolerar. O número mais baixo que eu recomendo é 2500 rodadas. Além disso, certifique-se de usar hash_hmac () se estiver disponível para dificultar a reprodução da operação.
Práticas Futuras
O PHP 5.5 é uma biblioteca completa de proteção por senha que abstrai qualquer esforço de trabalhar com o bcrypt. Enquanto a maioria de nós está presa ao PHP 5.2 e 5.3 nos ambientes mais comuns, especialmente em hosts compartilhados, o @ircmaxell criou uma camada de compatibilidade para a próxima API que é compatível com versões anteriores ao PHP 5.3.7.
Recapitulação e isenção de responsabilidade de criptografia
O poder computacional necessário para realmente quebrar uma senha com hash não existe. A única maneira de os computadores "violarem" uma senha é recriá-la e simular o algoritmo de hash usado para protegê-la. A velocidade do hash está linearmente relacionada à sua capacidade de ser forçada a bruto. Pior ainda, a maioria dos algoritmos de hash pode ser facilmente paralelizada para ter um desempenho ainda mais rápido. É por isso que esquemas caros como bcrypt e scrypt são tão importantes.
Você não pode prever todas as ameaças ou vias de ataque e, portanto, deve se esforçar ao máximo para proteger seus usuários com antecedência . Se não o fizer, pode até perder o fato de ter sido atacado até que seja tarde demais ... e você é responsável . Para evitar essa situação, aja de paranóico para começar. Ataque seu próprio software (internamente) e tente roubar credenciais do usuário, ou modificar as contas de outros usuários ou acessar seus dados. Se você não testar a segurança do seu sistema, não poderá culpar ninguém além de si mesmo.
Por fim: eu não sou um criptógrafo. Tudo o que eu disse é a minha opinião, mas acho que é baseado no bom e velho senso comum ... e muita leitura. Lembre-se, seja o mais paranóico possível, torne as coisas o mais difíceis de se intrometer possível e, em seguida, se você ainda estiver preocupado, entre em contato com um hacker de chapéu branco ou criptógrafo para ver o que eles dizem sobre seu código / sistema.
fonte
Uma resposta muito mais curta e segura - não escreva seu próprio mecanismo de senha , use um mecanismo testado e comprovado.
A maioria dos programadores simplesmente não tem o conhecimento necessário para escrever códigos relacionados a criptografia com segurança, sem introduzir vulnerabilidades.
Autoteste rápido: o que é o alongamento de senha e quantas iterações você deve usar? Se você não souber a resposta, deve usar
password_hash()
, pois o alongamento de senha agora é um recurso crítico dos mecanismos de senha devido a CPUs muito mais rápidas e o uso de GPUs e FPGAs para quebrar senhas a taxas de bilhões de palpites por segundo (com GPUs )Por exemplo, você pode decifrar todas as senhas do Windows de 8 caracteres em 6 horas usando 25 GPUs instaladas em 5 PCs de mesa. Isso é forçante, ou seja, enumerar e verificar cada senha do Windows de 8 caracteres , incluindo caracteres especiais, e não é um ataque de dicionário. Isso foi em 2012, a partir de 2018, você poderia usar menos GPUs ou quebrar mais rapidamente com 25 GPUs.
Também existem muitos ataques de tabelas do arco-íris às senhas do Windows que são executadas em CPUs comuns e são muito rápidas. Tudo isso ocorre porque o Windows ainda não modifica suas senhas, mesmo no Windows 10 - não cometa o mesmo erro da Microsoft!
Veja também:
password_hash()
ouphpass
o melhor caminho a percorrer.fonte
Eu não armazenaria o hash da senha de duas maneiras diferentes, porque o sistema é pelo menos tão fraco quanto o mais fraco dos algoritmos de hash em uso.
fonte
A partir do PHP 5.5, o PHP possui funções simples e seguras para hash e verificação de senhas, password_hash () e password_verify ()
Quando
password_hash()
é usado, ele gera um sal aleatório e o inclui no hash emitido (junto com o custo e o algoritmo usado.), Empassword_verify()
seguida, lê esse hash e determina o método de criptografia e sal usado e o verifica com a senha de texto sem formatação fornecida.Fornecendo o
PASSWORD_DEFAULT
instruções ao PHP para usar o algoritmo de hash padrão da versão instalada do PHP. Exatamente qual algoritmo significa mudar com o tempo em versões futuras, para que ele sempre seja um dos algoritmos mais fortes disponíveis.O aumento do custo (cujo padrão é 10) dificulta a força bruta, mas também significa gerar hashes e verificar senhas contra eles, além de ser mais trabalhoso para a CPU do servidor.
Observe que, embora o algoritmo de hash padrão possa ser alterado, os hashes antigos continuarão a ser verificados, porque o algoritmo usado é armazenado no hash e o
password_verify()
pega.fonte
Embora a pergunta tenha sido respondida, quero apenas reiterar que os sais usados no hash devem ser aleatórios e não como o endereço de e-mail sugerido na primeira resposta.
Mais explicações estão disponíveis em http://www.pivotalsecurity.com/blog/password-hashing-salt-should-it-be-random/
fonte
Eu só quero ressaltar que o PHP 5.5 inclui uma API de hash de senha que fornece um invólucro
crypt()
. Essa API simplifica significativamente a tarefa de hash, verificação e rehashing de hashes de senha. O autor também lançou um pacote de compatibilidade (na forma de um único arquivo password.php que você simplesmenterequire
usa), para aqueles que usam o PHP 5.3.7 e posterior e desejam usá-lo agora.Ele suporta apenas o BCRYPT por enquanto, mas pretende ser facilmente estendido para incluir outras técnicas de hash de senha e, como a técnica e o custo são armazenados como parte do hash, as alterações na sua técnica / custo preferencial não invalidarão os hashes atuais. automagicamente, use a técnica / custo corretos ao validar. Ele também controla a geração de um sal "seguro" se você não definir explicitamente o seu próprio.
A API expõe quatro funções:
password_get_info()
- retorna informações sobre o hash especificadopassword_hash()
- cria um hash de senhapassword_needs_rehash()
- verifica se o hash fornecido corresponde às opções fornecidas. Útil para verificar se o hash está em conformidade com o seu esquema atual de técnica / custo, permitindo que você refaça o procedimento se necessáriopassword_verify()
- verifica se uma senha corresponde a um hashNo momento, essas funções aceitam as constantes de senha PASSWORD_BCRYPT e PASSWORD_DEFAULT, que são sinônimos no momento, a diferença é que PASSWORD_DEFAULT "pode mudar nas versões mais recentes do PHP quando novos algoritmos de hash mais fortes são suportados". O uso de PASSWORD_DEFAULT e password_needs_rehash () no logon (e rehashing se necessário) deve garantir que seus hashes sejam razoavelmente resistentes a ataques de força bruta com pouco ou nenhum trabalho para você.
Edição: Acabei de perceber que isso é mencionado brevemente na resposta de Robert K. Deixarei essa resposta aqui, pois acho que fornece um pouco mais de informações sobre como funciona e a facilidade de uso que fornece para quem não conhece a segurança.
fonte
Estou usando o Phpass, que é uma classe PHP de um arquivo simples que pode ser implementada com muita facilidade em quase todos os projetos PHP. Ver também O H .
Por padrão, ele usava a criptografia disponível mais forte, implementada no Phpass, que
bcrypt
remonta a outras criptografias no MD5 para fornecer compatibilidade com versões anteriores para estruturas como o Wordpress.O hash retornado pode ser armazenado no banco de dados como está. O uso de amostra para gerar hash é:
Para verificar a senha, pode-se usar:
fonte
COISAS PARA LEMBRAR
Muito foi dito sobre a criptografia de senha para PHP, a maioria das quais é um conselho muito bom, mas antes mesmo de iniciar o processo de uso do PHP para criptografia de senha, verifique se você tem o seguinte implementado ou pronto para ser implementado.
SERVIDOR
PORTOS
Não importa quão boa seja sua criptografia, se você não proteger adequadamente o servidor que executa o PHP e o DB, todos os seus esforços serão inúteis. A maioria dos servidores funciona relativamente da mesma maneira, eles têm portas designadas para permitir que você os acesse remotamente através de ftp ou shell. Certifique-se de alterar a porta padrão em que a conexão remota está ativa. Ao não fazer isso, você efetivamente fez com que o invasor fizesse uma etapa a menos no acesso ao seu sistema.
NOME DO USUÁRIO
Por tudo que é bom no mundo, não use o nome de usuário admin, root ou algo semelhante. Além disso, se você estiver em um sistema baseado em unix, NÃO torne o login da conta raiz acessível, ele deve sempre ser apenas sudo.
SENHA
Você diz aos usuários para criar boas senhas para evitar serem invadidos, faça o mesmo. Qual é o sentido de passar por todo o esforço de trancar a porta da frente quando você tem a porta dos fundos aberta?
BASE DE DADOS
SERVIDOR
Idealmente, você deseja seu DB e APPLICATION em servidores separados. Isso nem sempre é possível devido ao custo, mas permite alguma segurança, pois o invasor precisará executar duas etapas para acessar totalmente o sistema.
DO UTILIZADOR
Sempre faça com que seu aplicativo tenha sua própria conta para acessar o banco de dados e dê apenas os privilégios necessários.
Em seguida, tenha uma conta de usuário separada para você que não esteja armazenada em nenhum lugar do servidor, nem mesmo no aplicativo.
Como sempre, NÃO crie essa raiz ou algo semelhante.
SENHA
Siga as mesmas diretrizes de todas as boas senhas. Além disso, não reutilize a mesma senha em nenhuma conta SERVER ou DB no mesmo sistema.
PHP
SENHA
NUNCA armazene uma senha no seu banco de dados, em vez disso, armazene o hash e o sal exclusivo, explicarei por que mais tarde.
HASHING
HASHING DE UMA MANEIRA !!!!!!!, Nunca use uma senha com hash de uma maneira que possa ser revertida; os hashes devem ser de uma maneira, o que significa que você não os reverterá e os comparará com a senha, mas sim a senha digitada. da mesma maneira e compare os dois hashes. Isso significa que, mesmo que um invasor obtenha acesso ao banco de dados, ele não sabe qual é realmente a senha, apenas o hash resultante. O que significa mais segurança para seus usuários no pior cenário possível.
Há um monte de bons funções hash lá fora (
password_hash
,hash
, etc ...), mas você precisa selecionar um bom algoritmo para o hash para ser eficaz. (bcrypt e similares a ele são algoritmos decentes).Quando a velocidade do hash é a chave, quanto mais lento, mais resistente aos ataques da Força Bruta.
Um dos erros mais comuns no hash é que os hashes não são exclusivos dos usuários. Isso ocorre principalmente porque os sais não são gerados exclusivamente.
SALGA
As senhas sempre devem ser salgadas antes do hash. Salting adiciona uma sequência aleatória à senha para que senhas semelhantes não apareçam iguais no banco de dados. No entanto, se o sal não for exclusivo de cada usuário (ou seja: você usa um sal codificado), você praticamente o tornará inútil. Porque uma vez que um invasor descobre um sal de senha, ele tem sal para todos eles.
Ao criar um salt, verifique se ele é exclusivo da senha que está salgando e, em seguida, armazene o hash e o sal completos no seu DB. O que isso fará é fazer com que um invasor precise quebrar individualmente cada sal e hash antes de obter acesso. Isso significa muito mais trabalho e tempo para o invasor.
USUÁRIOS QUE CRIAM SENHAS
Se o usuário estiver criando uma senha pelo frontend, isso significa que ela deve ser enviada ao servidor. Isso abre um problema de segurança, porque isso significa que a senha não criptografada está sendo enviada para o servidor e, se um invasor puder ouvir e acessar, toda a sua segurança no PHP é inútil. SEMPRE transmita os dados com SEGURANÇA, isso é feito via SSL, mas fique cansado, mesmo o SSL não é perfeito (a falha Heartbleed do OpenSSL é um exemplo disso).
Também faça o usuário criar uma senha segura, é simples e sempre deve ser feita, o usuário será grato por isso no final.
Por fim, independentemente das medidas de segurança adotadas, 100% de segurança, quanto mais avançada a tecnologia a ser protegida, mais avançados os ataques. Mas seguir estas etapas tornará seu site mais seguro e muito menos desejável para os invasores.
Aqui está uma classe PHP que cria um hash e salt para uma senha facilmente
http://git.io/mSJqpw
fonte
O Google diz que o SHA256 está disponível para PHP.
Você definitivamente deveria usar sal. Eu recomendo o uso de bytes aleatórios (e não se limite a caracteres e números). Como de costume, quanto mais tempo você escolher, mais seguro e mais lento fica. 64 bytes devem estar bem, eu acho.
fonte
No final, o hash duplo, matematicamente, não oferece nenhum benefício. Na prática, no entanto, é útil para impedir ataques baseados em tabelas do arco-íris. Em outras palavras, não é mais benéfico do que fazer hash com sal, o que leva muito menos tempo do processador em seu aplicativo ou em seu servidor.
fonte
Encontrei o tópico perfeito sobre esse assunto aqui: https://crackstation.net/hashing-security.htm , queria que você se beneficiasse, aqui está o código-fonte que também previa contra ataques baseados em tempo.
fonte
Normalmente, uso SHA1 e salt com o ID do usuário (ou alguma outra informação específica do usuário) e, às vezes, uso adicionalmente um sal constante (por isso tenho 2 partes para o sal).
O SHA1 agora também é considerado um pouco comprometido, mas em um grau muito menor que o MD5. Ao usar um sal (qualquer sal), você está impedindo o uso de uma tabela arco-íris genérica para atacar seus hashes (algumas pessoas tiveram sucesso usando o Google como uma espécie de tabela arco-íris pesquisando o hash). É possível que um invasor gere uma tabela de arco-íris usando o seu salt; é por isso que você deve incluir um sal específico do usuário. Dessa forma, eles terão que gerar uma tabela arco-íris para todos os registros do sistema, não apenas uma para todo o sistema! Com esse tipo de salga, até o MD5 é decentemente seguro.
fonte
SHA1 e um sal devem ser suficientes (dependendo, naturalmente, se você está codificando algo para Fort Knox ou um sistema de login para sua lista de compras) no futuro próximo. Se o SHA1 não for bom o suficiente para você, use o SHA256 .
A idéia de um sal é desequilibrar os resultados do hash, por assim dizer. Sabe-se, por exemplo, que o hash MD5 de uma sequência vazia é
d41d8cd98f00b204e9800998ecf8427e
. Portanto, se alguém com uma memória boa o suficiente ver esse hash e saber que é o hash de uma string vazia. Mas se a string for salgada (digamos, com a string "MY_PERSONAL_SALT
"), o hash da 'string vazia' (ou seja, "MY_PERSONAL_SALT
") se tornaráaeac2612626724592271634fb14d3ea6
, portanto, não óbvio para voltar atrás. O que eu estou tentando dizer, que é melhor usar qualquer sal, do que não. Portanto, não é muito importante saber qual sal usar.Na verdade, existem sites que fazem exatamente isso - você pode alimentá-lo com um hash (md5) e ele gera um texto simples conhecido que gera esse hash específico. Se você obtivesse acesso a um banco de dados que armazena hash md5 simples, seria fácil inserir o hash do administrador para esse serviço e efetuar login. Mas, se as senhas fossem salgadas, esse serviço se tornaria ineficaz.
Além disso, o hash duplo é geralmente considerado um método ruim, porque diminui o espaço de resultado. Todos os hashes populares são de comprimento fixo. Assim, você pode ter apenas valores finitos desse comprimento fixo e os resultados se tornam menos variados. Isso pode ser considerado como outra forma de salga, mas eu não recomendaria.
fonte
sha1(sha1($foo))
reduz efetivamente o espaço de saída, porque qualquer colisão da função interna se tornará automaticamente uma colisão da externa. A degradação é linear, mas ainda é uma preocupação. Os métodos iterativos de hash retornam dados a cada rodada, como$hash = sha1(sha1($salt . $password) . $salt)
. Mas isso ainda não é bom ... Stick with PBKDF2 ou Bcrypt ...ok no instável precisamos de sal, sal deve ser único, então vamos gerá-lo
também precisamos do hash que estou usando sha512 é o melhor e está em php
agora podemos usar essas funções para gerar senha segura
agora precisamos salvar no banco de dados nosso valor variável $ hash_psw e variável $ salt
e para autorizar, usaremos as mesmas etapas ...
é a melhor maneira de proteger as senhas de nossos clientes ...
Ps nos últimos 2 passos, você pode usar seu próprio algoritmo ... mas certifique-se de poder gerar essa senha com hash no futuro quando precisar autorizar o usuário ...
fonte
sha512
(mesmo que salgada) é amplamente considerada como insuficiente para proteção de senha. (também que o RNG não é criptograficamente seguro, portanto, usá-lo para geração de senha é arriscado).