Base64 es un sistema de numeración posicional que usa 64 como base. Es la mayor potencia que puede ser representada usando únicamente los caracteres imprimibles de ASCII. Esto ha propiciado su uso para codificación de correos electrónicos, PGP y otras aplicaciones. Todas las variantes famosas que se conocen con el nombre de Base64 usan el rango de caracteres A-Z, a-z y 0-9 en este orden para los primeros 62 dígitos, pero los símbolos escogidos para los últimos dos dígitos varían considerablemente de unas a otras. Otros métodos de codificación como UUEncode y las últimas versiones de binhex usan un conjunto diferente de 64 caracteres para representar 6 dígitos binarios, pero estos nunca son llamados Base64.
Esquemas de codificación en Base64
Protocolo Privacy-Enhanced Electronic Mail (PEM)
La primera aplicación conocida de la codificación Base64 para transmisiones electrónicas de datos fue el protocolo Privacy-enhanced Electronic Mail (PEM), propuesto por el RFC 989 en 1987. PEM define un esquema de caracteres imprimibles que usa Base64 para transformar una secuencia arbitraria de octetos en un formato que puede ser expresado en líneas cortas de caracteres de 6 bits, tales como las necesarias en protocolos de transmisión como SMTP.
La versión actual de PEM (especificada en el RFC 1421) usa un alfabeto de 64 caracteres consistente en los caracteres en mayúscula y minúscula del alfabeto latino (A-Z, a-z), los numerales (0-9) y los símbolos '+' y '/'. El símbolo '=' se usa como un sufijo especial. La especificación original (RFC 989) usa además el carácter '*' para delimitar la parte codificada pero no cifrada del flujo de salida.
Para transformar datos en una codificación PEM imprimible, el primer byte se sitúa en los 8 bits más significativos de un búfer de 24 bits, el siguiente en los 8 de en medio y el tercero en los de menor peso. Si hay menos de 3 bytes por codificar, el resto del búfer se rellena con ceros. En este punto, el búfer se usa de forma que se van extrayendo 6 bits desde la parte más significativa para ser usados como índice dentro de la cadena: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
, de forma que el carácter indicado será la salida.
Este proceso se repite con los datos restantes hasta que queden menos de cuatro octetos. Si quedan tres, se procesan de forma normal, mientras que si quedan menos de 3 bytes (24 bits), la entrada se rellenará con ceros por la derecha para formar un múltiplo de 6 bits.
Después de codificar los datos, si en el paso anterior quedaban 2 octetos por codificar, entonces se añade el carácter '=' al final de la salida; si solo quedaba un octeto, se concatenarán dos caracteres '='. Esto avisa al descodificador de que los bits a 0 que se hayan añadido de relleno no deben formar parte de los datos reconstruidos.
PEM necesita que todas las líneas codificadas estén formadas exactamente por 64 caracteres imprimibles, con la excepción de la última, que puede contener menos. Las líneas estarán delimitadas por caracteres de espacio en blanco de acuerdo con las convenciones específicas de la plataforma.
MIME
La especificación MIME (Multipurpouse Internet Mail Extensions) definida en el RFC 2045, describe Base64 como uno de los sistemas de codificación de binario a texto. El Base64 de MIME se basa en la versión de PEM que se describe en el RFC 1421: usa el mismo alfabeto de 64 caracteres y el mismo mecanismo de codificación, al igual que usa el símbolo '=' para señalar el relleno final, como se describe en el RFC 1521.
MIME no especifica un tamaño fijo para las líneas codificadas en Base64, pero sí precisa un tamaño máximo de 76 caracteres. Además, concreta que cualquier carácter que no pertenezca al alfabeto deberá ser ignorado por los decodificadores, aunque muchas implementaciones usan los caracteres CR/LF (retorno de carro y salto de línea) para delimitar las líneas codificadas. De esta manera, el tamaño real de los datos codificados conforme a MIME suele ser de un 140% del tamaño original.
UTF-7
UTF-7, descrito en el RFC 2152, introdujo un sistema llamado Modified Base64 (Base64 Modificado). Este esquema de codificación se usa para codificar UTF-16 como caracteres ASCII para ser usados en transmisiones de 7 bits como en SMTP. Es una variante del Base64 usado en MIME.
El alfabeto de Base64 modificado consiste en el alfabeto de Base64 usado en MIME, pero no usa el carácter '='. UTF-7 se pretendió usar para las cabeceras de los correos (definido en RFC 2047), y el carácter '=' se reserva en este contexto como carácter de escape para codificación Quoted-Printable. Base64 modificado simplemente omite el relleno y termina inmediatamente tras el último dígito Base64 que contiene bits útiles (dejando los 0-4 bits no usados del último dígito Base64).
OpenPGP
OpenPGP, descrito en el RFC 2440, usa la codificación Radix-64, también conocida como ASCII Armor. Radix-64 es idéntico a Base64 de MIME, salvo en que añade una suma de verificación CRC de 24 bits. Esta suma se calcula sobre los datos de entrada, antes de codificar, y posteriormente se codifica con el mismo Base64 para ser concatenada a la codificación resultante.
IRCu
En el protocolo P10 de servidor-servidor usado por el demonio IRC IRCu y software compatible, se usa una versión de Base64 para codificar los datos numéricos de cliente/servidor y de las direcciones IP binarias. Estos datos numéricos de la comunicación entre el cliente y el servidor tienen tamaños fijos, con un número exacto de dígitos Base64, por lo que no se necesita rellenar. Las direcciones IP binarias tienen bits a 0 por el comienzo para hacerlas encajar. El símbolo usado es algo diferente al usado en el alfabeto de MIME, utilizando "[]" en lugar de "+/" para evitar conflictos con otras partes del protocolo que usan el carácter '+' internamente como indicador de establecimiento de modos.
RFC 3548 (Las codificaciones Base16, Base32 y Base64) es un documento informal (no-normativo) que trata de unificar las especificaciones RFC 1421 y RFC 2045 de Base64, codificaciones con alfabetos alternativos y las codificaciones raramente usadas Base32 y Base16.
RFC 3548 prohíbe a las implementaciones añadir caracteres no alfabéticos y establece que los descodificadores deben rechazar datos que contengan caracteres no alfabéticos; todo esto si no están contemplados en una especificación que se refiera a esta o que, en todo caso, la requiera.
Este RFC hace obsoleto al RFC 3548 y se refiere al mismo tema:
- Este documento describe las codificaciones Base64, Base32 y Base16 usadas comúnmente y trata cuestiones como el uso de saltos de línea, rellenos, uso de caracteres no alfabéticos en los datos codificados y la utilización de otros alfabetos y codificaciones canónicas.
Ejemplo
Una cita de Thomas Hobbes perteneciente a la obra Leviathan:
Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.
se codifica en Base64 como sigue:
TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz
IHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2Yg
dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGlu
dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRo
ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=
En la cita de arriba el valor codificado de Man es TWFu. Codificadas en ASCII, las letras: M, a y n son almacenadas como los bytes 77, 97 y 110, es decir, 01001101, 01100001, 01101110 en base 2.
Ahora esos tres bytes se unen y tenemos el búfer de 24 bits, que será 010011010110000101101110. Este número se convertirá a su valor Base64, que puede hacerse tomando bloques de 6 bits a la vez (6 bits forman como máximo 64 valores diferentes en binario: 26). A continuación, cogiendo cada vez 6 bits del búfer, tenemos 4 números (24 = 6 x 4), que entonces son convertidos a su correspondiente valor en Base64.
Texto de entrada
|
M
|
a
|
n
|
ASCII
|
77
|
97
|
110
|
Bits
|
0 |
1 |
0 |
0 |
1 |
1 |
0 |
1 |
0 |
1 |
1 |
0 |
0 |
0 |
0 |
1 |
0 |
1 |
1 |
0 |
1 |
1 |
1 |
0
|
Índice
|
19
|
22
|
5
|
46
|
Resultado en Base64
|
T
|
W
|
F
|
u
|
Por tanto, 3 bytes sin codificar (en este caso, caracteres ASCII) entran y 4 caracteres ASCII codificados surgen como resultado.
La tabla de índice Base64:
Valor |
Carácter
|
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
|
Valor |
Carácter
|
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
|
Valor |
Carácter
|
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
|
Valor |
Carácter
|
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 |
/
|
Ilustración del marcado de relleno conforme acortamos la entrada:
La entrada termina con: any carnal pleasure. La salida termina con: YW55IGNhcm5hbCBwbGVhc3VyZS4=
La entrada termina con: any carnal pleasure La salida termina con: YW55IGNhcm5hbCBwbGVhc3VyZQ==
La entrada termina con: any carnal pleasur La salida termina con: YW55IGNhcm5hbCBwbGVhc3Vy
La entrada termina con: any carnal pleasu La salida termina con: YW55IGNhcm5hbCBwbGVhc3U=
La entrada termina con: any carnal pleas La salida termina con: YW55IGNhcm5hbCBwbGVhcw==
Aplicaciones en URL
La codificación Base64 puede ser útil cuando el tamaño de la información de identificación usada en un entorno HTTP es bastante grande. El framework de base de datos para objetos persistentes llamado Hibernate para el lenguaje de programación Java usa Base64 para codificar una ID única relativamente grande (generalmente UUIDs de 128 bits) dentro de una cadena de texto para ser usada como parámetro HTTP en los formularios o en el modo de transmisión GET. También, gran cantidad de aplicaciones necesitan codificar datos binarios de forma que puedan ser introducidos en las URL, así como en los campos ocultos de los formularios. Base64 resulta adecuado para estos propósitos ya que además de transformarlos en una cadena compacta, oculta la naturaleza de los datos ante posibles observadores.
El uso de un codificador de URL sobre Base64 estándar, sin embargo, no resulta adecuado ya que traducirá los caracteres '+' y '/' en las secuencias especiales en hexadecimal %XX ('+' = '%2B' y '/' = '%2F'). Si posteriormente se usa para almacenamiento en base de datos o entre sistemas heterogéneos, producirán un conflicto en el carácter '%' generado por el codificador de URL (debido a que este carácter es usado en ANSI SQL como comodín).
Por esta razón existe un Base64 Modificado para URL, donde no se usa el carácter '=' de marcado de relleno, y los caracteres '+' y '/' del Base64 estándar son sustituidos por '-' y '_' respectivamente, de manera que ya no se necesita usar codificadores de URL. Además, no tiene impacto en el tamaño de la codificación, dejándola intacta para uso en base de datos relacionales, formularios web e identificadores de objetos en general.
Otra variante, llamada Base64 Modificado para expresiones regulares, usa "!-" en lugar de "*-" para sustituir el "+/" del Base64 estándar, debido a que, tanto '+' como '*' son caracteres reservados para las expresiones regulares (cabe resaltar que el "[]" usado en la variante IRCu explicada arriba no funcionará en este contexto).
También hay otras variantes que usan "_-" o "._" cuando la cadena codificada va a ser usada como identificador válido para programas, o ".-" cuando se usa para los tokens de XML (Nmtoken), o incluso "_:" para ser usada en un los identificadores más restrictivos de XML (Name).
Para superar la incompatibilidad de Base64 debido a la inclusión de más de dos caracteres de "clase simbólica" (+, /, =, etc.) en el contenido de salida, se introdujo un esquema de codificación Base62x sin cifrar para el contenido de salida en el campo de la ingeniería de software. Base62x se considera una versión mejorada Base64 sin firmar.
Otras aplicaciones
Base64 se usa también para otras aplicaciones, como:
- Thunderbird y Evolution usan Base64 para ofuscar las contraseñas de correo electrónico.
- Ofuscación insegura pero rápida de información privada sin la necesidad de la gestión de claves de la criptografía.
- Los divulgadores de correo basura (spam) usan Base64 para evitar algunas protecciones anti-spam, que no suelen descodificar Base64 y, por tanto, no pueden detectar palabras prohibidas en los mensajes codificados.
- Codificación de cadenas de caracteres en archivos LDIF.
- Incorporación de datos binarios en archivos XML, usando una sintaxis similar a
<data encoding="base64">…</data>
. Por ejemplo, los favicons en el documento exportado por Firefox bookmarks.html.
- En el lenguaje CSS se puede, literalmente, escribir una imagen en Base64 en vez de cargar una imagen desde un servidor.
Un ejemplo programático
A continuación se muestra un ejemplo de como codificar y decodificar un texto usando Base64. El ejemplo que se muestra está escrito en el lenguaje de programación Python
>>> import base64
>>> texto = "Prueba de codificación BASE64"
>>> textoCodificado = base64.encodestring(texto)
>>> textoCodificado
'UHJ1ZWJhIGRlIGNvZGlmaWNhY2nDs24gQkFTRTY0IQ=\n'
>>> base64.decodestring(textoCodificado)
'Prueba de codificación BASE64'
En php también se permite el uso de Base64, en el siguiente ejemplo podemos ver como se codifica/decodifica en Base64 con PHP:
<?php
$texto = "Hola mundo";
$codificado = base64_encode($texto);
$decodificado = base64_decode($codificado);
echo $decodificado."<br />"; //Se muestra Hola mundo
echo $codificado; //Se muestra SG9sYSBtdW5kbw==
?>
En gambas3.2:
Public Sub Main()
Dim mensaje As String
Dim mensajeCodificado As String
Dim mensajeDecodificado As String
mensaje = "Prueba de codificacion Base64!"
Print "Mensaje Original: "; mensaje ' Muestra el mensaje en pantalla
mensajeCodificado = Base64$(mensaje)
Print "Mensaje codificado:"; mensajeCodificado ' Muestra el mensaje codificado
mensajeDecodificado = UnBase64$(mensajeCodificado)
Print "Mensaje decodificado: "; mensajeDecodificado ' Muestra el mensaje decodificado
End
En JavaScript:
const texto = "Prueba de codificación BASE64"
const textoCodificado = btoa(texto)
console.log(textoCodificado) // UHJ1ZWJhIGRlIGNvZGlmaWNhY2nzbiBCQVNFNjQ=
const textoDecodificado = atob(textoCodificado)
console.log(textoDecodificado) // Prueba de codificación BASE64
Véase también
Enlaces externos