Enviar um arquivo
  1. base64hub
  2. Aprenda Base64
  3. Como o Base64 funciona
Explicação

Como o Base64 funciona, byte a byte

O Base64 reescreve quaisquer bytes usando 64 caracteres seguros. Entram três bytes, saem quatro caracteres, e o resto é contabilidade.

O que é Base64 e por que ele existe

Base64 é um jeito de escrever dados binários arbitrários usando apenas 64 caracteres ASCII imprimíveis: A–Z, a–z, 0–9, + e /, mais = para preenchimento. É uma codificação, ou seja, qualquer pessoa pode revertê-la sem chave. Ele não esconde nada (mais sobre isso em codificação vs criptografia).

O objetivo é fazer os bytes passarem intactos por canais que só aceitam texto. Um arquivo PNG contém bytes como 0x00, 0x1A e 0x89 que um canal de texto pode remover, traduzir ou tratar como código de controle. Escrito em Base64, o mesmo arquivo vira iVBORw0KGgo..., que passa intacto por e-mail, JSON, XML, URLs (com a variante URL-safe), terminais e copiar e colar.

A definição atual é a RFC 4648. Especificações mais antigas para e-mail MIME (RFC 2045) e certificados PEM descrevem o mesmo alfabeto com regras extras sobre o tamanho das linhas. Um resumo das variantes está na página de padrões do Base64.

Por que o e-mail precisou dele

O e-mail dos primeiros tempos foi projetado para texto ASCII de 7 bits. Os servidores de retransmissão da época podiam remover o bit mais alto de cada byte, quebrar linhas longas e reescrever os finais de linha, o que é inofensivo para uma carta e fatal para um arquivo ZIP. O MIME precisava de um jeito de levar qualquer anexo por esse caminho, e precisava de um alfabeto que sobrevivesse a todos os sistemas no trajeto.

O Base64 escolhe seus 64 caracteres por isso. Letras e dígitos são idênticos no ASCII e em quase todos os conjuntos de caracteres legados, + e / são quase tão seguros, e nenhum deles é caractere de controle ou espaço em branco. 64 também é a maior potência de dois que dá para preencher com esse conjunto seguro, e uma potência de dois mantém a aritmética de bits simples. O custo é o tamanho: 6 bits úteis por caractere de 8 bits significam que a saída tem 4/3 da entrada, mais o preenchimento.

O problema dos 8 bits quase sumiu dos servidores de e-mail modernos, mas a mesma restrição aparece em qualquer lugar onde dados binários precisam ficar dentro de um formato de texto. O JSON não tem tipo binário, e atributos HTML, CSS e headers HTTP são todos texto, então o Base64 continua sendo o jeito padrão de colocar bytes neles.

O algoritmo: entram 3 bytes, saem 4 caracteres

O Base64 trabalha com blocos de 24 bits. Esse é o menor número divisível tanto por 8 (um byte) quanto por 6 (um caractere Base64), então 3 bytes correspondem exatamente a 4 caracteres.

Para cada bloco:

  1. Pegue 3 bytes e escreva-os como 24 bits em sequência.
  2. Corte esses 24 bits em quatro grupos de 6 bits.
  3. Leia cada grupo como um número de 0 a 63.
  4. Procure o número no alfabeto e escreva aquele caractere.

O alfabeto é uma tabela fixa. O índice 0 é A, 25 é Z, 26 é a, 51 é z, 52 é 0, 61 é 9, 62 é + e 63 é /. A tabela completa está na página do alfabeto Base64.

FaixaCaracteresExemplo
0–25A–Z19 → T
26–51a–z46 → u
52–610–952 → 0
62+
63/

A decodificação faz os mesmos passos ao contrário: procura cada caractere para obter 6 bits, junta quatro deles em 24 bits e divide isso em 3 bytes.

Exemplo prático: “Man” vira TWFu

O exemplo clássico usa o texto ASCII Man. Em ASCII, M é 77, a é 97 e n é 110.

Man
Decimal7797110
Binário010011010110000101101110

Junte os bits: 010011010110000101101110. Agora corte a cada 6 bits em vez de a cada 8:

Grupo de 6 bits010011010110000101101110
Valor1922546
CaractereTWFu

Então Man vira TWFu. Repare que nenhum caractere de saída se alinha com uma letra de entrada. O W é formado pelos últimos 4 bits de M e pelos 2 primeiros bits de a. É por isso que mudar um byte da entrada muda dois caracteres da saída, e por isso não dá para ler Base64 a olho nu mesmo quando a entrada é texto comum.

Dá para conferir em qualquer shell:

echo -n Man | base64
# TWFu

Sem -n, o echo acrescenta um byte de quebra de linha, e Man\n vira TWFuCg==.

Quando a entrada não é múltiplo de 3: preenchimento

Dados reais raramente têm comprimento divisível por 3. O último bloco fica então com 1 ou 2 bytes, e o Base64 o completa com bits zero e sinais =.

Sobram dois bytes, “Ma” → TWE=. Dois bytes são 16 bits. Acrescente dois bits zero para chegar a 18, que são três grupos de 6 bits:

Grupo de 6 bits010011010110000100(nenhum)
Valor19224
CaractereTWE=

O terceiro grupo é 0001 vindo de a seguido dos dois zeros acrescentados, o que dá 4, ou seja, E. Um = ocupa o lugar do quarto caractere ausente.

Sobra um byte, “M” → TQ==. Um byte são 8 bits. Acrescente quatro bits zero para chegar a 12, que são dois grupos: 010011 (19, T) e 010000 (16, Q). Dois sinais = completam o bloco.

Assim, o número de sinais = diz quantos bytes o último bloco tinha: nenhum significa 3, um significa 2, dois significam 1. Nunca existe um terceiro =, porque um bloco com zero bytes restantes não existe. O guia de preenchimento explica quando o = pode ser omitido e como recolocá-lo.

import base64
for s in [b"Man", b"Ma", b"M"]:
    print(s, base64.b64encode(s))
# b'Man' b'TWFu'
# b'Ma' b'TWE='
# b'M' b'TQ=='

O texto precisa virar bytes primeiro

O Base64 codifica bytes. O texto só vira bytes depois que você escolhe uma codificação de caracteres, e essa escolha muda o resultado. A palavra café em UTF-8 tem 5 bytes (o é ocupa dois), então vira Y2Fmw6k=. Em Latin-1 ela tem 4 bytes e vira Y2Fm6Q==.

Essa é a origem de uma armadilha famosa do JavaScript. A função btoa() do navegador trata cada caractere de uma string como um byte, o que é o comportamento do Latin-1:

btoa("café");        // "Y2Fm6Q==" (Latin-1, not UTF-8)
btoa("café ✓");      // throws InvalidCharacterError

Para obter Base64 de UTF-8 em JavaScript, converta para bytes antes com TextEncoder, ou use Buffer no Node.js. A página de código JavaScript mostra os padrões que funcionam, e Uint8Array.toBase64() cobre o método nativo mais novo. O codificador Base64 deste site usa UTF-8 por padrão e permite escolher outro charset.

Onde você encontra Base64

  • Anexos de e-mail. Todo anexo num arquivo .eml bruto é um bloco Base64 quebrado a cada 76 caracteres. Veja Base64 no e-mail.
  • Data URIs. data:image/png;base64,iVBORw0KGgo... embute uma imagem diretamente no HTML ou CSS. Quando isso compensa é o tema de desempenho de data URIs.
  • HTTP Basic Auth. O header Authorization: Basic dXNlcjpwYXNz é só user:pass em Base64.
  • JWTs. As três partes separadas por pontos de um JSON Web Token são Base64URL. Veja Base64 no JWT.
  • Arquivos PEM. Certificados e chaves entre as linhas -----BEGIN ...----- são Base64 de dados DER binários.
  • APIs e configuração. Secrets do Kubernetes, metadados de nuvem, payloads de webhooks e muitas APIs JSON transportam arquivos ou blobs binários como strings Base64.

Com o tempo você passa a reconhecer os blobs pelos primeiros caracteres: iVBORw0KGgo é um PNG, JVBERi0 é um PDF, /9j/ é um JPEG e eyJ é um JSON começando com {". A página de prefixos comuns de Base64 lista outros. Para ver o que um blob contém, a ferramenta Base64 para arquivo detecta o formato e mostra uma prévia no seu navegador.

Decodifique uma string agora

Cole o Base64 e veja o texto ou os bytes que ele contém. Roda localmente no seu navegador.

Decodificador Base64

Perguntas frequentes

O Base64 é uma forma de compressão?

Não. Ele sempre deixa os dados maiores: cada 3 bytes de entrada viram 4 caracteres de saída, cerca de 33% a mais. Veja o acréscimo de tamanho do Base64 para a fórmula exata.

Por que se chama Base64?

Cada caractere de saída carrega um de 64 valores possíveis, o que equivale a 6 bits de informação. O nome é o tamanho do alfabeto, do mesmo jeito que hex é base 16.

Qualquer dado pode ser codificado em Base64?

Sim. O algoritmo trabalha com bytes e não se importa com o que eles significam, então texto, imagens, PDFs, chaves e arquivos compactados são codificados do mesmo jeito. O texto precisa antes virar bytes por meio de uma codificação de caracteres, geralmente UTF-8.

A saída do Base64 pode conter espaços ou quebras de linha?

O Base64 puro da RFC 4648, não. Alguns formatos o quebram em linhas, por exemplo o e-mail MIME a cada 76 caracteres e os arquivos PEM a cada 64, e a maioria dos decodificadores ignora esses espaços em branco.

Continue lendo