A necessidade de esconder o sal para um hash

No trabalho, temos duas teorias concorrentes para sais. Os produtos em que trabalho usam algo como um nome de usuário ou número de telefone para salgar o hash. Essencialmente, algo diferente para cada usuário, mas está prontamente disponível para nós. O outro produto gera aleatoriamente um salt para cada usuário e muda sempre que o usuário altera a senha. O sal é então criptografado no database.

Minha pergunta é se a segunda abordagem é realmente necessária? Eu posso entender de uma perspectiva puramente teórica que é mais seguro do que a primeira abordagem, mas o que é do ponto de vista da praticidade. Agora mesmo para autenticar um usuário, o sal deve ser descriptografado e aplicado às informações de login.

Depois de pensar nisso, simplesmente não vejo um ganho real de segurança com essa abordagem. Mudar o sal de uma conta para outra ainda torna extremamente difícil para alguém tentar forçar o algoritmo de hash mesmo que o invasor saiba como determinar rapidamente o que era para cada conta. Isto está indo no pressuposto de que as senhas são suficientemente fortes. (Obviamente, encontrar o hash correto para um conjunto de senhas onde eles são todos dois dígitos é significativamente mais fácil do que encontrar o hash correto de senhas com 8 dígitos). Estou incorreto na minha lógica, ou há algo que estou perdendo?

EDIT: Ok, então aqui está a razão pela qual eu acho que é muito discutível para criptografar o sal. (deixa eu saber se estou no caminho certo).

Para a seguinte explicação, vamos supor que as senhas são sempre 8 caracteres e o salt é 5 e todas as senhas são compostas de letras minúsculas (isso só torna a matemática mais fácil).

Ter um sal diferente para cada input significa que eu não posso usar a mesma tabela de arco-íris (na verdade, tecnicamente, eu poderia se eu tivesse um tamanho suficiente, mas vamos ignorar isso por enquanto). Esta é a verdadeira chave para o sal do que eu entendo, porque para quebrar todas as contas eu tenho que reinventar a roda, por assim dizer, para cada um. Agora, se eu souber como aplicar o sal correto a uma senha para gerar o hash, eu faria isso porque um salt realmente apenas estende o comprimento / complexidade da frase hash. Então, eu estaria cortando o número de combinações possíveis que precisaria gerar para “saber” que tenho a senha + salt de 13 ^ 26 a 8 ^ 26 porque sei o que é o sal. Agora isso facilita, mas ainda é muito difícil.

Então, para criptografar o sal. Se eu sei que o salt é criptografado, eu não tentaria decifrar (supondo que eu saiba que ele tem um nível suficiente de criptografia) primeiro. Eu ignoraria isso. Em vez de tentar descobrir como descriptografá-lo, voltando ao exemplo anterior, eu apenas geraria uma tabela maior do arco-íris contendo todas as chaves para o 13 ^ 26. Não saber o sal definitivamente me atrasaria, mas eu não acho que isso acrescentaria a tarefa monumental de tentar quebrar a criptografia de sal primeiro. É por isso que não acho que valha a pena. Pensamentos?

Aqui está um link descrevendo quanto tempo as senhas vão aguentar sob um ataque de força bruta: http://www.lockdown.co.uk/?pg=combi

A resposta aqui é se perguntar do que você está realmente tentando se proteger. Se alguém tiver access ao seu database, ele terá access aos sais criptografados e provavelmente terá access ao seu código também. Com tudo o que eles poderiam descriptografar os sais criptografados? Se sim, então a criptografia é praticamente inútil de qualquer maneira. O sal realmente existe para que não seja possível formar uma tabela de arco-íris para quebrar seu database de senha inteiro de uma só vez, se for invadido. Desse ponto de vista, desde que cada sal seja único, não há diferença, um ataque de força bruta seria necessário com seus sais ou os sais criptografados para cada senha individualmente.

Escondendo um sal é desnecessário.

Um sal diferente deve ser usado para cada hash. Na prática, isso é fácil de conseguir obtendo 8 ou mais bytes do gerador de números randoms de qualidade criptográfica.

De uma resposta anterior minha :

O sal ajuda a impedir ataques de dictionary pré-computados.

Suponha que um invasor tenha uma lista de senhas prováveis. Ele pode dividir cada hash e compará-lo com o hash da senha de sua vítima e ver se combina. Se a lista for grande, isso pode levar muito tempo. Ele não quer gastar tanto tempo em seu próximo alvo, então ele registra o resultado em um “dictionary” onde um hash aponta para sua input correspondente. Se a lista de senhas for muito, muito longa, ele pode usar técnicas como a Rainbow Table para economizar espaço.

No entanto, suponha que seu próximo alvo tenha salgado sua senha. Mesmo que o invasor saiba o que é o sal, sua tabela pré-computada não tem valor – o sal altera o hash resultante de cada senha. Ele tem que re-hash todas as senhas em sua lista, afixando o sal do alvo para a input. Cada sal diferente requer um dictionary diferente, e se sais suficientes forem usados, o invasor não terá espaço para armazenar dictionarys para todos eles. Negociar espaço para economizar tempo não é mais uma opção; o atacante deve voltar a colocar cada senha em sua lista para cada alvo que quiser atacar.

Portanto, não é necessário manter o segredo do sal. Garantir que o atacante não tenha um dictionary pré-calculado correspondente a esse sal em particular é suficiente.


Depois de pensar um pouco mais sobre isso, percebi que se enganar e pensar que o sal pode ser escondido é perigoso. É muito melhor assumir que o sal não pode ser escondido e projetar o sistema para ser seguro, apesar disso. Eu forneço uma explicação mais detalhada em outra resposta.

Meu entendimento do “sal” é que ele dificulta o craqueamento, mas não tenta esconder os dados extras. Se você está tentando obter mais segurança, tornando o sal “secreto”, então você realmente só quer mais bits em suas chaves de criptografia.

A segunda abordagem é apenas um pouco mais segura. Os sais protegem os usuários contra ataques de dictionary e ataques de mesa com arco-íris. Eles tornam mais difícil para um invasor ambicioso comprometer todo o seu sistema, mas ainda estão vulneráveis ​​a ataques focados em um usuário do seu sistema. Se você usar informações publicamente disponíveis, como um número de telefone, e o invasor perceber isso , você terá salvado uma etapa do ataque. É claro que a questão é discutível se o atacante obtiver todo o seu database, sais e tudo mais.

EDIT: Depois de reler sobre esta resposta e alguns dos comentários, ocorre-me que um pouco da confusão pode ser devido ao fato de que eu estou apenas comparando os dois casos muito específicos apresentados na pergunta: sal random vs. sal não random. A questão de usar um número de telefone como um sal é irrelevante se o invasor obtiver todo o seu database, não a questão de usar um sal.

Um sal oculto não é mais sal. É pimenta. Tem seu uso. É diferente do sal.

Pepper é uma chave secreta adicionada à senha + salt, que transforma o hash em um HMAC (Código de Autenticação de Mensagem Baseado em Hash). Um hacker com access à saída hash e ao sal pode, teoricamente, usar a força bruta para adivinhar uma input que irá gerar o hash (e, portanto, passar a validação na checkbox de texto da senha). Ao adicionar pimenta, você aumenta o espaço do problema de forma criptograficamente aleatória, tornando o problema intratável sem hardware sério.

Para mais informações sobre pimenta, confira aqui .

Veja também hmac .

Aqui está um exemplo simples mostrando porque é ruim ter o mesmo sal para cada hash

Considere a seguinte tabela

UserId UserName, Password 1 Fred Hash1 = Sha(Salt1+Password1) 2 Ted Hash2 = Sha(Salt2+Password2) 

Caso 1 quando salt 1 é o mesmo que salt2 Se Hash2 for substituído por Hash1, o usuário 2 poderá efetuar logon com a senha do usuário 1

Caso 2 quando salt 1 não é o mesmo salt2 Se o Hash2 for substituído por Hash1, o user2 não poderá fazer logon com a senha do usuário 1.

… algo como um nome de usuário ou número de telefone para salgar o hash. …

Minha pergunta é se a segunda abordagem é realmente necessária? Eu posso entender de uma perspectiva puramente teórica que é mais seguro do que a primeira abordagem, mas o que é do ponto de vista da praticidade?

Do ponto de vista prático, um sal é um detalhe de implementação. Se você alguma vez alterar como as informações do usuário são coletadas ou mantidas – e os nomes de usuários e números de telefone às vezes mudam, para usar seus exemplos exatos – então você pode ter comprometido sua segurança. Você quer que uma mudança tão voltada para fora tenha preocupações de segurança muito mais profundas?

A interrupção do requisito de que cada conta tenha um número de telefone precisa envolver uma revisão de segurança completa para garantir que você não tenha aberto essas contas para um comprometimento da segurança?

Existem duas técnicas, com objectives diferentes:

  • O “salt” é usado para fazer duas senhas iguais, criptografadas de maneira diferente. Dessa forma, um intruso não pode usar com eficiência um ataque de dictionary contra uma lista inteira de senhas criptografadas.

  • O “segredo” (compartilhado) é adicionado antes da mensagem, para que um intruso não possa criar suas próprias mensagens e aceitá-las.

Eu costumo esconder o sal. Eu uso 10 bits de sal prefixando um número random de 1 a 1024 para o início da senha antes de fazer o hashing. Ao comparar a senha que o usuário inseriu com o hash, faço um loop de 1 a 1024 e experimento todos os valores possíveis de sal até encontrar a correspondência. Isso leva menos de 1/10 de segundo. Eu tenho a idéia de fazer isso desta maneira a partir do PHP password_hash e password_verify . No meu exemplo, o “custo” é 10 para 10 bits de sal. Ou a partir do que outro usuário disse, “sal” oculto é chamado de “pimenta”. O sal não é criptografado no database. É brutal forçado para fora. Isso tornaria a mesa do arco-íris necessária para inverter o hash 1000 vezes maior. Eu uso sha256 porque é rápido, mas ainda é considerado seguro.

Realmente, isso depende do tipo de ataque que você está tentando proteger seus dados.

O propósito de um salt exclusivo para cada senha é evitar um ataque de dictionary contra o database de senhas inteiro.

Criptografar o sal exclusivo para cada senha tornaria mais difícil decifrar uma senha individual, sim, mas você deve ponderar se realmente há muito benefício. Se o atacante, por força bruta, descobrir que esta string:

 Marianne2ae85fb5d 

hashes para um hash armazenado no DB, é realmente difícil descobrir qual parte é a passagem e qual parte é o sal?