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 modifica

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:

Valore ASCII
0 A
1 B
2 C
3 D
4 E
5 F
6 G
7 H
8 I
9 J
10 K
11 L
12 M
13 N
14 O
15 P
Valore ASCII
16 Q
17 R
18 S
19 T
20 U
21 V
22 W
23 X
24 Y
25 Z
26 a
27 b
28 c
29 d
30 e
31 f
Valore ASCII
32 g
33 h
34 i
35 j
36 k
37 l
38 m
39 n
40 o
41 p
42 q
43 r
44 s
45 t
46 u
47 v
Valore ASCII
48 w
49 x
50 y
51 z
52 0
53 1
54 2
55 3
56 4
57 5
58 6
59 7
60 8
61 9
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 modifica

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 modifica

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 modifica