Vai al contenuto
LeedyBox
Sostieni

Base64, codifica URL e JWT spiegati

Tutti e tre compaiono ovunque i dati debbano viaggiare come testo: negli URL, negli header HTTP, nel JSON e nei token di accesso. Nessuno dei tre nasconde qualcosa. Questa guida spiega come funziona ciascuno, dove lo incontri e gli errori che causano la maggior parte dei problemi.

Codifica non è cifratura

Una codifica cambia il modo in cui i dati sono scritti, così che possano passare per un canale che accetta solo determinati caratteri. Chiunque può invertirla, perché non c’è alcuna chiave. Anche la cifratura trasforma i dati, ma solo chi possiede la chiave può riportarli all’originale. Un hash è un’altra cosa ancora: un’impronta a senso unico che non si può invertire affatto, come spiegato in Le funzioni di hash spiegate.

Base64 e la codifica URL sono codifiche. Un JWT di solito è firmato, il che dimostra chi lo ha emesso e che il contenuto non è stato modificato, ma il contenuto è solo codificato. Se un valore deve restare segreto, serve la cifratura, non uno di questi formati.

Come funziona Base64

Base64 legge i dati tre byte (24 bit) alla volta e li divide in quattro gruppi di sei bit. Ogni gruppo è un numero da 0 a 63 e viene scritto come un carattere di un alfabeto di 64 caratteri: A–Z per 0–25, a–z per 26–51, 0–9 per 52–61, poi + e /. La parola «Man» mostra i passaggi:

PassaggioMan
Valore del byte7797110
Bit010011010110000101101110
Quattro gruppi da 6 bit010011 · 010110 · 000101 · 101110 = 19 · 22 · 5 · 46
Base64T W F u → TWFu

Se la lunghezza dell’input non è un multiplo di tre, l’ultimo gruppo viene completato e segnalato con il padding: un byte rimasto dà due caratteri e ==, due byte rimasti danno tre caratteri e =. «Ma» diventa TWE= e «M» diventa TQ==.

Poiché ogni tre byte diventano quattro caratteri, Base64 aumenta i dati di circa un terzo, più le interruzioni di riga che alcuni formati inseriscono. Una foto da 3 MB inviata come allegato email viaggia come circa 4 MB di testo, e un’immagine incorporata in un foglio di stile come data URL pesa circa un terzo in più del file.

Dove incontri Base64

  • Allegati email (MIME): testo Base64 spezzato a 76 caratteri per riga.
  • Data URL come data:image/png;base64,iVBORw0… inseriscono un piccolo file direttamente in HTML o CSS.
  • Autenticazione HTTP Basic: invia user:password in Base64 nell’header Authorization. Questo nasconde la password solo a un’occhiata veloce, quindi è sicuro solo su HTTPS.
  • Certificati e chiavi nei file PEM sono Base64 tra le righe -----BEGIN …----- e -----END …-----, spezzati a 64 caratteri.
  • JSON e XML trasportano valori binari, come firme o miniature, come stringhe Base64, perché non hanno un tipo binario.

Base64URL e padding

I caratteri + e / del Base64 standard hanno un significato negli URL e nei percorsi dei file, quindi un secondo alfabeto, Base64URL, usa al loro posto - e _. Di solito omette anche il padding =, perché il decodificatore può calcolare la lunghezza. JWT, molti token API e alcuni nomi di file usano Base64URL. Per trasformare il Base64 standard in Base64URL, sostituisci + con -, / con _ ed elimina gli = finali; per tornare indietro, inverti le sostituzioni e aggiungi = finché la lunghezza non è un multiplo di quattro.

La percent-encoding negli URL

Un URL può contenere solo un insieme limitato di caratteri, e alcuni di essi danno struttura all’indirizzo: / e ? separano percorso e query, & e = separano i parametri, # apre il frammento. Quando un valore contiene uno di questi caratteri, o qualsiasi carattere fuori dall’ASCII, viene codificato in percentuale: ogni byte della sua forma UTF-8 è scritto come % seguito da due cifre esadecimali. «café» diventa caf%C3%A9, perché é corrisponde ai due byte C3 A9.

Lettere, cifre e - . _ ~ non vanno mai codificati. Questi caratteri causano più spesso problemi:

CarattereCodificatoPerché conta
spazio%20Non ammesso in un URL
&%26Aprirebbe un nuovo parametro
=%3DChiuderebbe il nome del parametro
?%3FAprirebbe la query
#%23Aprirebbe il frammento, che non viene inviato al server
/%2FAggiungerebbe un segmento al percorso
+%2BViene letto come spazio nei dati dei moduli
%%25Aprirebbe una sequenza di escape

Codifica ogni valore separatamente, poi componi l’URL. In JavaScript, encodeURIComponent lo fa per un singolo valore e codifica anche / ? & = #, mentre encodeURI è pensata per un indirizzo completo e lascia quei caratteri come sono. Usare encodeURI per un singolo valore è una causa comune di stringhe di query rotte.

Segni più, spazi e doppia codifica

I moduli HTML inviano i campi come application/x-www-form-urlencoded, dove uno spazio diventa +. Nella sintassi URL generica, + è solo un segno più. Così una ricerca di «C++» inviata come q=C++ arriva a un server che decodifica i dati dei moduli come «C» seguito da due spazi; andrebbe inviata come q=C%2B%2B. Quando decodifichi a mano una stringa di query, verifica prima con quale regola è stata prodotta.

La doppia codifica avviene quando un valore già codificato viene codificato di nuovo: %20 diventa %2520, perché lo stesso % diventa %25. Se in un URL vedi %25 seguito da due cifre esadecimali, un passaggio della catena ha codificato due volte; decodifica una volta e cerca dove avviene il passaggio in più.

Che cosa contiene un JWT

Un JSON Web Token (JWT) trasporta delle affermazioni (claim), come chi è l’utente e fino a quando vale il token, dal sistema che lo emette a quello che lo riceve. La forma firmata comune è composta da tre parti Base64URL separate da punti: header, payload e firma. Decodificate, le prime due sono normale JSON:

Header:  {"alg": "HS256", "typ": "JWT"}
Payload: {"sub": "user-42", "role": "editor", "iat": 1767225600, "exp": 1767229200}

Lo standard (RFC 7519) definisce alcuni claim registrati; le applicazioni ne aggiungono di propri, come role qui sopra.

ClaimSignificato
issEmittente: chi ha creato il token
subSoggetto: di solito l’ID dell’utente o dell’account
audDestinatario: il servizio a cui il token è destinato
exp, nbf, iatScadenza, non prima di, emissione: ore Unix in secondi
jtiID del token, per rilevarne il riuso o revocarne uno singolo

Poiché il payload è solo codificato, chiunque abbia il token può leggerlo. Non inserire dati personali né segreti e tieni il token piccolo: viaggia con ogni richiesta, e molti server limitano la dimensione degli header.

Firmato non significa segreto: come si verifica un JWT

La firma è calcolata su header e payload. Con HS256, chi emette e chi riceve condividono un segreto e usano HMAC con SHA-256. Con RS256 o ES256, chi emette firma con una chiave privata e chi riceve verifica con la chiave pubblica corrispondente, quindi non può creare token per conto proprio.

Un server che riceve un token deve verificare la firma con l’algoritmo e la chiave attesi, e controllare exp, nbf, iss e aud, prima di fidarsi di qualsiasi claim. La sola decodifica, come quella dello strumento LeedyBox, salta tutto questo: mostra che cosa c’è nel token, non se il token è autentico. Le librerie dovrebbero inoltre rifiutare l’algoritmo «none», che indica un token non firmato, a meno che i token non firmati siano attesi di proposito. Se il contenuto stesso va nascosto, il token viene cifrato (JWE) ed è composto da cinque parti illeggibili senza chiave.

Problemi comuni e soluzioni

SintomoCausa probabileSoluzione
Il Base64 decodificato è testo senza sensoI dati sono binari, o testo in un’altra codificaVerifica che cosa è stato codificato; salva i dati binari come file
«Carattere non valido» in decodificaPrefisso data:, virgolette o alfabeto Base64URLElimina tutto fino alla virgola; usa un decodificatore che accetti - e _
Un parametro arriva troncatoUn & o un # non codificato dentro il valoreCodifica ogni valore con encodeURIComponent
%2520 nell’URLValore codificato due volteCodifica una sola volta, dove l’URL viene composto
Token rifiutato anche se exp è nel futuroDestinatario o emittente sbagliato, orologi sfasati o chiave diversaConfronta aud, iss e chiave di firma con quelli attesi dal server
Scadenza tra migliaia di anniexp scritto in millisecondi anziché in secondiMemorizza exp, nbf e iat in secondi

Domande frequenti

Base64 può proteggere una password o una chiave API?

No. Chiunque può invertire Base64 in un secondo. Le credenziali codificate in Base64, per esempio in un file di configurazione o in un URL, sono esposte quanto il testo in chiaro.

Posso mettere dati personali nel payload di un JWT?

Meglio di no. Chiunque abbia il token può leggere il payload, comprese estensioni del browser, log e proxy che vedono la richiesta. Metti un ID nel token e recupera i dettagli sul server.

La codifica URL protegge dagli attacchi di iniezione?

Solo nel senso che un valore non può rompere la struttura dell’URL. Il server deve comunque validare ed eseguire l’escape del valore decodificato per il contesto in cui lo usa, come SQL, HTML o un comando di shell.

Perché la mia stringa Base64 è più lunga del file?

Ogni tre byte diventano quattro caratteri, quindi il testo è circa il 33% più grande, e le interruzioni di riga aggiungono un po’ di più. Per i file grandi, inviare i byte direttamente è più efficiente che usare Base64.