Subir un archivo
  1. base64hub
  2. Aprende Base64
  3. Prefijos Base64 habituales
Referencia

Prefijos Base64 habituales: reconoce un archivo

La mayoría de los formatos de archivo empiezan con unos bytes mágicos fijos, así que su Base64 también empieza con caracteres fijos. Aprende una docena de prefijos y distinguirás un PNG de un PDF sin decodificar nada.

Tabla de prefijos

Cada fila se comprobó codificando los bytes mágicos reales del formato. El «prefijo estable» es la parte que nunca cambia en ese formato. Los caracteres que siguen dependen del resto del archivo.

Prefijo Base64Bytes mágicos (hex)FormatoÁbrelo con
iVBORw0KGgo89 50 4E 47 0D 0A 1A 0APNGBase64 a PNG
/9j/FF D8 FFJPEGBase64 a JPG
R0lGOD47 49 46 38 (GIF8)GIF (R0lGODlh = GIF89a, R0lGODdh = GIF87a)Base64 a GIF
UklGR52 49 46 46 (RIFF)WebP, WAV, AVIBase64 a WebP, Base64 a WAV
JVBERi025 50 44 46 2D (%PDF-)PDFBase64 a PDF
UEsDB50 4B 03 04 (PK..)ZIP, DOCX, XLSX, PPTX, JAR, APK, EPUBBase64 a ZIP, Word, Excel
H4sI1F 8B 08gzipDecodificar Base64 gzip
eJ, eN, eF, eA78 9C, 78 DA, 78 5E, 78 01zlibZlib y Base64
eyJ7B 22 ({")Objeto JSON, JWTBase64 a JSON, decodificador JWT
PD94bWwg3C 3F 78 6D 6C 20 (<?xml )XML, SVG con declaraciónBase64 a XML
PHN2Zy3C 73 76 67 20 (<svg )SVG sin declaración (<svg más un salto de línea da PHN2Zw)Base64 a SVG
MII30 82DER: certificados, claves, CSRdecodificador de certificados
AAAA00 00 00Blob de clave pública SSH, o ceros inicialeshuella de clave SSH
SUQz49 44 33 (ID3)MP3 con etiqueta ID3v2Base64 a MP3
AAABAA00 00 01 00ICOBase64 a ICO
d09GMg77 4F 46 32 00 (wOF2)Fuente WOFF2 con contornos TrueType (las fuentes CFF empiezan por d09GMk9UVE8)Base64 a fuente
TVqQ4D 5A 90 (MZ)EXE o DLL de Windows (algunos enlazadores escriben MZP, que da TVpQ)Base64 a archivo
f0VMR7F 45 4C 46 (.ELF)Binario ELF de LinuxBase64 a archivo

Algunas filas merecen un comentario:

  • RIFF es un contenedor. El nombre del formato está en los bytes 8 a 11, y los bytes 9 a 11 se codifican como los caracteres 13.º a 16.º: RUJQ para WebP (EBP), QVZF para WAV (AVE), Vkkg para AVI (VI ). La primera letra del nombre del formato comparte grupo de 3 bytes con el tamaño del archivo, así que no produce un carácter estable.
  • zlib no tiene un único prefijo. El segundo byte indica el nivel de compresión: eJ para el nivel por defecto, eN para los niveles 7 a 9, eF para 2 a 5, eA para 0 y 1 (tal como los escribe zlib de Python).
  • JSON empieza por eyJ solo cuando los dos primeros caracteres son {" sin espacio. { "a": 1 } empieza por eyAi, un { formateado con salto de línea empieza por ewo y un array [ empieza por W.
  • DER: las estructuras empiezan con una etiqueta SEQUENCE 30, que siempre da M. Una longitud de dos bytes (30 82) da MII, y el siguiente carácter depende de la longitud: una clave pública RSA 2048 es MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA, y un certificado típico es MIIC, MIID o MIIE. Las estructuras cortas usan una longitud de un byte: una clave privada Ed25519 empieza por MC4C y una clave pública P-256 por MFkw.
  • Claves públicas SSH: empiezan con una longitud big-endian de 4 bytes, así que el blob empieza por AAAA. Los caracteres siguientes deletrean el tipo de clave: AAAAC3NzaC1lZDI1NTE5 es ssh-ed25519, AAAAB3NzaC1yc2E es ssh-rsa, AAAAE2VjZHNh es ecdsa. Fuera de SSH, una serie de A significa bytes cero.
  • MP3: los archivos sin etiqueta ID3 empiezan directamente con una cabecera de trama. Sus bits de sincronización FF Fx dan un // inicial, por ejemplo //uQ para FF FB 90.
  • Base64URL sustituye + y /, así que el prefijo de JPEG pasa a ser _9j_. Los demás prefijos de la tabla no contienen ninguno de los dos caracteres y se ven igual en ambos alfabetos.

Por qué el prefijo es estable

Base64 trabaja con grupos de 3 bytes. Cada grupo de 3 bytes se convierte exactamente en 4 caracteres, y esos 4 caracteres dependen solo de esos 3 bytes. Nada de lo que viene después en el archivo influye hacia atrás. Así que si un formato siempre empieza con los mismos 3 bytes, su Base64 siempre empieza con los mismos 4 caracteres.

bytes:   FF       D8       FF
bits:    11111111 11011000 11111111
groups:  111111 111101 100011 111111
index:   63     61     35     63
chars:   /      9      j      /

Cuando la parte mágica fija no mide un múltiplo de 3 bytes, el último grupo mezcla bits conocidos con bits del resto del archivo. Toma los 5 bytes de %PDF-. Los 3 primeros bytes dan 4 caracteres estables (JVBE). Los 2 siguientes dan 2 más (Ri), y el séptimo carácter mezcla los últimos 4 bits de - con los 2 primeros bits del dígito de versión. Todos los dígitos empiezan por los bits 00, así que en la práctica ese carácter siempre es 0. Después de JVBERi0 asoma la versión: JVBERi0xLjQ es %PDF-1.4, JVBERi0xLjc es %PDF-1.7, JVBERi0yLjA es %PDF-2.0.

La firma PNG tiene 8 bytes, lo que da 10 caracteres estables. El undécimo mezcla el último byte de la firma con el primer byte de la longitud del bloque IHDR, que siempre es 0, así que iVBORw0KGgo se mantiene. Como todo PNG continúa con ese bloque IHDR, los PNG reales comparten un prefijo aún más largo: iVBORw0KGgoAAAANSUhEUg.

Cuándo se desplaza el prefijo

El prefijo solo funciona cuando los bytes mágicos están en la posición 0, 3, 6, etc. Añade un byte delante y todos los grupos se desplazan, así que los caracteres cambian por completo:

EntradaEl Base64 empieza por
Firma PNGiVBORw0KGgoAAAA
1 byte + firma PNGAIlQTkcNChoKAAAA
2 bytes + firma PNGAACJUE5HDQoaCgAA
3 bytes + firma PNGAAAAiVBORw0KGgoA

Con 3 bytes extra se recupera la alineación y el prefijo conocido reaparece 4 caracteres después. Motivos habituales de un prefijo desplazado o ausente:

  • Una marca de orden de bytes (BOM). El texto UTF-8 con BOM empieza por 77u/ (EF BB BF). La BOM mide 3 bytes, así que un JSON detrás sigue mostrando eyJ: 77u/eyJ…. El texto UTF-16 con BOM empieza por //4 o //5 (little-endian) o por /v8 (big-endian).
  • Texto UTF-16. El texto guardado como UTF-16LE pone un byte cero detrás de cada carácter ASCII, lo que produce muchas A: Hello se convierte en SABlAGwAbABvAA==. El -EncodedCommand de PowerShell tiene este aspecto. Usa el decodificador de PowerShell o Base64 a UTF-16.
  • Compresión o cifrado. Un PNG comprimido con gzip empieza por H4sI, y un archivo cifrado no tiene ningún prefijo reconocible.
  • Una data URI. data:image/png;base64, es una cabecera; el Base64 empieza después de la coma. El analizador de data URI las separa por ti.
  • Saltos de línea y espacios. No desplazan los bytes, pero una búsqueda del prefijo con startswith fallará si la cadena empieza por un salto de línea o unas comillas. Recorta antes, o pásala por Reparar Base64.

Comprobar un prefijo en código

Puedes comparar los primeros caracteres como cadenas, pero comparar los bytes decodificados da menos errores: los números mágicos salen directamente de la especificación de cada formato y nunca tienes que averiguar qué caracteres son estables. Decodificar solo los 12 primeros caracteres da los 9 primeros bytes, suficiente para la mayoría de las firmas:

import base64

SIGNATURES = {
    b"\x89PNG\r\n\x1a\n": "png",
    b"\xff\xd8\xff": "jpeg",
    b"%PDF-": "pdf",
    b"PK\x03\x04": "zip",
    b"\x1f\x8b": "gzip",
}

def sniff(b64: str) -> str:
    head = base64.b64decode(b64.strip()[:12])
    for magic, name in SIGNATURES.items():
        if head.startswith(magic):
            return name
    return "unknown"

print(sniff("iVBORw0KGgoAAAANSUhEUgAAAAEAAAAB"))  # png
print(sniff("JVBERi0xLjcKJcfsj6IK"))              # pdf

La herramienta Base64 a archivo hace la misma comprobación con una lista más larga y muestra una vista previa cuando el navegador puede representar el formato. Para ver cómo se asignan los grupos de 6 bits a caracteres, consulta cómo funciona Base64 y la tabla del alfabeto.

Preguntas frecuentes

¿Qué significa una cadena Base64 que empieza por iVBORw0KGgo?

Es una imagen PNG. iVBORw0KGgo es la forma Base64 de la firma PNG de 8 bytes 89 50 4E 47 0D 0A 1A 0A. Pégala en Base64 a PNG para verla.

¿Qué es /9j/ al principio de una cadena Base64?

Un JPEG. Los bytes FF D8 FF con los que empieza todo archivo JPEG se codifican como /9j/. En Base64URL el mismo prefijo se escribe _9j_.

¿Por qué los JWT siempre empiezan por eyJ?

La cabecera de un JWT es un objeto JSON, así que empieza por {", y esos dos bytes se codifican como eyJ. La parte de la carga útil empieza por eyJ por la misma razón.

Mi Base64 no coincide con ningún prefijo conocido. ¿Y ahora qué?

Puede que los datos tengan bytes de más delante, estén comprimidos o cifrados, o sean texto normal. La herramienta Base64 a archivo decodifica los datos y compara los bytes con muchas firmas.

Sigue leyendo