Qual tipo de coluna / comprimento devo usar para armazenar uma senha criptografada do Bcrypt em um database?

Eu quero armazenar uma senha com hash (usando BCrypt) em um database. Qual seria um bom tipo para isso e qual seria o comprimento correto? As senhas são criptografadas com o BCrypt sempre do mesmo tamanho?

EDITAR

Exemplo de hash:

$2a$10$KssILxWNR6k62B7yiX0GAe2Q7wwHlrzhF3LqtVvpyvHZf0MwvNfVu

Após hashing algumas senhas, parece que o BCrypt sempre gera hashes de 60 caracteres.

EDIT 2

Desculpe por não mencionar a implementação. Eu estou usando o jBCrypt .

O formato de criptografia modular para bcrypt consiste em

  • $2$ , $2a$ ou $2y$ identificando o algoritmo de hashing e o formato
  • um valor de dois dígitos indicando o parâmetro de custo, seguido por $
  • um valor de codificação base-64 com 53 caracteres de comprimento (eles usam o alfabeto . , / , 09 , AZ , az que é diferente do alfabeto de codificação Base 64 padrão ) consistindo de:
    • 22 caracteres de sal (efetivamente apenas 128 bits dos 132 bits decodificados)
    • 31 caracteres de saída criptografada (efetivamente apenas 184 bits dos 186 bits decodificados)

Assim, o comprimento total é de 59 ou 60 bytes, respectivamente.

Ao usar o formato 2a, você precisará de 60 bytes. E assim, para o MySQL, recomendo usar o CHAR(60) BINARY ou BINARY(60) (consulte The _bin and binary Collations para obter informações sobre a diferença).

CHAR não é binário seguro e a igualdade não depende somente do valor do byte, mas do agrupamento real; no pior caso, A é tratado como igual a a . Veja The _bin and binary Collations para mais informações.

Um hash Bcrypt pode ser armazenado em uma coluna BINARY(40) .

BINARY(60) , como as outras respostas sugerem, é a escolha mais fácil e natural, mas se você quiser maximizar a eficiência do armazenamento, você pode economizar 20 bytes desconstruindo o hash sem perdas. Eu documentei isso mais detalhadamente no GitHub: https://github.com/ademarre/binary-mcf

Os hashes Bcrypt seguem uma estrutura conhecida como formato de cripta modular (MCF). O MCF binário (BMCF) decodifica essas representações de hashes textuais para uma estrutura binária mais compacta. No caso do Bcrypt, o hash binário resultante é 40 bytes.

O Gumbo fez um bom trabalho ao explicar os quatro componentes de um hash do Bcrypt MCF:

 $$$ 

A decodificação para o BMCF é assim:

  1. $$ pode ser representado em 3 bits.
  2. $ , 04-31, pode ser representado em 5 bits. Coloque-os juntos por 1 byte.
  3. O sal de 22 caracteres é uma representação de 64 bits de base (não padrão). A decodificação Base-64 produz 16 bytes.
  4. O digest do hash de 31 caracteres pode ser decodificado na base 64 para 23 bytes.
  5. Coloque tudo junto por 40 bytes: 1 + 16 + 23

Você pode ler mais no link acima, ou examinar minha implementação PHP , também no GitHub.

Se você estiver usando o password_hash() do PHP com o algoritmo PASSWORD_DEFAULT para gerar o hash bcrypt (que eu presumo que seja uma grande porcentagem de pessoas lendo esta questão) lembre-se de que no futuro password_hash() pode usar um algoritmo diferente como o padrão e isso poderia, portanto, afetar o comprimento do hash (mas pode não ser necessariamente mais longo).

Na página do manual:

Note que esta constante é projetada para mudar ao longo do tempo conforme novos e mais fortes algoritmos são adicionados ao PHP. Por esse motivo, o comprimento do resultado do uso desse identificador pode mudar com o tempo. Portanto, recomenda-se armazenar o resultado em uma coluna de database que pode se expandir para além de 60 caracteres (255 caracteres seria uma boa escolha).

Usando o bcrypt, mesmo se você tiver 1 bilhão de usuários (ou seja, você está competindo com o facebook) para armazenar hashes de 255 bytes, ele teria apenas ~ 255 GB de dados – aproximadamente o tamanho de um disco rígido SSD pequeno. É extremamente improvável que o armazenamento do hash da senha seja o gargalo no seu aplicativo. No entanto, na chance de que o espaço de armazenamento seja realmente um problema por algum motivo, você pode usar PASSWORD_BCRYPT para forçar o password_hash() a usar o bcrypt, mesmo que não seja o padrão. Apenas certifique-se de estar informado sobre quaisquer vulnerabilidades encontradas no bcrypt e revise as notas da versão toda vez que uma nova versão do PHP for lançada. Se o algoritmo padrão for alterado, seria bom revisar o motivo e tomar uma decisão informada sobre o uso ou não do novo algoritmo.

Eu não acho que existem truques legais que você possa fazer armazenando isso, como você pode fazer, por exemplo, com um hash MD5.

Eu acho que a sua melhor aposta é para armazená-lo como um CHAR(60) , pois é sempre de 60 caracteres