Base32

Codifica texto ou hexadecimal em Base32 ou base32hex, com ou sem preenchimento, maiúsculas ou minúsculas, e decodifica, com linha e coluna do caractere intruso.

Entrada
Saída
J5WMHII=

Bytes em trinta e dois caracteres, e os dígitos que ficam de fora

O Base32 escreve bytes como texto, em trinta e dois caracteres que representam cinco bits cada um, então cada cinco bytes — quarenta bits — viram oito caracteres. Hello tem cinco bytes e se escreve JBSWY3DP. Escolha “Decodificar” e cole Base32, e a página devolve os bytes que ele representa: como texto, ou em hexadecimal se você puser “Bytes como” em “Hexadecimal”.

A RFC 4648, que o define, usa as vinte e seis letras maiúsculas e os dígitos de 2 a 7. A RFC dá o motivo de faltarem o 0 e o 1: quem lida com o texto pode facilmente confundir o 0 com o O, e o 1 com o l ou o I, então o alfabeto fica com as letras e deixa esses dois dígitos de fora. Além das letras, ele precisa de seis dígitos, e os seis que adota são de 2 a 7, então o 8 e o 9 também não estão nele. Ao decodificar neste alfabeto, a página recusa um 0, 1, 8 ou 9 onde ele estiver, em vez de ler um 0 como O ou um 1 como I: a RFC permite que um decodificador os leia assim, e diz que, por padrão, ele não deveria fazer isso.

Maiúsculas e minúsculas não fazem parte do valor. A RFC 4648 projetou o Base32 para um texto que precisa ser lido sem distinguir maiúsculas de minúsculas, então jbswy3dp é Hello assim como JBSWY3DP. A RFC escreve o seu alfabeto em maiúsculas, e esta página também, a menos que você ative “minúsculas”. A leitura também ignora os caracteres de espaço em qualquer lugar, quebras de linha incluídas, então um Base32 dividido em grupos ou em várias linhas é lido como se estivesse escrito de uma vez só.

Preenchimento, e os comprimentos que o Base32 pode ter

Os bytes raramente vêm em grupos completos de cinco. Os que sobram no fim, de um a quatro, ocupam dois, quatro, cinco ou sete caracteres, e a RFC 4648 preenche esse último grupo até oito com =: seis deles, quatro, três ou um. Assim, f é MY======, fo é MZXQ====, foo é MZXW6=== e foob é MZXW6YQ=, enquanto fooba, cinco bytes, enche exatamente os seus oito como MZXW6YTB.

Contados de oito em oito, então, os caracteres antes de qualquer = sempre deixam 0, 2, 4, 5 ou 7 de resto e nunca 1, 3 ou 6, já que nenhum número de bytes deixa esse resto; a página recusa um texto assim no seu último caractere em vez de lê-lo como algo mais curto. O preenchimento não diz nada que o comprimento não diga, então a página lê Base32 sem o preenchimento — JBUQ é Hi assim como JBUQ==== — e só recusa o preenchimento onde ele está presente e errado: um = no meio, com mais texto depois dele, ou o número errado de = no fim, onde a recusa diz quantos devem estar ali.

Ao codificar, o interruptor “Preenchimento” decide se os = são escritos. Ele começa ligado, porque a RFC 4648 pede preenchimento a menos que a especificação que usa o Base32 diga outra coisa, e várias dizem: o Key Uri Format, que descreve o otpauth:// URI de um código QR de 2FA, diz que o preenchimento de um segredo deveria ser omitido, e os registros NSEC3 e o IPFS não escrevem nenhum. O interruptor “minúsculas”, ao lado dele, escreve as letras em minúsculas; os dígitos e o = não têm maiúsculas nem minúsculas para trocar. Os dois interruptores só aparecem ao codificar, já que a leitura aceita qualquer combinação deles.

Outras ferramentas leem menos do que esta página. O GNU coreutils escreve Base32 com base32, e o base32hex, o segundo alfabeto, com basenc --base32hex; o módulo base64 do Python tem uma função para cada um. Todas elas escrevem o que esta página escreve ao abrir, com preenchimento e em maiúsculas. Mas o base32 -d recusa um Base32 sem preenchimento ou com as letras em minúsculas, e o b32decode do Python também recusa os dois, e só lê minúsculas quando recebe casefold=True:

# Escrever: o alfabeto padrão, depois o outro
printf 'Hi' | base32                          # JBUQ====
printf 'Hi' | basenc --base32hex              # 91KG====

# Ler de volta: com preenchimento, depois sem preenchimento, depois em minúsculas
printf 'JBUQ====' | base32 -d                 # Hi
printf 'JBUQ' | base32 -d                     # base32: invalid input
printf 'jbuq====' | base32 -d                 # base32: invalid input

# O mesmo em um script
import base64
base64.b32encode(b'Hi')                       # b'JBUQ===='
base64.b32hexencode(b'Hi')                    # b'91KG===='
base64.b32decode('JBUQ')                      # binascii.Error: Incorrect padding
base64.b32decode('jbuq====', casefold=True)   # b'Hi'

Dois alfabetos: base32 e base32hex

A RFC 4648 define um segundo alfabeto, o base32hex: os dígitos de 0 a 9, depois as letras de A a V, de modo que os caracteres dele seguem a ordem dos valores que representam, do 0 para zero ao V para trinta e um. Isso dá a ele uma propriedade que falta ao primeiro, e que a RFC aponta: comparado caractere por caractere, o texto dele fica na ordem dos bytes que representa. O byte 00 é AA====== em base32 e 00====== em base32hex, e o byte FF é 74====== e VS======; ao ordená-los como texto, o base32 põe FF primeiro, já que os dígitos vêm antes das letras, enquanto o base32hex mantém os bytes em ordem.

Os registros NSEC3 do DNSSEC usam esse alfabeto. O nome de um desses registros começa com o hash de um nome de domínio, escrito em base32hex sem preenchimento, e a RFC 5155 observa que, escritos assim, os nomes com hash ficam na mesma ordem que os hashes têm por valor. A zona de exemplo da própria RFC dá a example o hash 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom. Com base32hex escolhido, a página lê esses 32 caracteres como os 20 bytes do hash; com base32 escolhido, ela recusa o 0 — e um aviso diz que o texto é lido inteiro em base32hex, ao lado de um botão que muda para ele.

Como os mesmos bytes são um texto diferente em cada um — Hi é JBUQ==== em base32 e 91KG==== em base32hex —, o alfabeto que você escolhe vale nas duas direções, e a página nunca o troca por você. Quando um texto que você decodifica tem um caractere que o alfabeto escolhido não tem, ou termina em bits excedentes que não são zero, o que as perguntas mais abaixo explicam, enquanto o outro alfabeto lê o texto inteiro como um codificador o escreveria, um aviso diz isso ao lado de um botão que muda para esse alfabeto; o alfabeto só muda quando você clica nesse botão ou o escolhe você mesmo. Um texto que os dois leem sem problema, como ABCDEFGH, é lido no alfabeto escolhido, já que nada nele diz qual se queria.

Onde o Base32 aparece: segredos de 2FA, endereços onion e IPFS

No Key Uri Format, que descreve o otpauth:// URI que um código QR de configuração pode conter, o segredo por trás dos códigos de um app de autenticação é escrito em Base32: o parâmetro secret do URI é Base32, e o preenchimento deveria ficar de fora. Cole um segredo assim em maiúsculas ou minúsculas, em grupos separados por espaços ou em várias linhas, com ou sem = — um hífen entre grupos é recusado onde estiver — ou cole o URI inteiro, e a página lê o segredo que está nele e diz isso. O que significam os outros parâmetros do URI, e como um segredo vira os códigos que um app mostra, ficam por conta do Depurador de códigos TOTP / 2FA: o guia dele explica o URI e os parâmetros, e a página dele calcula os códigos. O rótulo e o emissor no URI estão codificados em porcentagem, como pede o Key Uri Format, e o Codificador / decodificador de URL os lê.

Um endereço onion da versão 3 do Tor também é Base32. Os 56 caracteres dele antes de .onion são o Base32 de 35 bytes: a chave pública de 32 bytes do serviço, uma soma de verificação de dois bytes e um byte de versão, 03. A especificação do Tor escreve os endereços de exemplo dela em minúsculas, e 35 bytes enchem grupos completos, então não há preenchimento a omitir. Cole os 56 caracteres sem .onion, ponha “Bytes como” em “Hexadecimal”, e o último byte aparece como 03.

O IPFS escreve os seus identificadores de conteúdo, os CIDs, em Base32 por padrão a partir da versão 1: em minúsculas e sem preenchimento, depois de uma letra, b, que não faz parte do Base32 mas o nomeia — o prefixo do multibase, que é retirado antes de o resto ser decodificado. Assim, bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi, o exemplo da própria documentação do IPFS, é recusado aqui inteiro, como um comprimento que nenhum byte produz; sem o b, ele é lido como 36 bytes, o CID binário, que começa com 01 para a versão.

Um segredo de 2FA é feito de bytes, não de texto

O segredo de exemplo do Key Uri Format é JBSWY3DPEHPK3PXP, e esse documento detalha o valor dele como dez bytes: os caracteres de Hello!, e depois DE AD BE EF. Os oito primeiros caracteres dele, JBSWY3DP, são Hello por si sós. Decodificado aqui com “Bytes como” em “Texto”, o padrão da página, ele sai como Hello!, depois U+07AD — DE AD formam por acaso um caractere, uma marca combinante da escrita Thaana — e depois dois U+FFFD, cada um representando uma sequência que não é texto. Um aviso abaixo do resultado conta as sequências substituídas, diz que a primeira começa no byte 9, cujos bits começam no caractere da linha 1, coluna 13, o 3, e diz que pode ser que os bytes nem sejam texto.

Um segredo real é feito de bytes aleatórios, que raramente formam texto, então, decodificado como texto, ele vira um amontoado de caracteres soltos e U+FFFD que não diz nada sobre se o segredo está certo. É para isso que serve a opção “Hexadecimal” de “Bytes como”. Escolha essa opção, ou clique no botão ao lado do aviso, e o mesmo segredo aparece inteiro como 48 65 6C 6C 6F 21 DE AD BE EF: os próprios bytes, que são o que um servidor guarda e aquilo a partir do qual cada código é calculado. A página nunca muda para hexadecimal por conta própria, então o que está na tela é sempre o que você escolheu.

No sentido contrário, é a mesma escolha, feita ao codificar. Uma chave que um servidor guarda em hexadecimal é feita de bytes: escolha “Codificar”, ponha “Bytes como” em “Hexadecimal” e cole a chave — com espaços ou tudo junto, com 0x antes dos bytes, como um array de números ou como um despejo hexadecimal na disposição do hexdump -C ou do xxd — e a página escreve o Base32 que um app de autenticação aceita. 48656C6C6F21DEADBEEF sai como JBSWY3DPEHPK3PXP, o segredo acima; dez bytes enchem grupos completos, e uma chave que não os enche, como uma de dezesseis bytes, sai com = depois dela, a menos que você desligue o preenchimento, como pede o Key Uri Format. Hexadecimal colado por engano ao decodificar — um número par de dígitos hexadecimais e nada além de caracteres de espaço, numa forma que a codificação consegue ler como bytes — recebe um aviso de que parece hexadecimal, ao lado de um botão que passa a codificá-lo. E, ao decodificar, “Baixar” salva os próprios bytes como um arquivo chamado bytes.bin.

Base32 ou Base64, e por que não o alfabeto de Crockford

O Base64 faz o mesmo trabalho com sessenta e quatro caracteres, quatro para cada três bytes, o que deixa o texto dele um terço mais longo que os bytes, enquanto o do Base32 é três quintos mais longo. Em troca, o Base64 abre mão de poder ignorar maiúsculas e minúsculas: o alfabeto dele tem as maiúsculas e as minúsculas como valores diferentes, além de + e /, então SGk= é Hi e sgk= são outros dois bytes. O Base32 serve para um texto que passa por algo que ignora maiúsculas e minúsculas, ou que uma pessoa lê em uma tela e digita em outra. Quando o Base64 colado aqui tem um + ou um /, que nenhum Base32 escreve, e tem a forma de Base64 do começo ao fim, ele é recusado com um aviso de que parece Base64 e um link para a ferramenta Base64, que lê Base64 como texto.

Existem outros alfabetos de trinta e dois caracteres, e esta página oferece os dois da RFC 4648 e nenhum outro. Um deles é o de Douglas Crockford, que mantém todos os dez dígitos e deixa de fora I, L, O e U, e que o formato ULID usa. Crockford o definiu para escrever números, e, escrito sobre bytes, ele tem duas respostas: os dezesseis bytes de 00 a 0F, empacotados cinco bits por vez como a RFC 4648 empacota bytes, são 000G40R40M30E209185GR38E1W, e, lidos como um número de 128 bits, como são lidos os vinte e seis caracteres de um ULID, eles são 00041061050R3GG28A1C60T3GF. Uma página que escrevesse bytes nele estaria escolhendo uma das duas por você, sem que você visse.

Perguntas frequentes

Por que o meu segredo decodificado mostra U+FFFD?
Porque um segredo de 2FA é feito de bytes aleatórios, e bytes aleatórios raramente são texto UTF-8. Com “Bytes como” em “Texto”, a página escreve cada sequência que não é texto como U+FFFD, o caractere de substituição, e um aviso diz quantas houve e onde começa a primeira, como byte e como a linha e a coluna do caractere em que começam os bits dela. Os próprios bytes ficam intactos: o botão ao lado do aviso os mostra em hexadecimal, e “Baixar” os salva. Um U+FFFD que está de fato em um texto, os bytes EF BF BD, é lido como texto e não é contado.
O que significa “um comprimento que nenhum byte produz”?
Contados de oito em oito, os caracteres de um Base32, deixando de lado qualquer =, deixam 0, 2, 4, 5 ou 7 de resto, sejam quais forem os bytes, então um texto que deixa 1, 3 ou 6 não pode representar byte nenhum, e a página o recusa no seu último caractere. Um texto assim não foi escrito desse jeito por um codificador: algo se perdeu ou foi acrescentado no caminho até você. JBSWY3DPEHPK3P, o segredo do Key Uri Format com dois caracteres a menos, é recusado ali. Um corte também pode cair em um comprimento que os bytes de fato produzem, e então o texto é lido como menos bytes — JBSWY3DPEHPK3PX como nove —, o que a página só consegue perceber onde os bits excedentes do último caractere não são zero, como os desse X. Um corte em um grupo completo de oito não deixa nada para perceber.
O que são bits excedentes, e por que a página diz que os meus não são zero?
Cinco bits por caractere e oito por byte raramente fecham a conta, então, a menos que os bytes venham em grupos de cinco, o último caractere carrega de um a quatro bits que nenhum byte contém, e um codificador os escreve como zeros. MZXW6YQ= e MZXW6YR= são ambos foob: os três últimos bits de Q são 000 e os de R são 001, e só o primeiro é o que um codificador escreve. A página lê os dois, e, para o segundo, o aviso dela nomeia o R, onde ele está e o Q que um codificador escreve ali. Bits excedentes que não são zero significam que o texto não é o que um codificador escreveu: ele pode ter sido cortado, editado à mão ou escrito no outro alfabeto, e esta última possibilidade a página verifica para você.
Base32 é criptografia?
Não. O Base32 muda a forma como os bytes são escritos e nada mais: qualquer um pode decodificá-lo, e todo decodificador que segue a RFC 4648 recupera os mesmos bytes no mesmo alfabeto. Um segredo de 2FA escrito em Base32 é o próprio segredo, então quem vê a chave de configuração tem em mãos o seu segundo fator.
Alguma coisa do que colo é enviada para um servidor?
Não. As duas direções rodam nesta página, no seu próprio dispositivo: nada do que você cola — um segredo, um texto ou hexadecimal — é enviado, e o arquivo que “Baixar” salva é criado no seu navegador a partir dos bytes que já estão lá.

Ferramentas relacionadas

  • Base64

    O Base64 escreve quatro caracteres a cada três bytes, enquanto o Base32 escreve oito a cada cinco, e no Base64 ser maiúscula ou minúscula faz parte do valor de uma letra: abc é YWJj naquela página, e YWJJ é lido lá como abI.

  • Depurador de códigos TOTP / 2FA

    Gere e depure códigos 2FA, com a derivação completa.

  • Codificador / decodificador de URL

    Codificação percentual de um valor ou de um URL inteiro, e ao contrário.

  • Escape / unescape de strings JSON

    Faça escape de texto para uma string JSON, ou leia uma com escape.