Pular para o conteúdo principal

Como funciona o Base64

O Base64 converte dados binários em texto para que possam trafegar por canais que só aceitam caracteres. A RFC 4648 define o mecanismo: a cada 3 bytes — 24 bits — correspondem 4 caracteres de um alfabeto de 64 símbolos, com preenchimento em = quando os bytes não se dividem por igual. Os dados crescem cerca de um terço, e trata-se de uma codificação, não de criptografia.

Só local

Como funciona o Base64: explicação

Os sistemas de e-mail dos anos 1980 transportavam texto de 7 bits e nada mais; cabeçalhos HTTP, campos JSON, URLs e arquivos de log são, na prática, territórios exclusivamente textuais. Binário puro — uma imagem, uma assinatura, uma chave criptográfica — se corrompe no instante em que um canal desses o encontra. O Base64 é a ponte padrão: uma forma totalmente reversível de soletrar bytes arbitrários usando apenas 64 caracteres imprimíveis e seguros.

Você já leu Base64 o dia inteiro sem perceber: cada JWT são três segmentos Base64url, cada data: URI embutida em CSS, cada anexo de e-mail MIME. O esquema é especificado na RFC 4648 — que consolidou as definições anteriores de Base-64 em um único documento — e é pequeno o bastante para ser calculado à mão. É exatamente isso que este guia faz, um grupo de 24 bits por vez.

Três coisas confundem todo mundo no começo: por que 3 bytes viram 4 caracteres, para que servem os sinais de = e por que existem dois alfabetos. Cada uma ganha uma seção própria abaixo, junto com os limites sinceros — a penalidade de tamanho, as divergências entre decodificadores quanto a espaços em branco e o erro persistente de tratar uma codificação reversível como segurança.

Aqui, ler vale mais do que descrever — cole qualquer string em o decodificador de Base64 e veja os bytes que ela esconde; a decodificação acontece localmente, então tokens e chaves permanecem na sua aba.

O consumidor de Base64 mais famoso é o formato de tokens; o guia de estrutura do JWT mostra como os três segmentos de um JWT se apoiam no alfabeto seguro para URLs definido abaixo.

O mecanismo: 3 bytes entram, 4 caracteres saem

Pegue quaisquer dados binários e fatie-os em grupos de 3 bytes — 24 bits. Divida cada grupo em quatro blocos de 6 bits. Cada bloco é um número de 0 a 63, e o alfabeto da RFC 4648 mapeia esses números em caracteres: A–Z para 0–25, a–z para 26–51, 0–9 para 52–61 e, por fim, + e / para 62 e 63. Seis bits é o ponto ideal, porque 2⁶ = 64 é exatamente o tamanho de um alfabeto que qualquer canal só de caracteres transporta sem reclamação.

O exemplo clássico é o próprio vetor de teste da RFC, a palavra Man — três bytes, sem necessidade de preenchimento:

Byte a byte

M   0x4D   01001101
a   0x61   01100001
n   0x6E   01101110

joined:    010011 010110 000101 101110
indexes:      19     22      5      46

Caractere a caractere

19→T   22→W   5→F   46→u

"Man"  →  TWFu
"Ma"   →  TWE=
"M"    →  TQ==

Preenchimento: o que significam os sinais de =

Blocos de 6 bits só se remontam em bytes em grupos completos de quatro. Quando o comprimento da entrada não é múltiplo de 3, o grupo final fica curto: 2 bytes restantes produzem três caracteres mais um sinal de =, e 1 byte restante produz dois caracteres mais ==. O preenchimento restaura o comprimento para que o decodificador calcule a contagem exata de bytes sem adivinhar — e o = é o único caractere fora do alfabeto de 64 símbolos que pode aparecer na saída.

O preenchimento é metadado de comprimento, não segurança nem compressão. A RFC 4648 permite variantes sem preenchimento quando ambas as partes concordam — o Base64url dos JWTs, notoriamente, descarta o = por completo, porque os pontos delimitam os segmentos e o comprimento de cada segmento dá ao decodificador tudo o que ele precisa.

Bytes de entradaCaracteres de saídaPreenchimentoExemplo
3 (qualquer múltiplo de 3)4 por 3 bytesnenhum"Man" → TWFu
23um ="Ma" → TWE=
12dois =="M" → TQ==
1216nenhum"Hello, world" → SGVsbG8sIHdvcmxk

Os dois alfabetos: padrão e seguro para URLs

O alfabeto padrão usa + e / — inofensivos em e-mail, hostis em URLs, onde + é decodificado como espaço e / como separador de caminho. Por isso a RFC 4648 §5 define o Base64url, substituindo + por - e / por _: caracteres que dispensam codificação percentual em URLs e aspas em nomes de arquivo ou cookies. Fora isso, os dois dialetos são idênticos — mesmos blocos de 6 bits, mesmas regras de preenchimento.

Aí está a armadilha prática: os dialetos diferem em apenas dois caracteres, então um token colado com o alfabeto errado falha no segundo caractere — ou pior, decodifica para bytes diferentes se por acaso contiver + ou /. Decodificadores bem-comportados aceitam qualquer uma das formas e informam qual viram; os estritos recusam alfabetos misturados de cara, em vez de adivinhar.

ValoresPadrãoSeguro para URLs
0–25A–ZA–Z
26–51a–za–z
52–610–90–9
62+-
63/_

Mesmos bytes, dois dialetos

bytes:    0xFB 0xEF 0xBE

standard:  ++++
url-safe:  ----

Onde os dialetos atrapalham

em uma query de URL, ++++ chega como quatro espaços
(regra do mais como espaço) — ---- chega intacto.
É por isso que os tokens usam o alfabeto seguro para URL.

Tamanho: o imposto de um terço e suas letras miúdas

Quatro caracteres carregam três bytes, então a saída codificada é sempre 4/3 da entrada — cerca de 33% a mais — antes de qualquer overhead de transporte. Para ancorar em números: 100 bytes viram 136 caracteres, 17 bytes viram 24, e a proporção nunca muda, porque é aritmética, não ajuste fino. Preenchimento, quebras de linha e quebra de linhas longas adicionam mais: o MIME limita linhas de Base64 a 76 caracteres e exige quebras CRLF entre elas, o que acrescenta um extra pequeno em payloads grandes. Uma data: URI embute essa forma já inflada dentro de CSS ou HTML, e é por isso que imagens embutidas pesam cerca de um terço a mais do que os arquivos binários que substituem.

Nada de reversível encolhe dados, e o Base64 não é exceção — é uma mudança de grafia, não compressão. Se o tamanho importa, comprima primeiro e codifique os bytes comprimidos; nunca na ordem inversa.

Espaços em branco, quebras de linha e divergências entre decodificadores

A RFC 4648 é rigorosa: os decodificadores devem rejeitar caracteres fora do alfabeto, e o próprio documento nada diz sobre exigir quebras de linha. O Base64 do MIME (RFC 2045) espera o oposto — CRLF a cada 76 caracteres. As implementações reais se espalham entre os polos: muitas removem espaços em branco silenciosamente, algumas os exigem, outras rejeitam qualquer quebra de linha. Essa é a razão clássica de uma string que 'codifica bem' em uma ferramenta não decodificar em outra.

A regra honesta de interoperabilidade: produza Base64 padrão, com preenchimento e sem quebras, a menos que uma especificação diga o contrário, e construa decodificadores que tolerem os espaços em branco que outras ferramentas adicionam — ainda assim recusando qualquer caractere que não faça parte de um alfabeto reconhecido, porque a tolerância nesse ponto é como começa a corrupção silenciosa de bytes.

O que o Base64 não é

O Base64 não tem chave, nem rodadas de mistura, nem segredo: qualquer pessoa pode reverter, e decodificadores vêm na biblioteca padrão de toda linguagem. Tratar um payload codificado como dado protegido é um relatório de vulnerabilidade recorrente. As pistas são públicas: SGVsbG8= soletra Hello, JVBERi0x abre um PDF, /9j/ começa um JPEG, e eyJ começa quase todo JSON Web Token — esses primeiros caracteres são simplesmente o Base64 de %PDF-, dos magic bytes do JPEG e de uma chave de abertura JSON.

Use o Base64 pelo que ele é: uma grafia de bytes segura para qualquer contêiner. Deixe a confidencialidade para a criptografia de verdade — TLS em trânsito, uma cifra adequada em repouso — e mantenha o Base64 como o passo final que torna o resultado imprimível, nada além disso.

Começos que entregam

SGVsbG8sIHdvcmxk
JVBERi0xLjQ=
/9j/
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

No que decodificam

Hello, world
%PDF-1.4
(bytes FF D8 FF: o número mágico de um JPEG)
{"alg":"HS256","typ":"JWT"}

Perguntas frequentes

É seguro colar tokens e chaves em um decodificador de Base64?

Neste site, sim: o decodificador roda no seu navegador e nunca transmite a sua entrada — não há endpoint de envio de onde algo possa vazar. O painel Network não mostra nenhuma requisição enquanto você decodifica, e a Content-Security-Policy do site bloqueia conexões de saída. Isso importa porque tokens em Base64 são credenciais ativas, e muitos decodificadores aleatórios da web são bem menos cuidadosos com o que acontece com elas.

Base64 é criptografia?

Não — é uma codificação sem chave e sem nenhuma propriedade de sigilo. Qualquer biblioteca, e qualquer pessoa atenta, pode revertê-lo instantaneamente; uma senha codificada é uma senha visível. Criptografia transforma os dados para que fiquem ilegíveis sem uma chave, enquanto o Base64 apenas reescreve os bytes para que canais só de texto possam transportá-los. As duas resolvem problemas diferentes e costumam aparecer juntas.

Por que a saída do Base64 termina com sinais de =?

O = é preenchimento que restaura o comprimento. A saída vem em grupos de 4 caracteres, e quando a entrada não era múltiplo de 3 bytes o grupo final é completado — um = para dois bytes que sobraram, dois para um, nunca três, porque um grupo completo não precisa de nenhum. Os sinais não carregam dado algum; dizem ao decodificador a contagem exata de bytes.

Qual é a diferença entre Base64 e Base64url?

Dois caracteres. O Base64url, definido na RFC 4648 §5, substitui + por - e / por _, para que a saída seja segura em URLs, nomes de arquivo e cookies sem escapamento. Todo o resto — o agrupamento de 6 bits, as letras e os dígitos, as regras de preenchimento — é idêntico, e formatos como JWTs usam a variante segura para URLs com o preenchimento removido.

Por que a saída do Base64 é maior do que a entrada?

Cada caractere de saída carrega 6 bits, enquanto um byte carrega 8, então 3 bytes — 24 bits — exigem 4 caracteres: um 4/3 fixo, ou cerca de 33% de overhead, antes do preenchimento e das quebras de linha. É o preço de continuar imprimível; nenhuma codificação reversível escapa disso, e é por isso que o transporte de binário puro vence onde o canal permite bytes de verdade.

Dá para decodificar Base64 à mão?

Sim — o design convida a isso. Escreva os bytes da entrada em binário, reagrupe cada bloco de 24 bits em quatro blocos de 6 bits e leia cada bloco na tabela do alfabeto: A=0 até Z=25, a=26 até z=51, 0=52 até 9=61 e, por fim, + e /. O exemplo da própria RFC funciona no papel: Man é 010011 010110 000101 101110, que lê T, W, F, u — TWFu.

Onde posso ler os padrões citados aqui?

  • RFC 4648 — As codificações de dados Base16, Base32 e Base64
  • RFC 2045 — MIME, parte um: formato do corpo das mensagens da internet