Base32

Codifica testo o esadecimale in Base32 o base32hex, con o senza riempimento, maiuscolo o minuscolo, e lo decodifica, con riga e colonna del carattere estraneo.

Input
Output
INUWC3Y=

Byte in trentadue caratteri, e le cifre lasciate fuori

Base32 scrive i byte come testo, in trentadue caratteri che rappresentano cinque bit ciascuno, quindi ogni cinque byte — quaranta bit — diventano otto caratteri. Hello occupa cinque byte e si scrive JBSWY3DP. Scegli «Decodifica» e incolla del Base32, e la pagina restituisce i byte che rappresenta: come testo, o in esadecimale se imposti «Byte come» su «Esadecimale».

La RFC 4648, che lo definisce, usa le ventisei lettere maiuscole e le cifre da 2 a 7. La RFC dà il motivo per cui mancano 0 e 1: chiunque maneggi il testo può facilmente scambiare 0 per O, e 1 per l o I, quindi l’alfabeto tiene le lettere e lascia fuori quelle due cifre. Oltre alle lettere gli servono sei cifre, e le sei che prende sono da 2 a 7, quindi nemmeno 8 e 9 ne fanno parte. Quando decodifica in questo alfabeto, la pagina rifiuta uno 0, un 1, un 8 o un 9 nel punto in cui si trova, invece di leggere uno 0 come O o un 1 come I: la RFC consente a un decodificatore di leggerli così, e dice che per impostazione predefinita non dovrebbe farlo.

La distinzione tra maiuscole e minuscole non fa parte del valore. La RFC 4648 ha progettato Base32 per un testo che va letto senza badare a maiuscole e minuscole, quindi jbswy3dp è Hello proprio come JBSWY3DP. La RFC scrive il suo alfabeto in maiuscolo, e così fa questa pagina, a meno che tu non attivi «minuscolo». La lettura salta anche i caratteri di spaziatura ovunque si trovino, compresi gli a capo, quindi un Base32 diviso in gruppi o su più righe si legge come se fosse scritto tutto di seguito.

Il riempimento, e le lunghezze che Base32 può avere

I byte arrivano raramente in multipli esatti di cinque. Da uno a quattro byte rimasti alla fine occupano due, quattro, cinque o sette caratteri, e la RFC 4648 riempie quell’ultimo gruppo fino a otto con segni =: sei, quattro, tre o uno. Così f è MY======, fo è MZXQ====, foo è MZXW6=== e foob è MZXW6YQ=, mentre fooba, cinque byte, riempie esattamente i suoi otto caratteri come MZXW6YTB.

Contati a otto a otto, quindi, i caratteri che precedono un eventuale = lasciano sempre un resto di 0, 2, 4, 5 o 7 e mai di 1, 3 o 6, perché nessun numero di byte lascia quei resti; la pagina rifiuta un testo del genere al suo ultimo carattere invece di leggerlo come qualcosa di più corto. Il riempimento non dice nulla che la lunghezza non dica già, quindi la pagina legge il Base32 senza riempimento — JBUQ è Hi proprio come JBUQ==== — e rifiuta il riempimento solo dove c’è ed è sbagliato: un = nel mezzo, con altro testo dopo, o un numero sbagliato di = alla fine, dove il rifiuto dice quanti ne servono.

Quando codifichi, l’interruttore «Riempimento» decide se i segni = vengono scritti. All’inizio è attivo, perché la RFC 4648 chiede il riempimento a meno che la specifica che la adotta non dica altrimenti, e diverse lo fanno: il Key Uri Format, che descrive l’otpauth:// URI di un codice QR per la 2FA, dice che il riempimento di un segreto andrebbe omesso, e i record NSEC3 e IPFS non ne scrivono. L’interruttore «minuscolo» lì accanto scrive le lettere in minuscolo; le cifre e il segno = non hanno maiuscole o minuscole da cambiare. Entrambi gli interruttori compaiono solo durante la codifica, perché la lettura accetta ogni loro combinazione.

Altri strumenti leggono meno di questa pagina. GNU coreutils scrive Base32 con base32, e base32hex, il secondo alfabeto, con basenc --base32hex; il modulo base64 di Python ha una funzione per ciascuno. Tutti scrivono ciò che questa pagina scrive all’apertura, con riempimento e in maiuscolo. Ma base32 -d rifiuta un Base32 a cui manca il riempimento o le cui lettere sono minuscole, e anche b32decode di Python rifiuta entrambi i casi, leggendo le minuscole solo quando gli si passa casefold=True:

# Scrivere: l’alfabeto predefinito, poi l’altro
printf 'Hi' | base32                          # JBUQ====
printf 'Hi' | basenc --base32hex              # 91KG====

# Rileggere: con riempimento, poi senza riempimento, poi in minuscolo
printf 'JBUQ====' | base32 -d                 # Hi
printf 'JBUQ' | base32 -d                     # base32: invalid input
printf 'jbuq====' | base32 -d                 # base32: invalid input

# Lo stesso in uno 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'

Due alfabeti: base32 e base32hex

La RFC 4648 definisce un secondo alfabeto, base32hex: le cifre da 0 a 9, poi le lettere da A a V, così i suoi caratteri si susseguono nell’ordine dei valori che rappresentano, da 0 per zero a V per trentuno. Questo gli dà una proprietà che al primo manca, e che la RFC fa notare: ordinato carattere per carattere, il suo testo segue l’ordine dei byte che rappresenta. Il byte 00 è AA====== in base32 e 00====== in base32hex, e il byte FF è 74====== e VS======; ordinando i testi, base32 mette FF per primo, perché le cifre vengono prima delle lettere, mentre base32hex mantiene i byte in ordine.

Lo usano i record NSEC3 di DNSSEC. Il nome di un record inizia con l’hash di un nome di dominio, scritto in base32hex senza riempimento, e la RFC 5155 osserva che, scritti così, i nomi sottoposti a hash si ordinano come gli hash per valore. Nella zona di esempio della RFC stessa, example ha come hash 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom. Con base32hex scelto, la pagina legge quei 32 caratteri come i 20 byte dell’hash; con base32 scelto, rifiuta lo 0 — e un avviso dice che il testo si legge per intero in base32hex, accanto a un pulsante che passa a quell’alfabeto.

Poiché gli stessi byte sono testi diversi in ciascuno — Hi è JBUQ==== in base32 e 91KG==== in base32hex — l’alfabeto che scegli vale in entrambe le direzioni, e la pagina non lo cambia mai al posto tuo. Quando un testo che decodifichi contiene un carattere che l’alfabeto scelto non ha, o termina con bit in eccesso che non sono zero, spiegati nelle domande più sotto, mentre l’altro alfabeto lo legge per intero come lo scriverebbe un codificatore, un avviso lo segnala accanto a un pulsante che cambia alfabeto; l’alfabeto cambia solo quando premi quel pulsante o lo scegli tu. Un testo che entrambi leggono senza problemi, come ABCDEFGH, viene letto in quello scelto, perché nulla in esso dice quale fosse inteso.

Dove si incontra Base32: segreti 2FA, indirizzi onion e IPFS

È in Base32 che il Key Uri Format scrive il segreto da cui nascono i codici di un’app 2FA. Quel formato descrive l’otpauth:// URI che un codice QR di configurazione può contenere: il parametro secret dell’URI è in Base32, e il suo riempimento andrebbe omesso. Incolla un segreto del genere in maiuscolo o in minuscolo, in gruppi separati da spazi o su più righe, con o senza = — un trattino tra i gruppi viene rifiutato nel punto in cui si trova — oppure incolla l’URI intero, e la pagina legge il segreto contenuto nell’URI e lo dice. Che cosa significano gli altri parametri dell’URI, e come un segreto diventa i codici che un’app mostra, spettano al Debugger di codici TOTP / 2FA: la sua guida spiega l’URI e i suoi parametri, e la sua pagina calcola i codici. L’etichetta e l’emittente nell’URI sono codificati in percentuale, come chiede il Key Uri Format, e il Codificatore / decodificatore URL li legge.

Anche un indirizzo onion della versione 3 di Tor è Base32. I suoi 56 caratteri prima di .onion sono il Base32 di 35 byte: la chiave pubblica di 32 byte del servizio, un checksum di due byte e un byte di versione, 03. La specifica di Tor scrive i suoi indirizzi di esempio in minuscolo, e 35 byte riempiono gruppi interi, quindi non c’è riempimento da omettere. Incolla i 56 caratteri senza .onion, imposta «Byte come» su «Esadecimale», e l’ultimo byte si legge 03.

IPFS scrive i suoi identificatori di contenuto, i CID, in Base32 per impostazione predefinita dalla versione 1 in poi: in minuscolo e senza riempimento, dopo una lettera, b, che non fa parte del Base32 ma lo indica — il prefisso di multibase, che si toglie prima di decodificare il resto. Così bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi, l’esempio della documentazione stessa di IPFS, qui viene rifiutato per intero, come una lunghezza che nessun byte produce; senza la sua b si legge come 36 byte, il CID binario, che inizia con 01 per la sua versione.

Un segreto 2FA è fatto di byte, non di testo

Il segreto di esempio del Key Uri Format è JBSWY3DPEHPK3PXP, e quel documento ne espone il valore come dieci byte: i caratteri di Hello!, poi DE AD BE EF. I suoi primi otto caratteri, JBSWY3DP, da soli sono Hello. Decodificato qui con «Byte come» su «Testo», l’impostazione predefinita della pagina, esce come Hello!, poi U+07AD — DE AD formano per caso un carattere, un segno della scrittura thaana — e poi due U+FFFD, ciascuno al posto di una sequenza che non è testo. Un avviso sotto il risultato conta le sequenze sostituite, dice che la prima inizia al byte 9, i cui bit iniziano nel carattere alla riga 1, colonna 13, il 3, e dice che i byte potrebbero non essere affatto testo.

Un vero segreto è fatto di byte casuali, che raramente formano testo, quindi decodificato come testo è un’accozzaglia di caratteri sparsi e di U+FFFD che non ti dice se il segreto è quello giusto. A questo serve «Byte come» impostato su «Esadecimale». Sceglilo, o premi il pulsante accanto all’avviso, e lo stesso segreto viene mostrato per intero come 48 65 6C 6C 6F 21 DE AD BE EF: i byte stessi, cioè ciò che un server conserva e ciò da cui ogni codice viene calcolato. La pagina non passa mai da sola all’esadecimale, quindi ciò che c’è sullo schermo è sempre ciò che hai scelto.

Nella direzione opposta è la stessa scelta, fatta durante la codifica. Una chiave che un server conserva in esadecimale è fatta di byte: scegli «Codifica», imposta «Byte come» su «Esadecimale» e incollala — con spazi o tutta attaccata, con 0x prima dei byte, come array di numeri o come dump esadecimale disposto come lo scrivono hexdump -C o xxd — e la pagina scrive il Base32 che un’app di autenticazione accetta. 48656C6C6F21DEADBEEF diventa JBSWY3DPEHPK3PXP, il segreto qui sopra; dieci byte riempiono gruppi interi, e una chiave che non li riempie, come una di sedici byte, esce seguita da segni = a meno che tu non disattivi il riempimento, come chiede il Key Uri Format. L’esadecimale incollato per sbaglio durante la decodifica — un numero pari di cifre esadecimali e nient’altro che caratteri di spaziatura, in una forma che la codifica sa leggere come byte — fa comparire un avviso che dice che sembra esadecimale, accanto a un pulsante che passa a codificarlo. E durante la decodifica «Scarica» salva i byte stessi in un file chiamato bytes.bin.

Base32 o Base64, e perché non l’alfabeto di Crockford

Base64 fa lo stesso lavoro con sessantaquattro caratteri, quattro ogni tre byte, il che rende il suo testo più lungo di un terzo rispetto ai byte, mentre quello di Base32 lo è di tre quinti. In cambio Base64 rinuncia a ignorare maiuscole e minuscole: il suo alfabeto tratta le maiuscole e le minuscole come valori diversi, con in più + e /, quindi SGk= è Hi e sgk= sono altri due byte. Base32 si presta a un testo che passa attraverso qualcosa che ignora maiuscole e minuscole, o che una persona legge su uno schermo e digita su un altro. Quando il Base64 incollato qui contiene un + o un /, che nessun Base32 scrive, ed è tutto nella forma di Base64, viene rifiutato con un avviso che dice che sembra Base64 e un collegamento allo strumento Base64, che legge Base64 come testo.

Esistono altri alfabeti di trentadue caratteri, e questa pagina offre i due della RFC 4648 e nessun altro. Uno, quello di Douglas Crockford, tiene tutte e dieci le cifre e lascia fuori I, L, O e U, ed è quello che usa il formato ULID. Crockford lo ha definito per scrivere numeri, e, applicato ai byte, quell’alfabeto dà due risposte: i sedici byte da 00 a 0F, impacchettati cinque bit alla volta come la RFC 4648 impacchetta i byte, sono 000G40R40M30E209185GR38E1W, e letti come un unico numero di 128 bit, come si leggono i ventisei caratteri di un ULID, sono 00041061050R3GG28A1C60T3GF. Una pagina che scrivesse byte con quell’alfabeto sceglierebbe una delle due al posto tuo, senza che tu lo veda.

Domande frequenti

Perché il mio segreto decodificato mostra U+FFFD?
Perché un segreto 2FA è fatto di byte casuali, e byte casuali raramente sono testo UTF-8. Con «Byte come» su «Testo» la pagina scrive ogni sequenza che non è testo come U+FFFD, il carattere sostitutivo, e un avviso dice quante erano e dove inizia la prima, indicando il byte in cui inizia e la riga e la colonna del carattere in cui iniziano i bit di quel byte. I byte stessi restano intatti: il pulsante accanto all’avviso li mostra in esadecimale, e «Scarica» li salva. Un U+FFFD che si trova davvero in un testo, i byte EF BF BD, viene letto come testo e non viene contato.
Che cosa significa «una lunghezza che nessun byte produce»?
Contati a otto a otto, i caratteri di un Base32, messo da parte ogni =, lasciano un resto di 0, 2, 4, 5 o 7, qualunque siano i byte, quindi un testo che lascia 1, 3 o 6 non può rappresentare alcuna sequenza di byte, e la pagina lo rifiuta al suo ultimo carattere. Un testo così non è stato scritto in quel modo da un codificatore: qualcosa si è perso o si è aggiunto lungo la strada fino a te. JBSWY3DPEHPK3P, il segreto del Key Uri Format con due caratteri in meno, viene rifiutato lì. Un taglio può anche cadere su una lunghezza che i byte producono davvero, e allora il testo si legge come meno byte — JBSWY3DPEHPK3PX come nove —, cosa di cui la pagina può accorgersi solo dove i bit in eccesso dell’ultimo carattere non sono zero, come accade con quella X. Un taglio alla fine di un gruppo intero di otto non lascia nulla di cui accorgersi.
Che cosa sono i bit in eccesso, e perché la pagina dice che i miei non sono zero?
Cinque bit per carattere e otto per byte raramente tornano pari, quindi, a meno che i byte non arrivino in multipli di cinque, l’ultimo carattere porta da uno a quattro bit che nessun byte contiene, e un codificatore li scrive come zeri. MZXW6YQ= e MZXW6YR= sono entrambi foob: gli ultimi tre bit della Q sono 000 e quelli della R 001, e solo il primo è ciò che scrive un codificatore. La pagina li legge entrambi, e per il secondo il suo avviso nomina la R, il punto in cui si trova e la Q che un codificatore scrive lì. Bit in eccesso che non sono zero vogliono dire che il testo non è ciò che ha scritto un codificatore: può essere stato troncato, modificato a mano o scritto nell’altro alfabeto, e quest’ultimo caso la pagina lo controlla per te.
Base32 è una forma di crittografia?
No. Base32 cambia il modo in cui i byte vengono scritti e nient’altro: chiunque può decodificarlo, e ogni decodificatore che segue la RFC 4648 ottiene gli stessi byte nello stesso alfabeto. Un segreto 2FA scritto in Base32 è il segreto stesso, quindi chiunque veda la chiave di configurazione ha in mano il tuo secondo fattore.
Qualcosa di ciò che incollo viene inviato a un server?
No. Entrambe le direzioni funzionano in questa pagina, sul tuo dispositivo: nulla di ciò che incolli — un segreto, un testo o dell’esadecimale — viene caricato, e il file che «Scarica» salva viene creato nel tuo browser a partire dai byte che sono già lì.

Strumenti correlati

  • Base64

    Base64 scrive quattro caratteri ogni tre byte, dove Base32 ne scrive otto ogni cinque, e in Base64 che una lettera sia maiuscola o minuscola fa parte del suo valore: abc in quella pagina è YWJj, e YWJJ lì si legge abI.

  • Debugger di codici TOTP / 2FA

    Genera e fai il debug di codici 2FA, con la derivazione completa.

  • Codificatore / decodificatore URL

    Codifica percentuale di un valore o di un URL intero, e viceversa.

  • Escape / unescape di stringhe JSON

    Applica l’escape al testo per una stringa JSON, o rileggine una con escape.