Base64

Base64 è un sistema di codifica che consente la traduzione di dati binari (contenenti sequenze di 8 bit) in stringhe di testo ASCII, rappresentando i dati sulla base di 64 caratteri ASCII diversi.

Viene usato principalmente come codifica di dati binari nelle e-mail, per convertire i dati nel formato ASCII.

L'algoritmo

L'algoritmo che effettua la conversione suddivide il file in gruppi da 6 bit, i quali possono quindi contenere valori da 0 a 63. Ogni possibile valore viene convertito in un carattere ASCII secondo la seguente tabella:

ValoreASCII
0A
1B
2C
3D
4E
5F
6G
7H
8I
9J
10K
11L
12M
13N
14O
15P
ValoreASCII
16Q
17R
18S
19T
20U
21V
22W
23X
24Y
25Z
26a
27b
28c
29d
30e
31f
ValoreASCII
32g
33h
34i
35j
36k
37l
38m
39n
40o
41p
42q
43r
44s
45t
46u
47v
ValoreASCII
48w
49x
50y
51z
520
531
542
553
564
575
586
597
608
619
62+
63/


Il set di 64 caratteri scelto per rappresentare i 64 valori (0-63) varia a seconda dell'implementazione scelta. L'obiettivo solitamente è di scegliere 64 caratteri che siano comuni alla maggior parte delle codifiche e che siano anche stampabili. Le altre varianti, solitamente derivate dal Base64, condividono queste proprietà ma differiscono nella scelta degli ultimi due caratteri; per esempio la variante URL e file name safe (RFC 4648/Base64URL), usa "-" e "_".

L'algoritmo causa un aumento delle dimensioni dei dati del 33%, poiché ogni gruppo di 3 byte viene convertito in 4 caratteri. Questo supponendo che per rappresentare un carattere si utilizzi un intero byte.

Se per rappresentare i caratteri ASCII si usassero 7 bit (che sarebbero sufficienti) e non 8, l'aumento di dimensioni sarebbe solo del 17%. Poiché però per rappresentare i caratteri ASCII si usano convenzionalmente 8 bit (7 per il carattere, lasciando il restante bit nullo), allora si ottiene l'aumento delle dimensioni descritto poco fa.

Esempio di codifica

Dati 3 byte che contengono i valori A, B, C, partendo dalla loro rappresentazione binaria, applichiamo l'algoritmo:

Rappresentazione ASCII:                   A           B           C                                          |           |           |Rappresentazione binaria:             01000001    01000010    01000011                                        /    \     /    \     /    \Suddivisione in gruppi da 6 bit:     010000  01  0100  0010  01  000011                                     |----|  \------/  \------/  |----|I 4 valori dedotti:                  010000   010100    001001   000011                                       \/       \/        \/       \/Il valore decimale:                    16       20         9        3                                        |        |         |        |Il valore codificato:                   Q        U         J        D

Quindi la sequenza di valori (ABC) viene convertita nella sequenza (QUJD).

Se la lunghezza del messaggio originale non è un multiplo di 3 byte il numero dei bit che costituiscono il risultato non sarà un multiplo di 6. Verranno quindi inseriti bit nulli (0) alla fine (4 o 2), e nel valore codificato vengono aggiunti da 0 a 2 simboli '=' (padding character) sufficienti a raggiungere un multiplo di 4 simboli. Ciascun padding character indica pertanto l'aggiunta di una coppia di bit nulli. Il padding non è comunque indispensabile per la decodifica e alcune implementazioni non lo utilizzano. Il padding è indispensabile solo qualora si vogliano concatenare messaggi codificati.

Quindi, preso un singolo byte di valore (A), esso viene convertito nella sequenza (QQ==), il singolo valore (B) viene convertito in (Qg==), mentre la sequenza (AB) diventa (QUI=).

Possibile routine di conversione
 union conv { unsigned int l; struct bytes { char b1; char b2; char b3; char b4; } b; };  char convert (char c) { if (c == 63) return 47; else if (c == 62) return 43; else if (c >= 52) return c - 4; else if (c >= 26) return c + 71; else return c + 65; }  unsigned int toBase64(char b1, char b2, char b3) { conv src, dest; src.b.b1 = b3; src.b.b2 = b2; src.b.b3 = b1; src.b.b4 = 0; //conv.l == b4 b3 b2 b1 dest.b.b1 = convert(src.b.b1 & 0x3f); src.l = src.l >> 6;  dest.b.b2 = convert(src.b.b1 & 0x3f); src.l = src.l >> 6; dest.b.b3 = convert(src.b.b1 & 0x3f); src.l = src.l >> 6; dest.b.b4 = convert(src.b.b1 & 0x3f);  return dest.l; }

Varianti

Esistono varianti di questa codifica, che differiscono principalmente nella scelta dei due caratteri usati per rappresentare i valori 62 e 63 e per il "padding char". In particolare molto usata è la variante che usa i caratteri "-" e "_" come valori 62 e 63 (al posto di "+" e "/") e non usa padding; questa variante è particolarmente utile quando la stringa codificata deve essere usata in una URL o in un filename.

Collegamenti esterni