„Vou codificar em Base64 para que ninguém leia.“ Esta frase aparece em revisões de código, mensagens de Slack e respostas do Stack Overflow muito mais do que deveria. Base64 não é criptografia. Não é obfuscação. Não é segurança de espécie alguma. Decodificá-lo exige uma chamada de função e zero conhecimento de qualquer chave ou segredo. Este artigo explica o que Base64 realmente é, por que a confusão persiste e o que usar no lugar quando você de fato precisa proteger dados.
O que é Base64 de verdade
Base64 é um esquema de codificação —— um mapeamento reversível entre dados binários e um conjunto de 64 caracteres ASCII imprimíveis (A–Z, a–z, 0–9, +, /, com = como padding).
Cada 3 bytes de entrada viram 4 caracteres Base64. O algoritmo é totalmente determinístico e não exige chave:
// Codificação
btoa("hello") // → "aGVsbG8="
btoa("secret password") // → "c2VjcmV0IHBhc3N3b3Jk"
// Decodificação —— uma chamada, sem chave
atob("c2VjcmV0IHBhc3N3b3Jk") // → "secret password"É tudo. Qualquer um com acesso à string codificada pode decodificá-la instantaneamente, em qualquer linguagem, em qualquer ambiente, sem informação adicional.
Por que a confusão existe
Strings codificadas em Base64 parecem dados criptografados. Estão cheias de maiúsculas, minúsculas, números e caracteres especiais misturados, e não têm semelhança visível com a entrada original. Esse ruído visual basta para enganar um observador não técnico —— e, surpreendentemente, muitas vezes também um técnico.
O padrão também é reforçado por proximidade. Base64 aparece o tempo todo em contextos de segurança:
- Certificados HTTPS são codificados em Base64 (formato PEM)
- Tokens JWT usam codificação Base64url para header e payload
- A autenticação HTTP Basic envia credenciais como Base64
- Chaves SSH são armazenadas como Base64
- Dados criptografados costumam ser codificados em Base64 para transporte
Ver Base64 em todos esses lugares adjacentes à segurança leva os desenvolvedores a confundir codificação com segurança. A codificação é só o invólucro; a segurança vem das operações criptográficas que estão abaixo.
Codificação vs criptografia: a diferença central
A distinção é simples e absoluta:
| Codificação (Base64) | Criptografia (AES, RSA…) | |
|---|---|---|
| Propósito | Representar dados binários como texto | Ocultar dados de partes não autorizadas |
| Precisa de chave? | Não | Sim |
| Reversível por qualquer um? | Sim —— uma chamada de função | Apenas com a chave certa |
| Adiciona confidencialidade? | Não | Sim (se usada corretamente) |
| Tamanho de saída | ~33% maior que a entrada | Varia conforme o algoritmo |
A criptografia transforma dados com uma chave de modo que, sem ela, recuperar o original seja computacionalmente inviável. A codificação Base64 não tem essa propriedade.
Erros de segurança do mundo real
Guardar segredos „codificados“ no código-fonte
// ❌ Isto não é secreto —— qualquer um pode decodificar
const API_KEY = atob("c2stbGl2ZS1hYmMxMjM0NTY3ODk=");
// Qualquer um que leia este código executa:
atob("c2stbGl2ZS1hYmMxMjM0NTY3ODk=") // → "sk-live-abc123456789"Ferramentas automáticas de varredura de segredos (Secret Scanning do GitHub, GitGuardian, truffleHog) decodificam strings Base64 como parte da detecção. Se você espera que Base64 as detenha, não vai.
Autenticação HTTP Basic
// O cabeçalho Authorization fica assim:
Authorization: Basic dXNlcjpwYXNzd29yZA==
// Esse Base64 decodifica trivialmente:
atob("dXNlcjpwYXNzd29yZA==") // → "user:password"Autenticação HTTP Basic só é segura sobre HTTPS —— a camada TLS fornece a criptografia real. O Base64 no cabeçalho é puramente para codificar o par username:password como um único valor textual, não para escondê-lo. Sobre HTTP puro, qualquer um que intercepte o tráfego lê as credenciais instantaneamente.
Tratar „tokens“ JWT como segredos
// Um JWT parece três seções Base64url unidas por pontos:
eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjQyfQ.abc123
// A seção do meio (payload) decodifica para:
atob("eyJ1c2VySWQiOjQyfQ") // → '{"userId":42}'Payloads JWT não são criptografados —— são codificados em Base64url e assinados. Qualquer um que receba o token pode ler o payload. A assinatura impede adulteração, mas não fornece confidencialidade. Nunca coloque dados sensíveis (senhas, números de cartão, informações pessoais) em um payload JWT a menos que use JWE (JSON Web Encryption), que é um padrão diferente e bem menos comum.
Obfuscar dados em URLs
// Padrão comum em apps legados
/profile?data=eyJ1c2VySWQiOjQyfQ==
// Cole isto em qualquer decodificador:
atob("eyJ1c2VySWQiOjQyfQ==") // → '{"userId":42}' Base64 em URLs não acrescenta segurança alguma. Também quebra facilmente —— os caracteres + e / do Base64 padrão não são URL-safe e precisam ser percent-encoded, por isso o Base64url (+ → -, / → _, sem padding) existe como variante separada.
Para que Base64 serve de verdade
Base64 tem usos legítimos e importantes —— só que não para segurança:
- Embutir dados binários em formatos de texto —— imagens, fontes e arquivos embutidos como URIs
data:em HTML/CSS ou anexos em respostas JSON de API - Anexos de e-mail —— a codificação MIME usa Base64 para transmitir arquivos binários por protocolos que só lidam com ASCII de 7 bits
- Segurança de transporte —— alguns canais corrompem dados binários (bytes nulos, caracteres de controle); Base64 garante que o conteúdo chegue intacto
- Identificadores opacos —— codificar um ID ou cursor como Base64 sinaliza aos consumidores da API „não tente parsear isto“, embora não traga segurança
O que usar quando você realmente precisa de segurança
Se seu objetivo é impedir acesso não autorizado a dados, use uma ferramenta criptográfica de verdade:
| Objetivo | O que usar |
|---|---|
| Criptografar dados em repouso | AES-256-GCM (criptografia simétrica) |
| Criptografar dados em trânsito | TLS 1.3 (HTTPS) |
| Hash de senhas | bcrypt, scrypt ou Argon2 —— nunca SHA-256 sozinho |
| Assinar tokens | HMAC-SHA256 (como JWT HS256) ou RS256 |
| Armazenar segredos | Variáveis de ambiente, um gerenciador de segredos (Vault, AWS Secrets Manager) |
| Criptografar tokens fim-a-fim | JWE (JSON Web Encryption) —— não JWT puro |
Quando você realmente precisa de um token criptografado: JWE e JOSE
Um JWT padrão é assinado (JWS), não criptografado —— o payload pode ser lido. Se você precisa de confidencialidade dos claims, use um JWE (JSON Web Encryption, RFC 7516). JWE faz parte da família de padrões JOSE:
- Algoritmos JOSE —— criptografia de conteúdo (ex.:
A256GCM) e gestão de chaves (ex.:RSA-OAEP-256,ECDH-ES,A256KW). „alg“ escolhe como a chave de criptografia de conteúdo é empacotada; „enc“ escolhe como o payload é criptografado. - Wrapping de chave —— JWE gera uma chave de criptografia de conteúdo nova por mensagem e a envolve sob a chave do destinatário (assimétrica ou simétrica). A chave embrulhada viaja no cabeçalho do token. Isso permite criptografar o mesmo texto claro para diferentes destinatários sem recriptografar o corpo.
- Forma compacta do JWE —— cinco seções Base64url unidas por pontos (header.key.iv.ciphertext.tag), visualmente parecido com um JWT, mas com quatro pedaços em vez de três.
Escolha uma biblioteca revisada (jose, node-jose, python-jose) em vez de implementar JWE por conta própria —— as combinações de algoritmos e formatos de chave são sutis, e o downgrade silencioso para algoritmos fracos é um bug clássico do JOSE.
Um teste rápido para o seu próprio código
Pesquise na sua base de código por btoa(, atob( e Buffer.from(…, 'base64'). Para cada ocorrência, pergunte:
- Faço isso para o texto caber em um campo ou sobreviver ao transporte? → Bom.
- Faço isso para esconder dados de alguém? → Substitua por criptografia real ou controle de acesso.
Perguntas frequentes
Base64 é criptografia?
Não. Base64 é uma codificação reversível sem chave —— qualquer um pode decodificar em uma chamada (atob()). Criptografia exige uma chave e torna inviável recuperar o conteúdo sem ela.
É seguro guardar senhas ou chaves de API em Base64?
Não. A decodificação é trivial e scanners de segredos decodificam Base64 automaticamente. Use um gerenciador de segredos ou variáveis de ambiente e hashee senhas com bcrypt, scrypt ou Argon2.
Qualquer um pode ler o payload de um JWT?
Sim. Payloads JWT são codificados em Base64url e assinados, não criptografados —— qualquer um com o token pode ler todas as claims. Nunca coloque segredos em um JWT a menos que use JWE. Colar tokens em ferramentas online é arriscado; veja por que você não deve colar JSON sensível online.
Para que serve Base64 então?
Representar dados binários como texto de forma segura —— URIs data:, anexos de e-mail (MIME) e transporte por canais que só lidam com ASCII. É um invólucro, não uma medida de segurança.
Codifique e decodifique no seu navegador
Precisa inspecionar uma string Base64 agora? Codificação e decodificação Base64 no fixjson.org permite codificar ou decodificar qualquer string instantaneamente —— incluindo Unicode completo e UTF-8 —— sem instalar nada. Útil para depurar payloads JWT, inspecionar respostas de API ou ver o que se esconde dentro de uma URI data:.
- Codificar e decodificar Base64 —— instantaneamente, no navegador, sem enviar dados a nenhum servidor
- RFC 4648: o padrão Base64 —— a história e definição formal de Base64 e Base64url
- Como decodificar um JWT —— leia os claims de um token e por que decodificar não é verificar
- RFC 7519: JSON Web Token (JWT) —— como Base64url é usado no padrão JWT e considerações de segurança
- Decodificar URL —— decodifica percent-encoding de uma URL ou query string
- JSON Stringify —— codifica um valor JSON como literal de string escapada