Pergunta

Atualmente diz-se que o MD5 é parcialmente inseguro.Levando isso em consideração, gostaria de saber qual mecanismo usar para proteção por senha.

Essa questão, O “hashing duplo” é uma senha menos segura do que apenas fazer hash uma vez? sugere que fazer hash múltiplas vezes pode ser uma boa ideia, enquanto Como implementar proteção por senha para arquivos individuais? sugere usar sal.

Estou usando PHP.Quero um sistema de criptografia de senha seguro e rápido.Hashing 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, prefiro que o resultado tenha um número constante de caracteres.

  1. O mecanismo de hash deve estar disponível em PHP
  2. Deve ser seguro
  3. 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)?Isso o tornaria mais seguro ou inseguro?

Caso 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 seguro e rápido.

Perguntas relacionadas que não cobrem minha pergunta:

Qual é a diferença entre SHA e MD5 em PHP
Criptografia de senha simples
Métodos seguros de armazenamento de chaves e senhas para asp.net
Como você implementaria senhas salgadas no Tomcat 5.5

Foi útil?

Solução

AVISO LEGAL: Esta resposta foi escrita em 2008.

Desde então, o PHP nos deu password_hash e password_verify E, desde a sua introdução, eles são o método recomendado de hash de senha e verificação.

A teoria da resposta ainda é uma boa leitura.

Tl; dr

Não é

  • Não limite o que os usuários dos personagens podem inserir para senhas. Apenas idiotas fazem isso.
  • Não limite a duração de uma senha. Se seus usuários desejam uma frase com supercalifragilisticexpialidocious, não os impeça de usá -la.
  • Nunca armazene a senha do seu usuário em texto simples.
  • Nunca envie um e -mail para uma senha para o seu usuário Exceto quando eles perderam o deles, e você enviou um temporário.
  • Nunca, jamais registre senhas de qualquer maneira.
  • Nunca hash senhas com SHA1 ou MD5 ou mesmo SHA256! Brackers modernos pode exceder 60 e 180 bilhões de hashes/segundo (respectivamente).
  • Não misture bcrypt e com o cru saída de hash (), use saída hexadecimal ou base64_encode It. (Isso se aplica a qualquer entrada que possa ter um ladino \0 nele, o que pode enfraquecer seriamente a segurança.)

Dos

  • Use Scrypt quando puder; BCRYPT se você não puder.
  • Use PBKDF2 se você não puder usar BCRYPT ou SCRYPT, com hashes sha2.
  • Redefina as senhas de todos quando o banco de dados estiver comprometido.
  • Implementar um comprimento mínimo razoável de 8 a 10 caracteres, além de requer pelo menos 1 letra superior, 1 letra minúscula, um número e um símbolo. Isso melhorará a entropia da senha, tornando mais difícil de quebrar. (Veja a seção "O que faz uma boa senha?" Para algum debate.)

Por que as senhas de hash de qualquer maneira?

O objetivo por trás das senhas de hash é simples: impedir o acesso malicioso às contas de usuário comprometendo o banco de dados. Portanto, o objetivo do hash de senha é impedir um hacker ou cracker, custando muito tempo ou dinheiro para calcular as senhas de texto simples. E tempo/custo são os melhores impedimentos do seu arsenal.

Outro motivo pelo qual você deseja um hash bom e robusto em uma conta de usuário é dar -lhe tempo suficiente para alterar todas as senhas do sistema. Se o seu banco de dados estiver comprometido, você precisará de tempo suficiente para ao menos Bloqueie o sistema, se não for alterado em todas as senha no banco de dados.

Jeremiah Grossman, CTO de Whitehat Security, declarou em seu blog Após uma recente recuperação de senha que exigia a quebra de força bruta de sua proteção de senha:

Curiosamente, ao viver esse pesadelo, aprendi muito que não sabia sobre rachaduras, armazenamento e complexidade de senha. Eu vim para apreciar por que o armazenamento de senha é muito mais importante que a complexidade da senha. Se você não sabe como sua senha é armazenada, tudo o que você realmente pode depender é de complexidade. Isso pode ser um conhecimento comum para os profissionais de senha e criptografia, mas para o especialista médio do InfoSec ou da Segurança da Web, duvido muito.

(Ênfase minha.)

O que faz um Boa Senha de qualquer maneira?

Entropia. (Não que eu assine totalmente o ponto de vista de Randall.)

Em resumo, a entropia é a quantidade de variação dentro da senha. Quando uma senha é apenas letras romanas minúsculas, são apenas 26 caracteres. Isso não é muita variação. As senhas alfa-numéricas são melhores, com 36 caracteres. Mas permitir que a parte superior e inferior, com símbolos, tenha cerca de 96 caracteres. Isso é muito melhor do que apenas letras. Um problema é que, para tornar nossas senhas memoráveis, inserimos padrões - que reduz a entropia. Opa!

A entropia de senha é aproximado facilmente. O uso de toda a gama de caracteres ASCII (cerca de 96 caracteres típicos) produz 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, realmente aumentam a entropia de uma senha e dificultam a quebra.

Há uma discussão mais longa sobre entropia de senha no Cripto Stackexchange local. Uma boa pesquisa no Google também apresentará muitos resultados.

Nos comentários que conversei com @popnoodles, que apontou que aplicação Uma política de senha de X comprimento com x muitas letras, números, símbolos, etc., pode realmente reduzir a entropia, tornando o esquema de senha mais previsível. Eu concordo. Randomess, o mais aleatório possível, é sempre a solução mais segura, mas menos memorável.

Até onde eu consegui dizer, fazer a melhor senha do mundo é um Catch-22. Ou não é memorável, muito previsível, muito curto, muitos caracteres unicode (difíceis de digitar em um dispositivo Windows/Mobile), muito tempo, etc. Nenhuma senha é realmente boa o suficiente para nossos propósitos, por isso devemos protegê -los como se eles estavam em Fort Knox.

Melhores Práticas

Bcrypt e Scrypt são as melhores práticas atuais. Scrypt Será melhor que o BCRYPT no tempo, mas ainda não viu a adoção como padrão do Linux/Unix ou pela Web Servers e ainda não teve análises detalhadas de seu algoritmo publicado. Mas ainda assim, o futuro do algoritmo parece promissor. Se você está trabalhando com Ruby, há um gem isso vai te ajudar, e node.js agora tem seu próprio Scrypt pacote. Você pode usar o SCRYPT em PHP através do Scrypt extensão ou o Libsodium Extensão (ambos estão disponíveis no PECL).

Eu sugiro muito ler a documentação para o função cripta Se você quiser entender como usar o BCRYPT ou encontrar -se um Boa embrulho ou use algo como Phpass Para uma implementação mais herdada. 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 a programação principal do Blowfish, com um mecanismo de custo variável. O último permite aumentar o custo para uma senha de força bruta, aumentando o cronograma-chave já caro do Blowfish.

Práticas médias

Eu quase não consigo mais imaginar essa situação. Phpass Suporta Php 3.0.18 a 5.3, por isso é utilizável em quase todas as instalações que se possa imaginar - e devem ser usadas se você não saber com certeza que seu ambiente suporta BCRYPT.

Mas suponha que você não possa usar o BCRYPT ou o phpass. O que então?

Tente uma implementação de Pdkbf2 com o Número máximo de rodadas que seu ambiente/aplicativo/percepção do usuário possa tolerar. O número mais baixo que eu recomendo são 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

Vindo em Php 5.5 é um biblioteca de proteção de senha completa Isso abstrava qualquer dores de trabalho com BCRYPT. Enquanto a maioria de nós está presa com Php 5.2 e 5.3 em ambientes mais comuns, especialmente hosts compartilhados, @ircmaxell construiu um camada de compatibilidade Para a próxima API que é compatível com o PHP 5.3.7.

Criptografia recapitulação e isenção de isenção

O poder computacional necessário para realmente rachadura uma senha de hash não existe. A única maneira de os computadores "quebrar" uma senha é recriá -la e simular o algoritmo de hash usado para protegê -lo. A velocidade do hash está linearmente relacionada à sua capacidade de ser forçada bruta. Pior ainda, a maioria dos algoritmos de hash pode ser facilmente paralela 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 avenidas de ataque e, portanto, deve fazer o seu melhor esforço para proteger seus usuários na frente. 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 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. O que eu disse é minha opinião, mas acho que é baseado no bom e velho senso ... e muita leitura. Lembre-se, seja o mais paranóico possível, dificulte as coisas e, se você ainda estiver preocupado, entre em contato com um hacker ou criptógrafo de chapéu branco para ver o que eles dizem sobre seu código/sistema.

Outras dicas

Uma resposta muito mais curta e segura - Não escreva seu próprio mecanismo de senha, use um mecanismo comprovado e testado.

  • Php 5.5 ou superior: Password_hash () é de boa qualidade e parte do núcleo do PHP.
  • Versões PHP mais antigas: OpenWall's phpass A biblioteca é muito melhor do que a maioria do código personalizado - usado no WordPress, Drupal, etc.

A maioria dos programadores simplesmente não tem experiência para escrever código relacionado a criptografia com segurança, sem introduzir vulnerabilidades.

Auto-teste rápido: O que é o alongamento de senha e quantas iterações você deve usar? Se você não sabe a resposta, deve usar password_hash(), como o alongamento de senha agora é um recurso crítico dos mecanismos de senha devido a CPUs muito mais rápidas e ao uso de GPUs e FPGAs para quebrar senhas a taxas de bilhões de suposições por segundo (com GPUs).

Por exemplo, você pode quebrar todas as senhas do Windows de 8 caracteres em 6 horas Usando 25 GPUs instalados em 5 PCs de mesa. Isso é forçando o isto é, enumerando e verificando cada senha do Windows de 8 caracteres, incluindo personagens especiais, e não é um ataque de dicionário. Isso foi em 2012, a partir de 2018, você poderia usar menos GPUs, ou rachar mais rápido com 25 GPUs.

Também existem muitos ataques de mesa do arco -íris nas senhas do Windows que são executadas nas CPUs comuns e são muito rápidas. Tudo isso é porque o Windows ainda Sal não estica suas senhas, Mesmo no Windows 10 - Não cometa o mesmo erro que a Microsoft!

Veja também:

  • Excelente resposta com mais sobre o porquê password_hash() ou phpass são o melhor caminho a percorrer.
  • Bom artigo do blog fornecendo 'fatores de trabalho' recomendados (número de iterações) para algoritmos principais, incluindo BCRYPT, SCRYPT e PBKDF2.

Eu não armazenaria o hash de senha de duas maneiras diferentes, porque o sistema é pelo menos tão fraco quanto o mais fraco dos algoritmos de hash em uso.

A partir do PHP 5.5, o PHP possui funções simples e seguras para senhas de hash e verificação, Password_hash () e Password_Verify ()

$password = 'anna';
$hash = password_hash($password, PASSWORD_DEFAULT);
$expensiveHash = password_hash($password, PASSWORD_DEFAULT, array('cost' => 20));

password_verify('anna', $hash); //Returns true
password_verify('anna', $expensiveHash); //Also returns true
password_verify('elsa', $hash); //Returns false

Quando password_hash() é usado, ele gera um sal aleatório e o inclui no hash em saída (junto com o custo e o algoritmo usado.) password_verify() Em seguida, lê que hash e determina o método de sal e criptografia usado e o verifica em relação à senha de texto simples.

Fornecendo o PASSWORD_DEFAULT Instrui o PHP a usar o algoritmo de hash padrão da versão instalada do PHP. Exatamente qual algoritmo que significa mudar ao longo do tempo em versões futuras, para que sempre seja um dos algoritmos mais fortes disponíveis.

O aumento do custo (que padrão é 10) torna o hash mais difícil de fazer a força bruta, mas também significa gerar hashes e verificar senhas contra eles será mais trabalho para a CPU do seu servidor.

Observe que, embora o algoritmo de hash padrão possa mudar, os hashes antigos continuarão a verificar bem porque o algoritmo usado é armazenado no hash e password_verify() pega nele.

Embora a pergunta tenha sido respondida, quero apenas reiterar que os sais usados ​​para 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/

Recentemente eu tive uma discussão se hashes de senha salgada com aleatório bits são mais seguros do que aquele salgado com adivinhável ou conhecido Sais.Vamos ver:Se a senha de armazenamento do sistema estiver comprometida como bem como o sistema que armazena o sal aleatório, o atacante irá ter acesso ao haxixe, bem como ao sal, portanto, se o sal é aleatório ou não, não importa.O invasor pode gerar pré-computados Tabelas arco-íris para quebrar o hash.Aí vem a parte interessante - ele não é tão trivial gerar tabelas pré-computadas.Tomemos o exemplo do modelo de segurança WPA.Sua senha WPA na verdade nunca é enviada para Ponto de acesso sem fio.Em vez disso, ele é hashed com seu SSID (o nome da rede - como Linksys, Dlink etc).Uma explicação muito boa de como este trabalho está aqui.Para recuperar a senha do hash, você precisa saber a senha, bem como o salt (nome da rede).Igreja de Wifi já pré-computado tabelas de hash que tem top 1000 SSIDs e cerca de 1 milhão de senhas.O tamanho de todas as tabelas é de cerca de 40 GB.Como você pode ler em seu site, alguém usou 15 matrizes FGPA por 3 dias para gerar essas tabelas.Supondo que a vítima esteja usando o SSID como "a387csf3" e senha como "123456", será que ele será quebrado por aqueles Tabelas?Não!..Eu não posso.Mesmo que a senha seja fraca, as tabelas não tem hashes para SSID a387csf3.Esta é a beleza de ter sal aleatório.Isso impedirá os crackers que prosperam com pré-computados Tabelas.Isso pode impedir um hacker determinado?Provavelmente não.Mas usando sais aleatórios fornecem camada adicional de defesa.Enquanto estamos em Neste tópico, vamos discutir a vantagem adicional de armazenar aleatoriamente sais em um sistema separado.Cenário 1 :Os hashes de senha são armazenados no sistema X e os valores de sal usados para hashing são armazenados no sistema Y.Esses valores de sal são previsíveis ou conhecidos (por exemplo,nome de usuário) Cenário nº 2:Os hashes de senha são armazenados no sistema X e os valores salt usados para hashing são armazenados no sistema Y.Esses valores de sal são aleatórios.Caso sistema X foi comprometido, como você pode adivinhar, há um enorme vantagem de usar sal aleatório em um sistema separado (Cenário #2).O atacante precisará adivinhar valores de adição para poder decifrar Hashes.Se um sal de 32 bits for usado, 2^32= 4.294.967.296 (cerca de 4,2 bilhões) iterações podem ser necessárias para cada senha adivinhada.

Eu só quero salientar que o PHP 5.5 inclui um API de hash de senha que fornece um invólucro em torno crypt().Esta 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ê simplesmente require usar), para quem usa PHP 5.3.7 e posterior e deseja usar agora.

Ele suporta apenas 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, alterações em sua técnica/custo de hash preferido não invalidarão os hashes atuais, a estrutura irá automaticamente usar a técnica/custo correto ao validar.Ele também gera um salt "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 fornecido
  • password_hash() - cria um hash de senha
  • password_needs_rehash() - verifica se o hash fornecido corresponde às opções fornecidas.Útil para verificar se o hash está em conformidade com seu esquema de técnica/custo atual, permitindo que você repita se necessário
  • password_verify() - verifica se uma senha corresponde a um hash

No 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 em versões mais recentes do PHP quando algoritmos de hash mais novos e mais fortes são suportados". Usar PASSWORD_DEFAULT e password_needs_rehash() no login (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ê.

EDITAR:Acabei de perceber que isso é mencionado brevemente na resposta de Robert K.Vou deixar esta resposta aqui porque acho que ela traz um pouco mais de informação sobre como funciona e a facilidade de uso que proporciona para quem não conhece segurança.

estou a usar Phpass que é uma classe PHP simples de um arquivo que pode ser implementada com muita facilidade em quase todos os projetos PHP. Veja também O h.

Por padrão, ele usou a criptografia disponível mais forte que é implementada no phpass, que é bcrypt e volta a outras criptografias até o MD5 para fornecer compatibilidade com retaguarda para estruturas como o WordPress.

O hash retornado pode ser armazenado no banco de dados como está. O uso da amostra para gerar hash é:

$t_hasher = new PasswordHash(8, FALSE);
$hash = $t_hasher->HashPassword($password);

Para verificar senha, pode -se usar:

$t_hasher = new PasswordHash(8, FALSE);
$check = $t_hasher->CheckPassword($password, $hash);

COISAS PARA LEMBRAR

Muito foi dito sobre a criptografia de senha para o PHP, a maioria dos quais é um conselho muito bom, mas antes mesmo de iniciar o processo de uso do PHP para a criptografia de senha, verifique se você tem o seguinte implementado ou pronto para ser implementado.

SERVIDOR

Portas

Não importa o quão boa seja sua criptografia se você não proteger corretamente o servidor que executa o PHP e o banco de dados, todos os seus esforços são inúteis. A maioria dos servidores funciona relativamente da mesma maneira, eles têm portas atribuídas para permitir que você as acessasse remotamente por FTP ou Shell. Certifique -se de alterar a porta padrão da conexão remota que você tem ativo. Ao não fazer isso, você, de fato, fez o invasor fazer uma etapa a menos para acessar seu sistema.

NOME DE USUÁRIO

Para tudo o que é bom no mundo, não use o administrador do nome de usuário, raiz 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 sempre deve ser apenas sudo.

SENHA

Você diz aos seus usuários para fazer boas senhas para evitar ser invadidas, faça o mesmo. Qual é o sentido de passar por todo o esforço de travar sua porta da frente quando você tem o backdoor aberto.

BASE DE DADOS

SERVIDOR

Idealmente, você deseja seu banco de dados e aplicativo em servidores separados. Isso nem sempre é possível devido ao custo, mas permite alguma segurança, pois o invasor terá que passar por duas etapas para acessar totalmente o sistema.

DO UTILIZADOR

Sempre peça que seu aplicativo tenha sua própria conta para acessar o banco de dados e apenas fornecer os privilégios de que precisará.

Em seguida, tenha uma conta de usuário separada para você que não é armazenada em nenhum lugar do servidor, nem mesmo no aplicativo.

Como sempre, não faça essa raiz ou algo semelhante.

SENHA

Siga as mesmas diretrizes que com todas as boas senhas. Também não reutilize a mesma senha em qualquer servidor ou contas de banco de dados no mesmo sistema.

Php

SENHA

Nunca armazene uma senha no seu banco de dados, em vez disso, armazene o hash e o sal único, explicarei por que mais tarde.

Hashing

One Way Hashing !!!!!!!, nunca hash uma senha de uma maneira que possa ser revertida, os hashes devem ser de uma maneira, o que significa que você não os reverte e compará -los com a senha, em vez disso, você está com a senha inserida da mesma maneira e compare os dois hashes. Isso significa que, mesmo que um invasor tenha acesso ao banco de dados, ele não sabe qual é a senha, apenas o hash resultante. O que significa mais segurança para seus usuários no pior cenário possível.

Existem muitas boas funções de hash por aí (password_hash, hash, etc ...) Mas você precisa selecionar um bom algoritmo para que o hash seja eficaz. (BCRYPT e aqueles semelhantes a ele são algoritmos decentes.)

Quando a velocidade da hash é a chave, quanto mais lenta, mais resistente a ataques de 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 devem sempre ser salgadas antes de hash. A salga adiciona uma string aleatória à senha para que senhas semelhantes não pareçam as mesmas no banco de dados. No entanto, se o sal não for exclusivo para cada usuário (ou seja: você usa um sal de codificação dura), você praticamente fez seu sal inútil. Porque uma vez que um invasor descobre um sal de senha, ele tem sal para todos eles.

Ao criar um sal, verifique se é exclusivo da senha que está salgando e guarde o hash e o sal concluídos no seu banco de dados. O que isso fará é fazê -lo para que um invasor tenha que quebrar individualmente cada sal e hash antes que eles possam obter acesso. Isso significa muito mais trabalho e tempo para o atacante.

Usuários criando senhas

Se o usuário estiver criando uma senha através do front -end, significa que ela deve ser enviada para o servidor. Isso abre um problema de segurança, porque isso significa que a senha não criptografada está sendo enviada ao servidor e se um invasor puder ouvir e acessar que toda a sua segurança no PHP é inútil. Sempre transmitir os dados com segurança, isso é feito através do SSL, mas seja cansado, mesmo o SSL não é impecável (a falha do OpenSSL é um exemplo disso).

Também faça com que o usuário crie uma senha segura, é simples e sempre deve ser feita, o usuário ficará grato por ela no final.

Finalmente, não importa as medidas de segurança que você tome nada é 100% seguro, mais avançada a tecnologia para proteger se torna mais avançado os ataques se tornam. Mas, após essas etapas, tornará seu site mais seguro e muito menos desejável para os atacantes seguirem.

Aqui está uma classe PHP que cria um hash e sal para uma senha facilmente

http://git.io/msjqpw

O Google diz que o SHA256 está disponível para o PHP.

Você definitivamente deve usar um sal. Eu recomendo o uso de bytes aleatórios (e não se restringe a personagens e números). Como geralmente, quanto mais você escolher, mais segura, mais lenta, fica. 64 bytes devem ficar bem, eu acho.

Encontrei tópico perfeito sobre este assunto aqui: https://crackstation.net/hashing-security.htm, Eu queria que você se beneficiasse com isso, aqui está o código-fonte também que também prevê a prevenção contra ataques baseados no tempo.

<?php
/*
 * Password hashing with PBKDF2.
 * Author: havoc AT defuse.ca
 * www: https://defuse.ca/php-pbkdf2.htm
 */

// These constants may be changed without breaking existing hashes.
define("PBKDF2_HASH_ALGORITHM", "sha256");
define("PBKDF2_ITERATIONS", 1000);
define("PBKDF2_SALT_BYTES", 24);
define("PBKDF2_HASH_BYTES", 24);

define("HASH_SECTIONS", 4);
define("HASH_ALGORITHM_INDEX", 0);
define("HASH_ITERATION_INDEX", 1);
define("HASH_SALT_INDEX", 2);
define("HASH_PBKDF2_INDEX", 3);

function create_hash($password)
{
    // format: algorithm:iterations:salt:hash
    $salt = base64_encode(mcrypt_create_iv(PBKDF2_SALT_BYTES, MCRYPT_DEV_URANDOM));
    return PBKDF2_HASH_ALGORITHM . ":" . PBKDF2_ITERATIONS . ":" .  $salt . ":" . 
        base64_encode(pbkdf2(
            PBKDF2_HASH_ALGORITHM,
            $password,
            $salt,
            PBKDF2_ITERATIONS,
            PBKDF2_HASH_BYTES,
            true
        ));
}

function validate_password($password, $good_hash)
{
    $params = explode(":", $good_hash);
    if(count($params) < HASH_SECTIONS)
       return false; 
    $pbkdf2 = base64_decode($params[HASH_PBKDF2_INDEX]);
    return slow_equals(
        $pbkdf2,
        pbkdf2(
            $params[HASH_ALGORITHM_INDEX],
            $password,
            $params[HASH_SALT_INDEX],
            (int)$params[HASH_ITERATION_INDEX],
            strlen($pbkdf2),
            true
        )
    );
}

// Compares two strings $a and $b in length-constant time.
function slow_equals($a, $b)
{
    $diff = strlen($a) ^ strlen($b);
    for($i = 0; $i < strlen($a) && $i < strlen($b); $i++)
    {
        $diff |= ord($a[$i]) ^ ord($b[$i]);
    }
    return $diff === 0; 
}

/*
 * PBKDF2 key derivation function as defined by RSA's PKCS #5: https://www.ietf.org/rfc/rfc2898.txt
 * $algorithm - The hash algorithm to use. Recommended: SHA256
 * $password - The password.
 * $salt - A salt that is unique to the password.
 * $count - Iteration count. Higher is better, but slower. Recommended: At least 1000.
 * $key_length - The length of the derived key in bytes.
 * $raw_output - If true, the key is returned in raw binary format. Hex encoded otherwise.
 * Returns: A $key_length-byte key derived from the password and salt.
 *
 * Test vectors can be found here: https://www.ietf.org/rfc/rfc6070.txt
 *
 * This implementation of PBKDF2 was originally created by https://defuse.ca
 * With improvements by http://www.variations-of-shadow.com
 */
function pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output = false)
{
    $algorithm = strtolower($algorithm);
    if(!in_array($algorithm, hash_algos(), true))
        die('PBKDF2 ERROR: Invalid hash algorithm.');
    if($count <= 0 || $key_length <= 0)
        die('PBKDF2 ERROR: Invalid parameters.');

    $hash_length = strlen(hash($algorithm, "", true));
    $block_count = ceil($key_length / $hash_length);

    $output = "";
    for($i = 1; $i <= $block_count; $i++) {
        // $i encoded as 4 bytes, big endian.
        $last = $salt . pack("N", $i);
        // first iteration
        $last = $xorsum = hash_hmac($algorithm, $last, $password, true);
        // perform the other $count - 1 iterations
        for ($j = 1; $j < $count; $j++) {
            $xorsum ^= ($last = hash_hmac($algorithm, $last, $password, true));
        }
        $output .= $xorsum;
    }

    if($raw_output)
        return substr($output, 0, $key_length);
    else
        return bin2hex(substr($output, 0, $key_length));
}
?>

No final, o chapéu duplo, matematicamente, não oferece benefícios. Na prática, no entanto, é útil para prevenir ataques baseados em mesa do arco-íris. Em outras palavras, não é mais benefício do que o hash com um sal, o que leva muito menos tempo do processador em seu aplicativo ou no seu servidor.

Normalmente, uso o SHA1 e o sal com o ID do usuário (ou alguma outra informação específica do usuário) e, às vezes, uso um sal constante (por isso tenho 2 partes no sal).

O SHA1 agora também é considerado um pouco comprometido, mas em um grau muito menor que o MD5. Usando um sal (qualquer sal), você está impedindo o uso de um genérico Tabela de arco -íris Para atacar seus hashes (algumas pessoas tiveram sucesso usando o Google como uma espécie de tabela de arco -íris, procurando o hash). Um invasor pode gerar uma mesa de arco-íris usando seu sal, é por isso que você deve incluir um sal específico do usuário. Dessa forma, eles terão que gerar uma mesa de arco -íris para cada registro do seu sistema, não apenas um para todo o seu sistema! Com esse tipo de salga, mesmo o MD5 é decentemente seguro.

SHA1 e um sal deve ser suficiente (dependendo, naturalmente, se você está codificando algo para forte Knox ou um sistema de login para sua lista de compras) para o futuro próximo. Se o sha1 não é bom o suficiente para você, use SHA256.

A idéia de um sal é deixar o equilíbrio dos resultados de hash, por assim dizer. Sabe-se, por exemplo, que o md5-hash de uma corda vazia é d41d8cd98f00b204e9800998ecf8427e. Então, se alguém com boa memória o suficiente veria esse hash e soubesse que é o hash de uma corda vazia. Mas se a corda estiver salgada (digamos, com a corda "MY_PERSONAL_SALT"), o hash para a 'string vazia' (ou seja"MY_PERSONAL_SALT") torna-se aeac2612626724592271634fb14d3ea6, daí não óbvios para voltar atrás. O que estou tentando dizer, que é melhor usar algum sal, do que não. Portanto, não é uma importância demais para saber que sal para usar.

Na verdade, existem sites que fazem exatamente isso - Você pode alimentá -lo um hash (md5) e ele cospe um texto simples conhecido que gera esse hash particular. Se você obtenha acesso a um banco de dados que armazena-hashes md5 simples, seria trivial entrar no hash para o administrador a esse serviço e fazer login. Mas, se as senhas fossem salgadas, esse serviço se tornaria ineficaz.

Além disso, a hasteagem dupla é geralmente considerada como 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. este poderia Seja considerado outra forma de salga, mas eu não recomendaria.

ok no fitsy, precisamos de sal de sal deve ser único, então vamos gerá -lo

   /**
     * Generating string
     * @param $size
     * @return string
     */
    function Uniwur_string($size){
        $text = md5(uniqid(rand(), TRUE));
        RETURN substr($text, 0, $size);
    }

também precisamos do hash que estou usando o sha512, é o melhor e está no php

   /**
     * Hashing string
     * @param $string
     * @return string
     */
    function hash($string){
        return hash('sha512', $string);
    }

Então agora podemos usar essas funções para gerar senha segura

// generating unique password
$password = Uniwur_string(20); // or you can add manual password
// generating 32 character salt
$salt = Uniwur_string(32);
// now we can manipulate this informations

// hashin salt for safe
$hash_salt = hash($salt);
// hashing password
$hash_psw = hash($password.$hash_salt);

Agora precisamos salvar no banco de dados nosso valor de variável $ hash_psw e $ variável

E para autorizar, usaremos as mesmas etapas ...

É a melhor maneira de proteger as senhas de nossos clientes ...

PS Para as últimas 2 etapas, você pode usar seu próprio algoritmo ... mas certifique -se de gerar essa senha com hash no futuro quando precisar autorizar o usuário ...

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