¿Tiene que ocuparse del formato Base64? Entonces esta página es perfecta para Ud. Utilice nuestra práctica herramienta en línea para codificar o decodificar sus datos.

Codificación Base64 en Perl: una guía completa

Tienes datos que deben sobrevivir a un canal que no los quiere. Un blob binario que tiene que estar sentado en un campo JSON. Una imagen que debe vivir dentro de una etiqueta HTML. Un certificado que tiene su sitio en un archivo de configuración. Un token que viajará por URLs, cabeceras y query strings. Esa es la vida diaria de la codificación Base64: reescribe cada tres bytes de datos crudos como cuatro caracteres de un alfabeto de 64 letras, con uno o dos signos = terminando la cola, para que el resultado sea texto plano que cualquier cosa puede llevar, típicamente unos 33 por ciento más largo de lo que empezaste. La página de inicio de este sitio explica el formato al completo, así que este artículo se centra en lo que Perl te da, lo que decide en silencio por ti, y dónde están las trampas.

Primero la buena noticia: encode_base64 vive en el core de Perl desde 2002, está implementado en C, y es cómodamente rápido. La parte interesante es que la función tiene opiniones. Dobla su salida a 76 caracteres, añade un salto de línea final, y no codificará caracteres Unicode que no hayas convertido antes a bytes: por encima del rango Latin-1 muere sin más, y por debajo de esa línea asume en silencio bytes Latin-1. Esta guía recorre cada variante de Base64 que un desarrollador Perl realmente produce: el one-liner, el cuerpo de correo doblado MIME, la clave envuelta en PEM, el token seguro para URLs, y la versión en streaming para archivos demasiado grandes para caber en memoria.

Una función, un salto de línea oculto

La API entera, exactamente tal como la presenta la documentación moderna:

encode_base64( $bytes )
encode_base64( $bytes, $eol )

Léelo otra vez. Dos argumentos, uno de ellos opcional, un valor de retorno, sin flags. El segundo argumento opcional es la secuencia de fin de línea, y por defecto es un salto de línea plano, lo que significa que la llamada de aspecto más inocente de Perl produce salida doblada y terminada en salto de línea:

use MIME::Base64 qw(encode_base64);
my $wrapped = encode_base64("Aladdin:open sesame");
print length($wrapped), "\n";  # 29: los 28 caracteres más un salto de línea
my $single = encode_base64("Aladdin:open sesame", "");
print length($single), "\n";   # 28: pasa una cadena vacía para no doblar

El tamaño de la salida sigue un patrón fijo que puedes predecir antes de llamar:

Bytes de entrada Caracteres de salida Padding
0 0 ninguno
1 4 dos =
2 4 un =
3 4 ninguno
100,000 133,336 ninguno, en una sola línea
3,000,000 4,000,000 ninguno

El patrón son cuatro caracteres por cada grupo completo de tres bytes, más un grupo final parcial relleno con uno o dos signos =. Una consecuencia que conviene conocer: un byte y tres bytes producen ambos cuatro caracteres, así que la longitud codificada oculta el tamaño exacto de la entrada. Y si necesitas el tamaño sin hacer el trabajo, el módulo lleva una función de longitud desde la 3.10 en 2010. Solo que no está exportada por defecto, así que la llamas por el nombre del paquete:

use MIME::Base64 ();
my $with_wrap   = MIME::Base64::encoded_base64_length($bytes);        # líneas de 76 caracteres, eol por defecto
my $single_line = MIME::Base64::encoded_base64_length($bytes, "");    # sin doblado
my $mime_body   = MIME::Base64::encoded_base64_length($bytes, "\r\n");

Hay una regla más que memorizar, porque es la única forma en que el codificador alguna vez grita: si la cadena que le pasas contiene caracteres con código por encima de 255, encode_base64 muere con Carácter ancho en entrada de subrutina. Por debajo de esa línea el fallo es más callado: los caracteres hasta 255 se degradan en silencio a sus bytes Latin-1, así que una cadena de caracteres acentuados que se saltó la conversión se codifica como Latin-1 en vez de UTF-8, y nadie te lo dice. La codificación Base64 solo está definida para caracteres de un solo byte, y Perl 5.8 y superiores permiten caracteres extendidos en las cadenas, así que la conversión es una decisión que tomas a propósito, con Encode, en la misma siguiente sección.

¿Texto o bytes? El paso que la función no puede hacer

Las cadenas Perl llevan una flag callada que dice si contienen caracteres o bytes, y Base64 vive del lado de los bytes de esa línea. Si tu texto es una cadena de caracteres, y lo es en el momento en que sale de un parser JSON, una plantilla, o un literal con letras acentuadas en un archivo fuente UTF-8, el codificador se niega a adivinar qué bytes querías para los caracteres por encima del rango Latin-1, y te lo dice; por debajo del rango adivina Latin-1 en silencio. La solución es la misma en ambos casos, y es una función core del módulo Encode:

use MIME::Base64 qw(encode_base64);
use Encode qw(encode);
my $chars = "H\x{eb}llo W\x{f6}rld";  # una cadena de caracteres
my $utf8  = encode("UTF-8", $chars);  # ahora: bytes
my $b64   = encode_base64($utf8, "");
print $b64, "\n";  # SMOrbGxvIFfDtnJsZA==

Esa llamada a encode es toda la coreografía: elige la representación en bytes, y UTF-8 para lo moderno, convierte los caracteres a esos bytes, y solo entonces entrega los bytes al codificador. Para texto occidental heredado que llegó como Windows 1252, la conversión es la misma función con otro nombre, encode("Windows-1252", $legacy), que te entrega la forma original de un solo byte. El módulo Encode es core, así que todo esto no cuesta nada.

Ahora la trampa. Si los bytes que tienes ya son UTF-8 y los pasas otra vez por encode("UTF-8", ...), pensando que los estás haciendo UTF-8, no obtienes una copia: obtienes una codificación doble, donde cada carácter acentuado se hincha hasta convertirse en dos caracteres propios. El síntoma clásico es un texto que antes leía Hëllo y ahora lee Hëllo, y cada decodificador del internet lo decodificará con fidelidad para ti:

use Encode qw(encode decode);
my $right = encode("UTF-8", "H\x{eb}llo");
my $wrong = encode("UTF-8", $right);  # recodificando los bytes como caracteres
print decode("UTF-8", $right), "\n";  # Hëllo
print decode("UTF-8", $wrong), "\n";  # Hëllo

La regla de oro que lo evita: los bytes se codifican exactamente una vez, y utf8::is_utf8() te muestra de qué lado de la línea está una cadena. Si la flag está activada, sostienes caracteres y la llamada a encode() es el movimiento correcto; si no está activada, sostienes bytes y estás listo para Base64.

Doblado de líneas: tres dialectos, una regla

Como la salida por defecto está doblada y terminada en salto de línea, la primera decisión de cada trabajo de codificación es un problema de destino: ¿dónde vivirá esta cadena? El hecho unificador es que los decodificadores ignoran los saltos de línea por completo: el RFC 2045 dice al software de decodificación que ignore todos los saltos de línea y los caracteres fuera del alfabeto, así que el doblado es una cortesía con las herramientas basadas en líneas y con los humanos, no una diferencia semántica. Las tres respuestas en la práctica:

Sin saltos de línea. La salida de la función con el doblado desactivado, exactamente una línea. Esto es lo que quieres para URLs, payloads JSON, cabeceras, valores de base de datos, y cualquier otra cosa donde un salto de línea sería un bug. Esto es también lo que la mayoría quiere decir cuando piden solo el Base64:

my $single = encode_base64($bytes, "");

MIME: 76 caracteres más CRLF. La convención de correo del RFC 2045: las líneas codificadas no deben exceder los 76 caracteres, y el mundo MIME habla CRLF. Esta es tarea propia del módulo, hecha con el segundo argumento:

my $mime_body = encode_base64($bytes, "\r\n");

PEM: 64 caracteres más LF. Las claves y los certificados usan la convención más vieja con líneas más cortas de 64 caracteres, y el módulo no puede producir ese ancho por sí solo, así que un helper de cuatro líneas llena el hueco:

sub wrap_lines {
  my ($text, $width) = @_;
  return join "\n", $text =~ /(.{1,$width})/g;
}
my $pem = "-----BEGIN CERTIFICATE-----\n"
        . wrap_lines(encode_base64($der, ""), 64) . "\n"
        . "-----END CERTIFICATE-----\n";

El mismo helper sirve también para los demás dialectos de 64 caracteres - la codificación textual PKIX del RFC 7468 y la armadura OpenPGP, cuyas líneas de datos son de 64 caracteres de ancho y cuya línea final de suma de verificación CRC24 la añade GnuPG en lugar de ti. Un bache se aplica a todos ellos: encode_base64 añade el fin de línea al final exacto del resultado, incluso cuando la última línea llena su ancho exactamente. Si un consumidor aguas abajo tropieza con esa línea en blanco final, una llamada a rtrim sobre el resultado lo arregla.

Base64 seguro para URLs: el alfabeto - y _

El alfabeto estándar incluye + y /, y ambos son problemas fuera de un archivo de texto: un + en una query string codificada por formulario se convierte en un espacio antes de que tu aplicación lo vea, y / es un separador de rutas en las URLs. Los nombres de archivo y los tokens tienen sus propias quejas. El RFC 4648, sección 5, resuelve esto con el alfabeto seguro para URLs y nombres de archivo, donde + se convierte en -, / se convierte en _, y el padding = final suele descartarse. El RFC insiste en que esta codificación no debe considerarse la misma que la codificación base64, así que trátalo como un formato distinto, comúnmente llamado base64url. Perl lo produce en una llamada desde la versión 3.11 en 2010:

use MIME::Base64 qw(encode_base64url);
my $seg = encode_base64url("sunset-42");
print $seg, "\n";  # c3Vuc2V0LTQy: sin padding, sin salto de línea

Esa única llamada hace los tres cambios: el cambio de alfabeto, sin padding, sin saltos de línea. Si ya sostienes Base64 estándar y el destino quiere el dialecto seguro para URLs, dos operaciones de cadenas lo convierten in situ:

sub to_urlsafe {
  my ($b64) = @_;
  $b64 =~ tr{+/}{-_};
  return $b64 =~ s/=+\z//r;
}
my $seg = to_urlsafe(encode_base64($bytes, ""));

Cuándo usarlo: partes de JSON Web Token, parámetros de state y nonce de OAuth, IDs de API que pones en rutas de URL, y claves opacas que necesitan sobrevivir a una barra de direcciones o un nombre de archivo, donde Data::UUID::Base64URLSafe de CPAN existe justo para esto. Cuándo no usarlo: cuerpos de correo, armadura PEM, y cualquier lugar donde al otro lado haya un consumidor del alfabeto estándar, porque - y _ no están en su vocabulario. Y no mezcles los dos alfabetos en silencio: un valor codificado seguro para URLs debe decodificarse seguro para URLs, en todas partes, para siempre. En Perls anteriores a 3.11, el módulo independiente MIME::Base64::URLSafe de 2006, que es un port del codec urlsafe de Python, ofrece urlsafe_b64encode; en cualquier cosa moderna, la función integrada es la herramienta correcta.

Construyendo un JWT: cada parte a mano

El JSON Web Token es el consumidor insignia de Base64 en las APIs modernas, y usa el dialecto seguro para URLs y sin padding de la sección de arriba. Según el RFC 7515, un JWT compacto es tres partes base64url separadas por puntos: la cabecera protegida, el payload y la firma. Construir uno a mano es una forma agradable de ver cada pieza móvil:

use MIME::Base64 qw(encode_base64url);
use JSON::PP qw(encode_json);
use Digest::SHA qw(hmac_sha256);
my $secret  = "correct-horse-battery-staple";
my $head    = encode_base64url(encode_json({ alg => "HS256", typ => "JWT" }));
my $claims  = encode_base64url(encode_json({ sub => "homer", role => "admin" }));
my $sig     = encode_base64url(hmac_sha256("$head.$claims", $secret));
my $jwt     = "$head.$claims.$sig";
print $jwt, "\n";  # un token HS256 compacto; el orden de las claves dentro de cada parte JSON varía de una ejecución a otra

Tres detalles que merecen atención. Primero, encode_json del módulo core JSON::PP emite bytes UTF-8 compactos sin espacios, que es exactamente lo que las especificaciones JOSE quieren dentro de un token. Segundo, el payload es legible por cualquiera, y eso es por diseño: un JWT es un ticket firmado, no un secreto, así que nunca pongas valores confidenciales en los claims. Tercero, la firma es la codificación base64url de bytes HMAC crudos, y por eso hmac_sha256 va directamente al codificador sin ningún formato hex.

Para producción, no haces el firmado a mano. El módulo de CPAN Crypt::JWT, que se apoya en CryptX, implementa JWS y JWE con el conjunto completo de algoritmos:

use Crypt::JWT qw(encode_jwt);
my $jwt = encode_jwt(
  payload => { sub => "homer", role => "admin" },
  alg     => "HS256",
  key     => $secret,
);

Y en el lado receptor, fija el algoritmo con accepted_alg para que un atacante no pueda cambiar el token a una variante más débil: decode_jwt(token => $jwt, key => $secret, accepted_alg => "HS256") verifica la firma y explota si falla. Hacerlo a mano va bien para entender; una librería va bien para el dinero.

HTTP: cabeceras de autenticación, data URIs y el apretón de manos WebSocket

La cabecera Authorization: Basic es el caso de uso vivo más antiguo: el nombre de usuario y la contraseña unidos por dos puntos, codificados en una sola línea y prefijados con la palabra de esquema. El segundo argumento de cadena vacía carga peso aquí, porque un salto de línea final dentro de un campo de cabecera es un bug:

use MIME::Base64 qw(encode_base64);
my $user = "alice";
my $pass = "s3cr3t";
my $header = "Basic " . encode_base64("$user:$pass", "");
print $header, "\n";  # Basic YWxpY2U6czNjcjN0

Los data URIs del RFC 2397 son la misma idea aplicada a las imágenes: el payload se sienta directamente en la URL, así que no se necesita una segunda petición para obtenerlo. Los medios binarios usan la flag ;base64, así que el payload es exactamente lo que encode_base64 produjo con el doblado desactivado:

my $uri = "data:" . $mime_type . ";base64," . encode_base64($bytes, "");

Dicho esto, los contrapuntos son reales. El payload codificado es unos 33 por ciento más grande que el archivo, lo que hace el documento HTML mismo más grande. Los navegadores no cachean un data URI de la forma en que cachean una URL de archivo - no hay una descarga separada que cachear, así que cada vista de página envía de nuevo los bytes como parte del documento, y el propio RFC dice que los data URIs solo son útiles para valores cortos. Úsalos para avatares, iconos y gráficos pequeños en línea; usa archivos reales para todo lo demás. Hay una tercera esquina de HTTP que usa Base64 en silencio: el apretón de manos WebSocket del RFC 6455, donde el cliente envía una cabecera Sec-WebSocket-Key que es el Base64 de dieciséis bytes aleatorios. Frameworks como Mojolicious lo hacen por ti, pero si algún día lo ves en el cable, ahora sabes qué es:

use MIME::Base64 qw(encode_base64);
my $key = encode_base64(pack("C16", map { int(rand 256) } 1 .. 16), "");
print length($key), "\n";  # 24: dieciséis bytes aleatorios, rellenados al grupo de cuatro caracteres

Archivos: slurps, trozos de 57 bytes y la CLI

El trabajo de codificación más directo: un archivo se convierte en texto. Las cadenas Perl son bytes, así que no hay que buscar ningún modo binario - la capa :raw es todo. Abre en crudo, lee, codifica, escribe:

use MIME::Base64 qw(encode_base64);
open my $in, "<:raw", $ARGV[0] or die $!;
local $/;
my $bytes = <$in>;
close $in;
open my $out, ">:raw", $ARGV[1] or die $!;
print {$out} encode_base64($bytes);
close $out;

Las capas :raw importan. Sin ellas, Perl intentaría interpretar los bytes como texto de la plataforma al entrar y al salir, y en un sistema con una codificación por defecto distinta eso es exactamente la corrupción que no ves hasta que el archivo se abre en otra parte. Y recuerda la factura de tamaño cuando planifiques almacenamiento: una imagen de 500 KB se convierte en un archivo de texto de 670 KB, y un video de 1 GB se convierte en 1.33 GB.

Para archivos demasiado grandes para caber en memoria, la propia documentación del módulo te da la regla: codifica en trozos que sean un múltiplo de 57 bytes, porque 57 bytes de datos llenan exactamente una línea de 76 caracteres, siendo 76 igual a 57 por 4 dividido entre 3. Trocea en ese límite y nunca tendrás padding en medio del flujo:

use MIME::Base64 qw(encode_base64);
open my $in, "<:raw", $ARGV[0] or die $!;
while (read($in, my $buf, 57 * 10)) {
  print encode_base64($buf);
}
close $in;

Cada trozo cae exactamente en los límites de línea, el último, posiblemente corto, trozo lleva el padding final, y el resultado es idéntico byte a byte a slurpear el archivo entero y codificarlo de una vez, solo que con una huella de memoria constante. Y cuando no necesitas ningún script, el one-liner lo cubre, con -0777 slurpeando la entrada y el argumento de cadena vacía manteniendo la salida en una línea:

perl -MMIME::Base64 -0777 -ne 'print encode_base64($_, "")' < file > file.b64

Correo: cuerpos MIME y adjuntos

El correo es donde Base64 ganó su nombre. El estándar MIME dice que los datos que no pueden viajar con seguridad como texto crudo deben enviarse con Content-Transfer-Encoding: base64, en líneas de no más de 76 caracteres. Si construyes correo con MIME::Lite, todo es un solo argumento, y el módulo hace la codificación, el doblado y la cabecera por ti:

use MIME::Lite;
my $mime = MIME::Lite->new(
  From    => 'me@example.com',
  To      => 'you@example.com',
  Subject => 'A file',
  Type    => 'text/plain',
  Data    => 'The body text.',
);
$mime->attach(
  Type     => 'application/octet-stream',
  Data     => $bytes,
  Encoding => 'base64',
  Filename => 'hello.txt',
);

El argumento Encoding es el detonante: MIME::Lite codifica el adjunto en Base64 en líneas de 76 caracteres (con el salto de línea plano por defecto del módulo; lo que los convierte en CRLF es el transporte de correo) y estampa la parte con la cabecera Content-Transfer-Encoding correspondiente. Email::MIME toma la misma postura y codifica en Base64 cualquier adjunto que le pases como cadena de datos cruda (su documentación: "todas las partes creadas de esta forma se codifican con base64, por si acaso"). Si estás ensamblando un mensaje MIME crudo a mano, el equivalente son las dos líneas de la sección de doblado, encode_base64($bytes, "\r\n") más la línea de cabecera, y esa es toda la historia del lado del protocolo.

Bases de datos, configuración y variables de entorno

Bases de datos: los datos binarios a menudo viajan en una columna TEXT como Base64, porque la columna no puede prometer que dejará pasar bytes arbitrarios intactos. Guarda la forma de una sola línea, nunca la doblada, o tu próximo SELECT devolverá una cadena con saltos de línea en medio del valor:

use MIME::Base64 qw(encode_base64);
# $dbh es un manejador DBI ya conectado
my $stmt = $dbh->prepare(q{UPDATE photos SET data = ? WHERE id = ?});
$stmt->execute(encode_base64($bytes, ""), 42);

Los archivos de configuración tienen la misma forma: un documento JSON donde el campo binario o de secreto es una cadena Base64 de una sola línea, que es exactamente por qué existe el segundo argumento:

use JSON::PP qw(encode_json);
my $config = {
  api_key  => encode_base64($key_bytes, ""),
  logo_png => encode_base64($png_bytes, ""),
};
open my $fh, ">:raw", "app.json" or die $!;
print {$fh} encode_json($config);
close $fh;

Las variables de entorno merecen una palabra de advertencia. Base64 va bien para tokens pequeños en el entorno, pero la forma codificada es un 33 por ciento más grande que el original, y el sistema operativo pone techo a cada argumento. En Linux el límite es de 128 KB por cadena, impuesto por execve, y un blob grande en una variable de entorno no falla con educación: el proceso hijo muere con un error enigmático en el momento en que se crea. Valores pequeños en el entorno, valores grandes en un archivo o una base de datos.

Rendimiento: el que trabaja es C, no Perl

El módulo core está implementado en C, y ese C desciende de código escrito para metamail en 1991, que es un dato curioso hasta que notas la implicación: el codificador lleva tres décadas de ajuste. En una máquina moderna procesa datos a un ritmo de gigabytes por segundo, más rápido que el disco o la red a los que normalmente alimenta, así que el Base64 en sí casi nunca es el cuello de botella. El E/S sí.

Para el raro sistema sin compilador de C, el gemelo puro en Perl MIME::Base64::Perl en CPAN ofrece la misma interfaz básica, varias veces más lento pero todavía cómodo para cargas de trabajo ordinarias. Y dos hábitos mantienen los trabajos grandes predecibles: haz streaming con trozos de 57 bytes en lugar de slurpear, y dimensiona tus buffers con encoded_base64_length antes de asignar, lo que te ahorra tanto el tanteo como la reasignación.

Trampas, clasificadas por coste de tarde

Las trampas, en el orden en que muerden, más o menos:

Trampa Qué pasa Solución
Olvidar el segundo argumento la salida llega doblada a 76 caracteres con un salto de línea final, y tu URL, campo JSON o cabecera se rompe en medio del valor pasa "" para salida de una línea, y conserva el doblado para los destinos que lo esperan
Doblar con el ancho equivocado un consumidor PEM espera líneas de 64 caracteres y recibe 76, o un cuerpo MIME excede el límite de 76 caracteres empareja el ancho con el dialecto: "" para ninguno, "\r\n" para MIME, un helper para PEM
El croak de carácter ancho una cadena de caracteres con códigos por encima de 255 muere con Carácter ancho en entrada de subrutina a mitad de petición pasa los caracteres por Encode primero, nombrado a propósito, antes de la llamada a encode_base64
Codificación doble recodificar bytes ya UTF-8 a través de encode("UTF-8", ...) convierte Hëllo en Hëllo los bytes se codifican exactamente una vez; comprueba utf8::is_utf8() si tienes dudas
Mezclar alfabetos en silencio un valor codificado con - y _ choca con un decodificador de alfabeto estándar y vuelve como basura un dialecto por valor, de extremo a extremo: elige base64url o estándar en el límite
El eol final encode_base64 añade el eol incluso cuando la última línea está exactamente llena, y un consumidor estricto ve una línea en blanco chomp o rtrim el resultado cuando el consumidor es exigente
Valores doblados en una base de datos los saltos de línea caen dentro de una columna TEXT y el próximo SELECT devuelve un token roto guarda la forma de una sola línea; dobla solo en el destino
Variables de entorno con blobs grandes el crecimiento del 33 por ciento más el límite por argumento del sistema operativo mata al proceso hijo al crearlo con un error enigmático valores pequeños en el entorno, valores grandes en un archivo o una base de datos
Suponer que Base64 es protección el formato no oculta nada, y el registro público documenta incidentes reales donde un usuario pegó un intercambio IMAP y reveló accidentalmente una contraseña trata la salida como confidencial desde el momento en que se produce, y mantenla fuera de los registros
Planear sin la factura de tamaño una imagen de 500 KB se convierte en 670 KB de texto, y el límite de almacenamiento o payload que no comprobaste muerde presupuesta 4/3 del tamaño original antes de comprometerte

Una historia contada por el codificador

El codificador Base64 de Perl tiene una carrera que merece un minuto, y empieza en la primera caja de herramientas web:

  • Nacido en libwww perl. El codificador empezó su vida como LWP::Base64, escrito por Martijn Koster y Joerg Reichelt, y Gisle Aas lo absorbió en libwww perl como MIME::Base64; ascendió a su propia distribución de CPAN en abril de 1997, versión 2.00, con una entrada del changelog que simplemente dice que está basado en libwww perl 5.08.
  • La era de la velocidad. La versión 2.07 en 1998 trajo una implementación en C del decodificador más rápida y más lista, unas 25 por ciento más veloz en las máquinas Linux modernas de entonces, y el ajuste continuó durante una década.
  • La era de Unicode. Perl 5.8 en 2002 trajo caracteres con códigos por encima de 255 a las cadenas corrientes, y el módulo respondió por etapas: la 2.12 en 2001 degradaba las cadenas UTF-8 antes de codificar, y el croak moderno de Carácter ancho en entrada de subrutina es la forma del codificador de mantener esa promesa. La sincronización 2.13 con el core ese mismo año trajo el soporte EBCDIC por el camino, un recordatorio de que el Base64 en Perl sigue corriendo en las mainframes.
  • La era de la línea de comandos. Las versiones desde la 2.14 en 2003 hasta la 3.05 en 2004 incluían un comando encode-base64 de verdad, junto con sus gemelos de decodificación y quoted-printable; la 3.06 en 2005 movió los scripts a una distribución aparte de MIME Base64 Scripts.
  • La llegada del seguro para URLs. El RFC 4648 estandarizó el alfabeto seguro para URLs en 2006, un módulo independiente MIME::Base64::URLSafe apareció ese mismo año, y el módulo core se puso al día en la 3.11 en 2010 con encode_base64url en una sola llamada.
  • La línea moderna. La versión 3.16 en 2020 reconstruyó el empaquetado y elevó el mínimo a Perl 5.6; los Perls core actuales traen la serie 3.16, y el módulo se mantiene dentro de la distribución core, que es un hogar tan seguro como puede tener un módulo core.

Datos curiosos, específicamente Perl

Las curiosidades que hacen de esta historia una buena:

  • El ejemplo de la POD es una frase mágica. Desde 1997, la propia documentación del módulo codifica Aladdin:open sesame, así que la cadena QWxhZGRpbjpvcGVuIHNlc2FtZQ== ha sido la tarjeta de visita del módulo durante casi treinta años.
  • El fin de línea por defecto es el que probablemente no esperabas. Es un \n plano, no el CRLF que habla MIME. La propia convención del RFC necesita el segundo argumento, y el módulo viene con el valor por defecto del programador, no el del protocolo.
  • La cadena vacía tiene una regla especial. Codifica nada y no recibes nada, sin salto de línea añadido: la única excepción documentada a la regla del eol final, y la razón de que un archivo vacío haga ida y vuelta limpio.
  • El primo IMAP lleva una coma. La variante de nombres de buzón del RFC 3501 cambia la / por una coma en el alfabeto, así que una cadena Base64 de un servidor IMAP puede contener una letra que el decodificador estándar trata como ruido.
  • El linaje de 1991 es real. La implementación en C desciende de metamail, el programa de correo de Bellcore de 1991, tres años antes de que naciera Perl 5, así que cada llamada a encode_base64 es en parte código de los noventa.
  • El gemelo puro en Perl tiene su propia historia. Cuando la versión 3.00 en 2004 quitó las implementaciones puras en Perl del módulo core, el changelog las llamó engorde que esconde problemas reales de las implementaciones XS y las relanzó como MIME::Base64::Perl, donde siguen viviendo.

Así que la próxima vez que unos bytes crudos necesiten viajar por un mundo solo de texto, ya conoces la historia entera. Una llamada a función hace el trabajo, el salto de línea oculto es una decisión que tomas con el segundo argumento, el croak de carácter ancho es la forma del codificador de mantener tu Unicode honesto, el dialecto seguro para URLs lleva siendo una llamada desde 2010, los archivos fluyen en trozos de 57 bytes, y la factura del 33 por ciento es el precio de la entrada. Y si un día necesitas hacer el viaje en la otra dirección, tomar una cadena de letras y sacar de vuelta los bytes originales, el artículo relacionado sobre la decodificación Base64 en Perl, enlazado abajo, cubre ese ritual con la misma profundidad.

Última actualización: 2026-09-08

Artículo relacionado: Decodificación Base64 en Perl: una guía completa