De onde devem vir os valores de hash de sal?

12

Ao adicionar valores de sal a um valor de hash para algo como uma senha que não pode ser armazenada em texto sem formatação, qual é o melhor local para obter os valores de sal? Para o contexto, suponhamos que seja para senhas em um login de página da web.

Morgan Herlocker
fonte
@ DevArt, achei que era mais adequado aqui porque requer uma resposta muito subjetiva. Um valor de sal pode ser extraído de qualquer lugar, por isso estou perguntando "Onde você acha que é o local mais seguro para extrair valores de sal: cliente ou servidor?"
Morgan Herlocker

Respostas:

7

Normalmente, tenho uma coluna created TIMESTAMPem uma tabela de usuários para ver quando o usuário se registrou. Como não gosto de adicionar uma coluna adicional ao Salt, use a coluna de carimbo de data / hora como salt:

SHA1(password + created)
Jonas
fonte
Estou assumindo que, quando o usuário faz login novamente, você extrai a data com base no nome de usuário ao refazer a verificação?
Morgan Herlocker
1
@ Pro: Sim, da mesma maneira que você, se você tiver uma coluna específica para o sal, então não há diferença nessa perspectiva.
Jonas
7

Isso importa?

O sal serve a dois propósitos. Torna impraticável o uso de grandes tabelas de senhas pré-divididas ("tabelas arco-íris") e faz com que senhas idênticas pareçam diferentes na lista de hashes. Fazer com que as senhas idênticas pareçam diferentes ajuda a evitar um problema em que várias pessoas estão usando uma senha específica, que provavelmente é uma senha fraca comum.

Portanto, cada conta deve ter seu próprio sal exclusivo e os sais não devem ser excessivamente previsíveis, no sentido de que não haverá um grupo de sais com probabilidade de ocorrer. (Se muitos sites começassem com 1 e contassem, os bandidos poderiam construir tabelas de arco-íris, incluindo sais de baixo número, por exemplo.) Eles não precisam ser aleatórios em nenhum sentido além de geralmente imprevisíveis. Eles não são mais secretos do que o próprio hash, portanto, não precisam ser especificamente incognoscíveis.

Use qualquer método conveniente para gerar um sal. Se houver muitos valores potenciais de sal (os primeiros sistemas Unix costumavam usar dois bytes, para um número possível de 65536) em comparação com o número de contas, a atribuição semi-aleatória quase nunca daria um sal duplicado.

David Thornley
fonte
1
Eu geralmente vi o segundo problema - senhas idênticas com aparência diferente - resolvidas concatenando o nome de usuário, o salt e a senha e hash a cadeia inteira. Isso elimina a necessidade de gerar um sal único por conta.
Justin Cave
1
@ Justin: interessante, eu nunca tinha visto o nome de usuário usado como parte do hash, mas é realmente uma boa maneira de adicionar entropia. Eu ainda usaria um sal pseudo-aleatório, apenas porque não custa muito para gerar um.
Matthieu M.
2
@ Matthieu Com a desvantagem de ter que armazená-lo em algum lugar, e se os dois lados de uma transação precisarem, também é necessário enviá-lo. Com o nome de usuário, os dois lados já o conhecem.
Matthew Frederick
2
@ Justin: Nesse caso, você está usando o nome de usuário como sal. Ele responde aos dois propósitos do sal: tornar as tabelas arco-íris impraticáveis ​​e fazer com que senhas semelhantes pareçam diferentes.
David Thornley
@ David - Verdade, você pode olhar para ele como o nome de usuário se tornando parte do sal. Eu ainda gostaria de um sal adicional para que o invasor não possa usar uma tabela arco-íris para encontrar as combinações de nome de usuário / senha. Sem um salt explícito, você está apenas aumentando o tamanho da cadeia de caracteres que o invasor precisa da tabela do arco-íris pelo tamanho do nome de usuário (que provavelmente será curto e minúsculo ou completamente maiúsculo). Um sal constante é suficiente para impedir um ataque de tabela arco-íris, a menos que o site seja grande o suficiente para que um invasor gere uma tabela arco-íris específica do site.
Justin Cave
3

Cada vez que você deseja armazenar uma nova senha (registro, redefinição de senha, atualização de senha), uma boa técnica é:

  • gerar novo sal
    • use um gerador de números pseudo-aleatórios com criptografia segura
    • use um tamanho decente - um bom valor é o tamanho do bloco do algoritmo de hash subjacente (pode ser SHA-256)
  • gerar um novo token de senha
    • crie uma função hmac a partir do algoritmo hash subjacente (pode ser SHA-256) usando o salt como chave hmac
    • for i in (0...65536) { password = hmac(password) }
    • o resultado dos aplicativos iterados da função hmac é o token de senha
  • armazene o salt e o token de senha
    • não armazene a senha original
    • opcionalmente, armazene o algoritmo de hash subjacente e as extensões para descoberta
yfeldblum
fonte
1

Alavancar a estrutura. No .NET você pode usar o RNGCryptoServoiceProvider ...

        // If salt is not specified, generate it on the fly.
        if (saltBytes == null)
        {
            // Define min and max salt sizes.
            int minSaltSize = 4;
            int maxSaltSize = 8;

            // Generate a random number for the size of the salt.
            Random  random = new Random();
            int saltSize = random.Next(minSaltSize, maxSaltSize);

            // Allocate a byte array, which will hold the salt.
            saltBytes = new byte[saltSize];

            // Initialize a random number generator.
            RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();

            // Fill the salt with cryptographically strong byte values.
            rng.GetNonZeroBytes(saltBytes); 
        }

Outras estruturas devem ter classes semelhantes que você pode aproveitar. Para obter aleatoriedade, o software geralmente utiliza o usuário em comparação Randomcom o mencionado acima. Mover aleatoriamente um mouse em uma área definida para fornecer sal é uma opção empregada pelo TrueCrypt. Tudo se resume às suas necessidades específicas e nível de segurança; desde que seu sal poderia simplesmente ser !@#$%.

Aaron McIver
fonte
1

Você gera um servidor salt e o atribui a uma conta de usuário após sua criação. É melhor usar alguma API de geração de criptografia disponível com sua estrutura, mas, em princípio, qualquer sequência serve.

Normalmente, as coisas são armazenadas assim:

User
-------------------
ID
Username
PasswordHashWithSalt

Exemplo:

PasswordHashWithSalt =

A15CD9652D4F4A3FB61A2A422AEAFDF0DEA4E703 j5d58k4b56s8744q


fonte
Atribua-o com base no que? Ele não precisa ter algum valor que permanecerá no local para que possa ser replicado quando o usuário fizer login novamente após a criação?
Morgan Herlocker
Com "assign", quero dizer gerar um sal por par de nome de usuário / senha (conta) e armazená-lo no banco de dados. Quando você precisa realizar o login, use esse sal armazenado para verificar as coisas.
1

Use bcrypt e leia este artigo, pois os hashes normais por si só não são uma proteção séria nos dias de hoje.

Considere usar o protocolo de senha de conhecimento zero SDR, que possui muitas bibliotecas de código-fonte aberto e é livre de patentes.

SDR requer sal e o melhor lugar para conseguir isso é o cliente; tempo, pressionando as teclas, movimentos do mouse, hash de variáveis ​​de ambiente, números aleatórios, horas de criação de arquivos em sua pasta temporária, para fazer sal no final de uma maneira imprevisível, longe do servidor. O SDR pega o salt, uma senha grande, a senha do usuário e gera uma chave verificadora. Você não armazena uma senha que nunca sai da máquina, mas pode verificar se eles têm a senha que acompanha a chave do verificador e o salt. É imune ao homem nos ataques do meio e do dicionário. Criptografe as chaves e o salt na coluna do banco de dados apenas para ter certeza.

simbo1905
fonte