Fastway
Voltar ao blog

Mitos do Base64: por que não é criptografia e nunca foi

Rodrigo Krohling
·6 min de leitura

Base64 não tem chave.

Quase tudo que se entende errado sobre ele decorre de não ter lido essa frase, então vale dizer antes de qualquer coisa. Não existe segredo, não existe senha, não existe parâmetro que mude a saída. A mesma entrada sempre produz a mesma saída, e qualquer um — inclusive esta página — consegue reverter na hora.

Estabelecido isso, aqui estão os mitos.

Mito 1: ele protege dados

Esse é o que causa dano real. Codificar uma senha, uma chave de API ou um registro de cliente em Base64 antes de armazenar ou transmitir acrescenta exatamente zero de proteção. Torna o valor ilegível para um humano de relance, o que não é a mesma coisa que ilegível para um atacante que tem o valor.

O sinal está no formato da string. c2VuaGExMjM= é reconhecível como Base64 num olhar — o conjunto de caracteres, o tamanho múltiplo de quatro, o = no fim. Quem já viu isso antes vai decodificar antes de terminar de ler a linha em que apareceu.

Se o requisito é confidencialidade, você precisa de criptografia: uma chave, um algoritmo e um plano para onde a chave mora. Se o requisito é "fazer este binário sobreviver a um canal de texto", Base64 é exatamente certo. São requisitos diferentes, e a confusão entre eles aparece em relatórios de vazamento com regularidade deprimente.

Mito 2: ele comprime

O oposto. Base64 pega três bytes e os representa como quatro caracteres, então a saída fica cerca de 33% maior que a entrada, mais até dois caracteres de padding.

A aritmética: três bytes são 24 bits, divididos em quatro grupos de 6 bits, cada um mapeado para um de 64 caracteres imprimíveis. Quatro caracteres onde antes havia três bytes.

Isso importa ao embutir imagens como data URL. Uma imagem de 90 KB vira uns 120 KB de marcação, e diferente de um arquivo separado ela não pode ser cacheada independentemente do documento que a carrega, nem carregada em paralelo. Embutir um ícone pequeno para economizar uma requisição é razoável. Embutir uma fotografia normalmente custa mais do que economiza.

Mito 3: é um padrão único

Existem dois alfabetos em uso comum, e confundi-los produz saída corrompida em vez de um erro limpo.

O Base64 padrão (RFC 4648 §4) usa + e / nas duas últimas posições. O Base64 seguro para URL (§5) usa - e _ no lugar, porque + é lido como espaço numa query string e / é separador de caminho.

JWTs usam a variante segura para URL com o padding removido. É por isso que colar um segmento de JWT num decodificador padrão pode falhar: o decodificador quer o padding = de volta. Acrescente = até o tamanho ser múltiplo de quatro e funciona — um detalhe que vale saber quando você está inspecionando um token à mão em vez de num decodificador que já trata disso.

Mito 4: o btoa lida com texto

Ele lida com Latin-1, o que não é a mesma coisa. O btoa nativo do navegador lança InvalidCharacterError em qualquer caractere acima de U+00FF:

btoa('café');   // InvalidCharacterError
btoa('日本');    // InvalidCharacterError
btoa('👋');      // InvalidCharacterError

O motivo é que Base64 codifica bytes, e o btoa não tem ideia de qual codificação seu texto deveria virar. Você tem que decidir, o que na prática significa UTF-8:

function codificarUtf8Base64(texto) {
  const bytes = new TextEncoder().encode(texto);
  let binario = '';
  for (const b of bytes) binario += String.fromCharCode(b);
  return btoa(binario);
}

function decodificarUtf8Base64(b64) {
  const binario = atob(b64);
  const bytes = Uint8Array.from(binario, c => c.charCodeAt(0));
  return new TextDecoder().decode(bytes);
}

Todo bug de "Base64 quebra com acento" é essa etapa faltando. O codificador foi direto de caracteres para btoa sem decidir que bytes aqueles caracteres eram.

Para que ele serve de verdade

Base64 existe porque muita infraestrutura pressupõe texto. Corpos de e-mail, valores de string em JSON, cabeçalhos HTTP, documentos XML, arquivos YAML — todos lidam com ASCII imprimível de forma confiável e estragam bytes arbitrários.

Então a descrição honesta é: Base64 é um jeito de mover dado binário por um canal que só garante texto. Usos legítimos se parecem com isto:

  • Anexar um arquivo a um e-mail.
  • Embutir uma imagem pequena em CSS ou HTML como data URL.
  • Colocar uma assinatura binária dentro de um campo JSON.
  • Levar credenciais num cabeçalho HTTP Basic Auth — onde, note, a codificação não fornece segurança nenhuma, e é exatamente por isso que Basic Auth exige HTTPS.

Esse último exemplo é o assunto inteiro em miniatura. O Basic Auth codifica usuario:senha em Base64 não para escondê-los, mas porque cabeçalhos HTTP são texto e uma senha pode não ser. A confidencialidade vem inteiramente da camada de transporte por baixo.

O teste de uma linha

Se alguém propuser Base64 como medida de segurança, pergunte qual é a chave.

Não existe. Isso encerra a discussão, e é uma explicação mais rápida que qualquer teoria sobre codificação contra criptografia.