Senha vs UUID vs Hash vs Token: Guia de 8 tipos de strings aleatórias para desenvolvedores

No desenvolvimento de software, você encontra constantemente strings como 550e8400-e29b-41d4-a716-446655440000 ou eyJhbGciOiJIUzI1NiJ9... — sequências de caracteres de aparência aleatória. UUIDs, senhas, hashes, tokens, chaves de API… todos se parecem, mas sua intenção de design e finalidade são fundamentalmente diferentes.

Este artigo decompõe os 8 tipos mais comuns de strings de aparência aleatória sob a ótica de “por que existem” e “o que protegem”. Quando você entende o que cada uma realmente é, escolher a certa para cada situação se torna algo natural.

Comparação dos 8 tipos

Vamos começar pela visão geral.

TipoUso principalSecreto?Reversível?GeraçãoCaracterística-chave
UUIDIdentificação únicaNãoAleatório / tempoID sem colisão
SenhaAutenticação de usuárioSimApenas o donoCriada por humanoSegredo memorizado
HashVerificação de integridadeNãoIrreversívelFunção matemáticaImpressão digital
TokenAutenticação / autorizaçãoSimDependeCSPRNGExpira
Chave de APIAutenticação de serviçoSimCSPRNGSenha de máquina
Sal (Salt)Reforço do hashNãoCSPRNGDefesa contra rainbow table
NonceIdentificação de uso únicoNãoCSPRNGPrevenção de replay
AssinaturaDetecção de adulteraçãoNãoIrreversívelCálculo criptoHMAC, assinatura RSA

A lição principal: classifique pela finalidade de design, não pela aparência. A mesma string aleatória de 32 caracteres pode ser apenas um rótulo quando usada como UUID, ou uma chave de autenticação quando usada como token.

UUID — Um rótulo sem colisão

Um UUID (Universally Unique Identifier) existe para gerar IDs que não colidam — em qualquer lugar do mundo, sem coordenação. Ele não tem nada a ver com segurança; sua única função é a identificação.

A variante mais usada, o UUID v4, é gerada aleatoriamente com 122 bits de entropia. Isso equivale a cerca de 5,3 × 1036 valores possíveis — mesmo gerando um bilhão por segundo, você esperaria mais de 10 bilhões de anos por uma colisão.

Casos de uso comuns:

  • Chaves primárias de banco de dados (alternativa ao auto-incremento)
  • IDs de objetos únicos em sistemas distribuídos
  • Nomes de arquivo sem colisão para uploads
  • IDs de requisição para rastreamento e logs
💡 Dica

o UUID v1 embute um timestamp e um endereço MAC, tornando o momento de geração e o dispositivo adivinháveis. Use o v4 (totalmente aleatório) para IDs visíveis externamente. E nunca reutilize um UUID como chave de sessão ou token — UUIDs garantem “sem colisões”, não “sem adivinhação”.

Experimente e aprenda com nosso gerador de UUID gratuito

Senha — O único segredo gerenciado por humanos

Entre os 8 tipos, as senhas são as únicas projetadas para a memorização humana. Isso torna sua entropia inerentemente dependente da memória humana — e, portanto, mais fraca do que as alternativas geradas por máquina.

É exatamente por isso que as senhas precisam de cuidado especial no armazenamento. Guardá-las em texto puro é inaceitável. Elas devem ser hasheadas, e não com qualquer hash — a boa prática moderna exige algoritmos propositalmente lentos como bcrypt, Argon2 ou scrypt.

Por que “lento” importa? Quando um atacante tenta bilhões de cálculos de hash por segundo em um ataque de força bruta, um algoritmo que leva 0,1 segundo por cálculo aumenta o custo do ataque em várias ordens de grandeza.

Casos de uso comuns:

  • Autenticação de login em serviços web
  • Credenciais de acesso a SSH e banco de dados
  • Frases-senha de criptografia para arquivos
💡 Dica

a força de uma senha é determinada por conjunto de caracteres × comprimento. Um curto P@ssw0rd com símbolos é muito mais fraco do que uma longa frase-senha como correct horse battery staple. Use sempre um gerenciador de senhas.

Experimente e aprenda com nosso gerador de senhas gratuito

Hash — Uma impressão digital

Uma função de hash recebe uma entrada de qualquer tamanho e produz uma saída de tamanho fixo — uma transformação de mão única. A mesma entrada sempre gera a mesma saída, mas você não consegue revertê-la. Pense nela como a impressão digital de um dado.

Por exemplo, o SHA-256 comprime tanto um “hello” de 5 caracteres quanto um arquivo de 1 GB em um valor de 256 bits (64 caracteres hexadecimais). Mude um único bit do dado original e o hash muda por completo.

Casos de uso comuns:

  • Armazenamento de senhas — Guardar o hash em vez do texto puro
  • Verificação de integridade de arquivos — Confirmar que downloads não foram adulterados (checksums)
  • IDs de commit do Git — O Git gerencia cada commit usando hashes SHA-1
  • Blockchain — As cadeias de transações são protegidas por hashes
💡 Dica

MD5 e SHA-1 têm ataques de colisão práticos — não os use para segurança. Escolha SHA-256 ou superior em novos projetos. Para armazenamento de senhas, não use SHA de forma alguma — é “rápido demais”, o que o torna vulnerável à força bruta. Use bcrypt ou Argon2 no lugar.

Experimente e aprenda com nosso gerador de hash gratuito

Token — Um passe temporário

Um token prova que “esta pessoa está autenticada” — temporariamente. Após um login bem-sucedido, o servidor emite um token; as requisições seguintes incluem esse token para afirmar “já estou autenticado”.

O exemplo mais famoso é o JWT (JSON Web Token), composto por três partes codificadas em Base64: cabeçalho, payload e assinatura. O payload contém o ID do usuário e a expiração, e a assinatura detecta adulterações.

Casos de uso comuns:

  • Gerenciamento de sessão de aplicações web
  • Tokens de acesso e de atualização (refresh) do OAuth 2.0
  • Links de uso único para verificação de e-mail e redefinição de senha
  • Autenticação sem estado (stateless) em SPAs
💡 Dica

os payloads de JWT são codificados em Base64 — não criptografados — então qualquer um pode ler o conteúdo. Nunca coloque senhas ou números de cartão de crédito em um JWT. Mantenha o tempo de vida dos tokens de acesso curto (15 minutos a 1 hora) e use tokens de atualização para a renovação.

Experimente e aprenda com nosso gerador de tokens gratuito

Chave de API — Uma senha para máquinas

Uma chave de API é uma string que permite a um aplicativo ou serviço dizer “sou um usuário autorizado”. Ela não é digitada por um humano — é embutida no código e anexada às requisições.

A maior diferença em relação às senhas: ninguém precisa memorizá-la. Isso permite gerar strings aleatórias suficientemente longas (128–256 bits), tornando-as muito mais fortes. O contraponto é que costumam ficar em texto puro no código-fonte ou em arquivos de configuração, criando alto risco de vazamento.

Casos de uso comuns:

  • Autenticação de APIs externas (Google Maps, OpenAI, Stripe)
  • Autenticação interna serviço-a-serviço em microsserviços
  • Identificação para cobrança e limite de taxa (rate limit)
💡 Dica

enviar chaves de API ao GitHub por engano é um problema recorrente. Guarde-as em arquivos .env ou variáveis de ambiente e adicione .env ao .gitignore — isso é inegociável. O Secret Scanning do GitHub pode revogar automaticamente algumas chaves, mas não confie nele como única proteção.

Experimente e aprenda com nosso gerador de chaves de API e tokens gratuito

Sal, Nonce e Assinatura — Os especialistas dos bastidores

Esses três raramente aparecem sozinhos — são componentes que fortalecem outros mecanismos.

Sal (Salt)

Um sal é um valor aleatório adicionado por usuário ao fazer o hash das senhas. Mesmo que dois usuários compartilhem a senha “password123”, sais diferentes produzem hashes diferentes. Isso derrota os ataques por rainbow table — dicionários de hashes pré-calculados.

Os sais não precisam ser secretos — são armazenados ao lado do hash no banco de dados. Algoritmos modernos como bcrypt e Argon2 cuidam da geração e do gerenciamento do sal internamente, de modo que os desenvolvedores raramente precisam lidar com eles manualmente.

Nonce

Nonce significa “Number used ONCE” — um valor descartável. Seu objetivo principal é a prevenção de ataques de replay. Se um atacante intercepta e reenvia uma requisição, o servidor reconhece que o nonce já foi usado e a rejeita.

No desenvolvimento web, os nonces também são usados como tokens de proteção CSRF (Cross-Site Request Forgery). A função wp_nonce_field() do WordPress é um exemplo bem conhecido.

Assinatura

Uma assinatura prova que os dados não foram adulterados. O HMAC (Hash-based Message Authentication Code) combina uma chave secreta com uma mensagem para calcular um hash. Sem a chave secreta, um terceiro não consegue produzir uma assinatura válida — assim, o destinatário pode confirmar que os dados vieram de um remetente legítimo.

O alg: HS256 em um cabeçalho JWT significa “assinado com HMAC-SHA256”. Webhooks de API (Stripe, GitHub, etc.) também usam assinaturas HMAC para detectar adulteração no corpo das requisições.

Organizando por eixos de design

Em vez de memorizar cada tipo individualmente, organize-os ao longo de 5 eixos.

TipoSecreto?Recuperável?Unicidade crítica?Expira?Uso humano?
UUID××××
Senha◎ (apenas o dono)×
Hash×× (irreversível)××
Token×
Chave de API××
Sal××××
Nonce×××
Assinatura×× (irreversível)×

Note que apenas as senhas têm ◎ em “Uso humano”. Isso destaca como as senhas são um caso fundamentalmente especial entre todos esses tipos de string.

Pensando em modelos de ataque

No design de segurança, a pergunta norteadora não é “o que estamos protegendo?”, mas “qual ataque estamos prevenindo?“. Cada tipo de string enfrenta uma ameaça diferente.

TipoAtaque a prevenirEstratégia de defesa
UUIDColisão (IDs duplicados)Entropia suficiente para tornar colisões desprezíveis
SenhaForça bruta / dicionárioHash lento + sal + senhas longas
HashAtaque de pré-imagem / colisãoUsar algoritmos seguros (SHA-256+)
TokenReplay / interceptaçãoTTL curto + HTTPS + rotação de refresh
Chave de APIVazamentoVariáveis de ambiente + rotação + restrições de IP
NonceReplayUso único + rastreamento no servidor
AssinaturaAdulteraçãoGestão rigorosa da chave secreta

Você não precisa de resistência à força bruta para UUIDs e raramente se preocupa com resistência a colisões para senhas. Ameaças diferentes exigem designs diferentes.

Um fluxo de decisão prático

Quando estiver em dúvida sobre qual tipo usar, siga este raciocínio:

  1. Defina a finalidade — Identificação? Autenticação? Verificação? Temporário?
  2. Identifique a ameaça — Colisão? Adivinhação? Vazamento? Replay? Adulteração?
  3. Determine a entropia necessária — 122 bits para UUID, 256 bits para tokens
  4. Escolha o método de geraçãoMath.random() nunca é aceitável; use módulos crypto
  5. Decida o armazenamento — Texto puro? Hasheado? Criptografado? Variável de ambiente?

O ponto 4 é crucial. Os geradores aleatórios padrão (Math.random(), random.random()) não são criptograficamente seguros. Para qualquer string ligada à segurança, use sempre um CSPRNG (gerador de números pseudoaleatórios criptograficamente seguro). Em Python, é o módulo secrets; no Node.js, crypto.randomBytes().

Resumo

Agrupados por finalidade de design, os 8 tipos se enquadram em 4 categorias:

  • Identificação: UUID
  • Autenticação: Senha, Chave de API
  • Verificação: Hash, Assinatura
  • Autenticação temporária / defesa: Token, Nonce, Sal

Elas podem parecer idênticas, mas sua finalidade de design é totalmente diferente — essa é a mensagem central deste artigo.

Como desenvolvedor, adote este princípio: “Não olhe para a string — olhe para a finalidade.” Seja projetando uma nova string aleatória ou lidando com uma existente, pergunte-se sempre primeiro “o que isto está protegendo?”. O método de geração, a abordagem de armazenamento e a política de expiração corretos seguirão naturalmente.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *