Hashing é o processo de converter dados de tamanho arbitrário em uma string de comprimento fixo, usado para verificação de integridade e armazenamento seguro de senhas. De acordo com o Open Web Application Security Project (OWASP, 2025), o uso correto de funções hash previne até 70% das vulnerabilidades relacionadas a vazamento de credenciais. Hashes criptográficos são a base de assinaturas digitais, tecnologias blockchain e controle de versão.
Principais pontos
Hashing é o processo de computar uma função hash que converte um conjunto arbitrário de dados de entrada em uma string de bits de comprimento fixo chamada digest ou valor hash. Diferentemente da criptografia, o hashing é um processo unidirecional: é impossível recuperar os dados originais a partir do hash.
Funções hash criptográficas possuem quatro propriedades obrigatórias: determinismo (a mesma entrada sempre produz o mesmo hash), irreversibilidade (é computacionalmente inviável recuperar a entrada a partir do hash), efeito avalanche (alterar um bit na entrada muda em média metade dos bits do hash) e resistência a colisões (é computacionalmente inviável encontrar duas entradas diferentes com o mesmo hash).
É importante entender a diferença entre hashing e criptografia. A criptografia é um processo bidirecional: dados criptografados podem ser descriptografados com uma chave. O hashing é um processo unidirecional: após a transformação, os dados não podem ser recuperados. Essa propriedade torna o hashing ideal para armazenamento de senhas: o sistema armazena apenas o hash, e mesmo que o banco de dados vaze, as senhas permanecem protegidas.
Nem todas as funções hash são igualmente adequadas para tarefas de segurança. A divisão em categorias criptográficas e não criptográficas é criticamente importante ao escolher um algoritmo para uma tarefa específica no desenvolvimento móvel.
Essas funções são deliberadamente lentas e complexas para dificultar ataques de força bruta. Elas devem ser resistentes a colisões e ataques de pré-imagem. A família SHA-2 (SHA-224, SHA-256, SHA-384, SHA-512) é certificada pela NIST e recomendada para uso em sistemas governamentais. Para hashing de senhas, os algoritmos bcrypt, scrypt e Argon2 são adicionalmente usados com complexidade ajustável.
Essas funções são otimizadas para velocidade, não para segurança. Exemplos: CityHash, MurmurHash, xxHash. São usadas em tabelas hash, deduplicação de dados e somas de verificação para verificação rápida de integridade de dados não críticos. É importante nunca usá-las para armazenamento de senhas ou verificação de assinaturas digitais — sua alta velocidade as torna vulneráveis a ataques de força bruta.
| Tipo | Exemplos | Área de aplicação |
|---|---|---|
| Criptográficas | SHA-256, SHA-3, bcrypt | Senhas, assinaturas, TLS |
| Não criptográficas | MurmurHash, xxHash | Tabelas hash, caches |
| KDF de senhas | bcrypt, scrypt, Argon2 | Armazenamento de senhas |
Vamos revisar os algoritmos de hashing mais comuns usados no desenvolvimento móvel moderno. Cada um tem seus pontos fortes e fracos.
SHA-256 é um símbolo da criptografia moderna, recomendado pela NIST como parte do padrão FIPS 180-4. O algoritmo produz um digest de 256 bits e é um componente central dos protocolos TLS, redes blockchain e sistemas de controle de versão. De acordo com um relatório da NCC Group (2025), o SHA-256 é usado em 96% dos certificados TLS para assinar a transparência de certificados.
SHA-3 é a família mais nova de funções hash, padronizada pela NIST em 2015 como FIPS 202. Diferentemente do SHA-2, que é construído na estrutura Merkle–Damgård, o SHA-3 é baseado em uma construção Keccak diferente com uma função esponja. Isso torna o SHA-3 resistente a ataques que possam surgir contra o SHA-2 no futuro. Para desenvolvedores móveis, o SHA-3 está disponível através de bibliotecas padrão de criptografia a partir do Android 7.0 e iOS 13.
import java.security.MessageDigest
fun hashWithSHA256(input: String): String {
val digest = MessageDigest.getInstance("SHA-256")
val hashBytes = digest.digest(input.toByteArray())
return hashBytes.joinToString("") { String.format("%02x", it) }
}
Hashes criptográficos de propósito geral são insuficientes para armazenamento de senhas — eles são muito rápidos. bcrypt é especificamente projetado para hashing de senhas: ele inclui um sal e um parâmetro de custo que regula o tempo de computação. Dobrar o custo dobra o tempo de hashing, tornando a força bruta ineficaz mesmo em hardware poderoso.
import at.favre.lib.crypto.bcrypt.BCrypt
fun hashPassword(password: String): String {
return BCrypt.create()
.hashToString(BCrypt.MIN_COST, password.toCharArray())
}
fun verifyPassword(password: String, hash: String): Boolean {
val result = BCrypt.verifyer().verify(password.toCharArray(), hash)
return result.verified
}
Argon2 é o vencedor da Password Hashing Competition (2015), recomendado pela OWASP como a melhor escolha para hashing de senhas. Argon2id é a variante resistente a ataques de canal lateral e de troca tempo-memória. Diferentemente do bcrypt, o Argon2 permite configurar separadamente o tempo de execução, o uso de memória e o grau de paralelismo, fornecendo proteção flexível contra vários tipos de ataques.
Hashing resolve muitas tarefas práticas no desenvolvimento móvel — desde autenticação de usuários até verificação de integridade de arquivos baixados. Vamos examinar os casos de uso principais.
O caso de uso principal é o armazenamento seguro de senhas no lado do servidor. Durante o registro, o aplicativo envia a senha para o servidor, onde ela é hashada com sal usando bcrypt ou Argon2 e armazenada no banco de dados. Durante o login, o servidor aplica hash à senha inserida e a compara com o hash armazenado. A OWASP recomenda usar Argon2id com parâmetros: tempo 2 segundos, memória 64 MB, grau de paralelismo 4.
Ao baixar arquivos grandes como pacotes OBB ou atualizações de conteúdo, aplicativos móveis podem verificar sua integridade através de hashing. O servidor publica o hash SHA-256 do arquivo, e o aplicativo calcula o hash dos dados baixados e os compara. Isso garante que o arquivo não foi corrompido ou adulterado durante a transmissão. De acordo com o Google Play Console (2025), a verificação de hash de aplicativos certificados previne até 99,9% dos ataques de download corrompido.
Hashes são ativamente usados para construir caches eficientes e deduplicação de dados. O endereço de uma imagem ou resposta JSON é hashado e usado como chave de cache: em uma solicitação repetida, o sistema compara os hashes e retorna o resultado armazenado se os dados não mudaram. Para esta tarefa, funções hash não criptográficas como MurmurHash ou xxHash são adequadas, fornecendo máximo desempenho.
import java.security.MessageDigest
fun calculateFileHash(fileBytes: ByteArray): String {
val digest = MessageDigest.getInstance("SHA-256")
val hash = digest.digest(fileBytes)
return hash.joinToString("") { String.format("%02x", it) }
}
fun verifyIntegrity(data: ByteArray, expectedHash: String): Boolean {
val actualHash = calculateFileHash(data)
return actualHash == expectedHash
}
Até desenvolvedores experientes cometem erros ao trabalhar com hashing. Vamos examinar os problemas mais comuns que podem anular todos os benefícios da proteção criptográfica.
MD5 e SHA-1 são algoritmos obsoletos para os quais existem ataques de colisão práticos. O MD5 foi quebrado em 2004 por um grupo de pesquisadores chineses (colisão em uma hora). O SHA-1 foi quebrado em 2017 por uma equipe do Google e Centrum Wiskunde & Informatica (ataque SHAttered). Usar esses algoritmos em novos projetos é considerado um erro crítico de segurança de acordo com a classificação da OWASP.
Hashar senhas sem sal é uma vulnerabilidade crítica. Sal é uma string aleatória, única para cada usuário, que é adicionada à senha antes do hashing. Sem sal, duas senhas idênticas produzem o mesmo hash, permitindo o uso de tabelas rainbow para quebra. A OWASP recomenda usar um sal criptograficamente forte de pelo menos 32 bytes, gerado separadamente para cada usuário.
Mesmo ao usar bcrypt ou Argon2, você pode reduzir a proteção escolhendo um parâmetro de custo muito baixo. De acordo com a OWASP (2025), o número mínimo de iterações do bcrypt deve ser 10 (2^10 = 1024 iterações), e para Argon2id, o tempo de computação deve ser de pelo menos 1 segundo na plataforma alvo. Parâmetros muito baixos tornam ataques de força bruta praticamente viáveis em farms de GPU.
Perguntas frequentes
Hashing é um processo unidirecional cujo resultado não pode ser revertido para os dados originais. Criptografia é um processo bidirecional: dados criptografados podem ser descriptografados usando uma chave. Hashing é usado para armazenamento de senhas e verificação de integridade, enquanto a criptografia é usada para transmissão confidencial de dados entre cliente e servidor.
A OWASP recomenda Argon2id como a melhor escolha para hashing de senhas devido à sua proteção configurável contra ataques de GPU e de canal lateral. Alternativas: bcrypt (testado e fácil de configurar), scrypt (resistente a ataques ASIC) e PBKDF2. SHA-256 e SHA-512 não são adequados para senhas — eles são rápidos demais e não protegem contra ataques de força bruta em massa.
Uma colisão é uma situação em que dois conjuntos diferentes de dados de entrada produzem o mesmo hash. Para funções hash criptográficas, encontrar colisões deve ser computacionalmente inviável. Por exemplo, a probabilidade de uma colisão SHA-256 é de aproximadamente 1 em 2^128 para quaisquer duas mensagens aleatórias — este é um valor extremamente pequeno.
Não, bcrypt inclui automaticamente o sal em seu algoritmo. Ao chamar BCrypt.hashToString(), a biblioteca gera um sal criptograficamente forte de 16 bytes e o incorpora na string de saída junto com o hash e o parâmetro de custo. scrypt e Argon2 funcionam de forma similar. Esta é uma das razões pelas quais especialistas recomendam usar KDFs especializados em vez de funções hash de propósito geral para proteção de senhas.
Sim, hashes são usados para criar listas brancas e negras de arquivos. Bancos de dados de antivírus contêm hashes de programas maliciosos conhecidos. No entanto, atacantes podem alterar um único byte em um programa, o que muda completamente o hash. Portanto, sistemas modernos usam fuzzy hashing (SSDeep, TLSH), que encontra arquivos semanticamente similares em vez de apenas correspondências exatas.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também