Senhas armazenadas com segurança

Márcio d'Ávila, 2 de novembro de 2005
Categoria: Segurança: Criptografia

O armazenamento de senhas requer um mínimo de segurança criptográfica, para que não haja risco das senhas serem lidas ou obtidas diretamente do local onde são armazenadas, tipicamente uma tabela de banco de dados.

Para decidir qual a forma de proteção mais adequada para senhas armazenadas, existe uma pergunta básica: Será necessário em algum momento recuperar (exibir ou listar) a senha original?

Não, a senha original nunca precisa ser recuperada.

O mecanismo de armazenamento de senha mais seguro é aquele em que a senha é codificada de forma irreversível, usando para isso uma técnica de message digest ou hash criptográfico como SHA-1 ou MD5, baseada em operações de “mão-única”. Só a senha criptografada é armazenada.

A comparação entre uma tentativa de senha fornecida e uma senha previamente armazenada é indireta, feita pela comparação das formas criptografadas de ambas (se a codificação gerada por ambas é a mesma, então a senha fornecida confere).

Caso a senha seja esquecida ou perdida por quem a gerou, a única alternativa é gerar uma nova senha, já que não é possível recuperar a senha original a partir do valor armazenado.

Sim, a senha original pode ser recuperada.

Se a senha original precisa em algum momento ser recuperada a partir do valor armazenado, então o armazenamento em geral requer um processo de criptografia convencional baseada em chave como AES, Blowfish ou RC4, em que a senha é armazenada criptografada com uma chave, por segurança. De posse desta chave, é possível decriptografar o valor armazenado e obter a senha original.

O caso típico é uma aplicação que, em caso de esquecimento da senha pelo seu “dono”, fornece a opção de enviar a senha atual por e-mail ou exibí-la mediante confirmação de determinados dados pessoais. Muitas vezes, a chave de criptografia é única para todas as chaves e é mantida, de alguma forma, dentro da aplicação.

Esta forma obviamente implica em um nível mais baixo de segurança, pois a segurança da senha depende da segurança da chave de criptografia. Se esta chave puder ser obtida, então a segurança das senhas armazenadas estará comprometida.

Para reduzir o número de vezes em que a senha original é decriptografada a partir do valor armazenado, é recomendável que a conferência entre uma tentativa de senha fornecida e da senha armazenada seja também feita indiretamente, criptografando a senha fornecida e comparando com o valor da senha criptografada armazenado.

Em ambos os casos, dois procedimentos adicionais podem ser usados para conferir ainda mais segurança às senhas armazenadas, como apresentado a seguir.

Incluir a identificação de usuário junto com a senha armazenada

Como o caso mais comum de uso de senhas é para a autenticação e autorização de acesso a usuários de um sistema, é comum cada senha estar associada em um par com uma identificação de usuário (login).

Neste caso, criptografar a identificação do usuário junto com sua senha assegura que, ainda que a mesma senha seja usada por dois usuários do sistema, a senha criptografada armazenada para ambos será diferente. Isto evita que seja possível identificar senhas iguais no sistema através da comparação de valores iguais entre as senhas armazenadas.

Tal procedimento pressupõe que a identificação de usuário não seja passível de alteração ou, caso seja alterada, a senha armazenada seja devidamente atualizada em conjunto.

Incluir um “sal” variável junto com a senha armazenada

Se a cada vez que um novo valor de senha é criptografado para ser armazenado for incluído um conteúdo adicional variável ou aleatório junto com a senha, isto garante o seguinte: ainda que um mesmo usuário escolha em vezes distintas a mesma senha, o valor armazenado a cada vez será diferente.

Para que seja possível criptografar tentativas de senhas fornecidas e conferí-las com o valor armazenado, é necessário que o valor do sal usado esteja disponível de forma não criptografada em algum lugar. Neste propósito, eis duas possibilidades: (1) Caso seja armazenado um valor como a data/hora da alteração de senha, este pode ser o valor usado como sal. (2) Caso seja gerado um sal aleatório, ele pode também ser armazenado separadamente, não criptografado.

Representando em termos de diagramas matemáticos tudo aqui exposto, temos:

senha irreversível armazenadasal || hash( sal || usuário || senha )


senha recuperável armazenadasal || cripto( sal || usuário || senha , chave )


Firefox - A web de volta
Creative Commons License

© 2003-2010, Márcio d'Ávila, mhavila.com.br, direitos reservados. O texto e código-fonte apresentados podem ser referenciados, distribuídos e utilizados, desde que expressamente citada esta fonte e o crédito do(s) autor(es). A informação aqui apresentada, apesar de todo o esforço para garantir sua precisão e correção, é oferecida "como está", sem quaisquer garantias explícitas ou implícitas decorrentes de sua utilização ou suas conseqüências diretas e indiretas.