¿Por qué una cadena codificada en base64 tiene un signo = al final?

322

Sé lo que base64es la codificación y cómo calcular la base64codificación en C #, sin embargo, he visto varias veces que cuando convierto una cadena en base64, hay una =al final.

Surgieron algunas preguntas:

  1. ¿Una base64cadena siempre termina con =?
  2. ¿Por qué =se agrega un al final?
santosh singh
fuente
99
Esto no tiene absolutamente nada que ver con C #.
BoltClock
19
En realidad, está relacionado con c #, no todos los lenguajes incluirán el =, por ejemplo, muchas bibliotecas perl omiten el =, por lo que conocer el entorno que está utilizando el usuario es realmente relevante.
Jacob
Parece que esto lo convierte en un método menos efectivo de ofuscación en algunos casos, ya que es bastante detectable.
dgo
66
@ user1167442 Base64 no es para ofuscación. Es para transportar datos binarios (o cadenas con caracteres unicode y otros caracteres especiales) como una cadena.
NH.

Respuestas:

270

Sirve como relleno .

Una respuesta más completa es que una cadena codificada en base64 no siempre termina con un =, solo terminará con uno o dos =si es necesario para rellenar la cadena a la longitud adecuada.

Andrew Hare
fuente
3
"Un caso en el que se requieren caracteres de relleno es la concatenación de múltiples archivos codificados en Base64".
André Puel
1
@ AndréPuel: bastará con resincronizar un sencillo =. Si desea encontrar los límites, entonces siempre debe estar presente un terminador (y todavía se necesita solo un carácter). Todo el concepto de relleno de Base64 es solo un brainfart ...
6502
55
Sin embargo, ese enlace es completamente irrelevante para base64.
NH.
1
Solo deseo que se publique un enlace relevante y confiable que explique sobre el relleno base64eficientemente con ilustraciones y ejemplos. El enlace actual a wikipedia es absolutamente irrelevante como @NH. mencionado.
Fr0zenFyr
1
@ Fr0zenFyr Si quieres un enlace, en.wikipedia.org/wiki/Base64#Output_padding es bastante bueno. Pero la respuesta de Badr es realmente mejor (simplemente no se ha puesto al día en los votos).
NH.
313

1-no

2- Como respuesta breve: el carácter 65 (signo "=") se usa solo como complemento en el proceso final de codificación de un mensaje.

No tendrá un signo '=' si su cadena tiene un número múltiplo de 3 caracteres, porque la Base64codificación toma cada tres bytes (8 bits) y los representa como cuatro caracteres imprimibles en el estándar ASCII.

Detalles:

(a) Si quieres codificar

ABCDEFG <=> [ ABC] [ DEF] [G

Base64tratará (produciendo 4 caracteres) con el primer bloque y el segundo (a medida que estén completos) pero para el tercero agregará un doble ==en la salida para completar los 4 caracteres necesarios. Por lo tanto, el resultado será QUJD REVG Rw == (sin espacio)

(b) Si desea codificar ...

ABCDEFGH <=> [ ABC] [ DEF] [GH

Del mismo modo, agregará solo uno =al final de la salida para obtener 4 caracteres, el resultado será QUJD REVG R0g = (sin espacio)

Badr Bellaj
fuente
26
Esto es más completo y claro que otras respuestas e incluso Wikipedia y debería merecer más votos que la respuesta aceptada, que no hace más que señalar el enlace de wikipedia. ¡Felicitaciones a usted! ¡Votado!
ANewGuyInTown
2
@ANewGuyInTown el enlace de wikipedia en la solución aceptada es incorrecto, no tiene nada que ver con el relleno en base64. La página correcta fue vinculada por Legolas en su respuesta a continuación
Fr0zenFyr
Otra buena respuesta
spottedmahn
66

De Wikipedia :

La secuencia final '==' indica que el último grupo contenía solo un byte, y '=' indica que contenía dos bytes.

Por lo tanto, esto es algún tipo de relleno.

Legolas
fuente
16
  1. No.
  2. Para rellenar la cadena codificada en Base64 a un múltiplo de 4 caracteres de longitud, para que pueda decodificarse correctamente.
Ian Kemp
fuente
3
Quité el =al final y probé esto para 1 millón de cadenas. La decodificación siempre coincidía.
vivek_23
15

Se define en RFC 2045 como un carácter de relleno especial si hay menos de 24 bits disponibles al final de los datos codificados.

iandotkelly
fuente
11

El signo igual (=) se usa como relleno en ciertas formas de codificación base64. El artículo de Wikipedia sobre base64 tiene todos los detalles.

Sam Holloway
fuente
2
¿Podría explicar la lógica de por qué "==" es 1 byte y "=" es 2 bytes? Simplemente no puedo entenderlo. ¿Cómo es que la entrada: "cualquier placer carnal". podría obtener el resultado "YW55IGNhcm5hbCBwbGVhc3VyZS4 =", mientras que "cualquier placer carnal" podría obtener el resultado "YW55IGNhcm5hbCBwbGVhc3VyZQ =="?
nulo
14
No es ese caso que '==' es 1 byte y '=' es 2 bytes. Es el caso que necesita tener siempre un múltiplo de 4 bytes en toda su cadena. Así que rellena con signos '=' hasta que obtenga eso. La primera cadena tiene un carácter más que la segunda cadena, por lo que se requiere un '=' menos de relleno.
Sam Holloway
2
¿Se supone que esta respuesta es un comentario?
Fr0zenFyr
9

Es acolchado. De http://en.wikipedia.org/wiki/Base64 :

En teoría, el carácter de relleno no es necesario para la decodificación, ya que el número de bytes faltantes se puede calcular a partir del número de dígitos Base64. En algunas implementaciones, el carácter de relleno es obligatorio, mientras que para otras no se usa. Un caso en el que se requieren caracteres de relleno es la concatenación de múltiples archivos codificados en Base64.

Thomas Leonard
fuente
1
La parte sobre "Un caso en el que se requieren caracteres de relleno es la concatenación de múltiples archivos codificados en Base64". Está Mal. Por ejemplo, al concatenar dos archivos base64 donde los bytes de origen para cada archivo tienen 3 bytes, las cadenas base64 tendrán 4 caracteres y no tendrán bytes de relleno. Cuando concatene estas dos cadenas de base64, no habrá forma de saber dónde comienza una y dónde se detiene solo en la cadena concatenada. Por lo tanto, confiar en el relleno base64 para ayudar con eso no va a funcionar. Este problema existirá para cualquier archivo con longitudes de bytes divisibles por 3.
Ron C
1
Supongo que significa el caso en el que el resultado final debería ser la concatenación de las entradas. Por ejemplo, decode(encode(A)+encode(B))=A+Bfunciona con relleno pero no sin él.
Thomas Leonard
tal vez, pero un uso tan limitado no permite confiar en los caracteres de relleno para el caso general de separar cadenas codificadas cuando las cadenas codificadas se concatenan juntas. Solo lo menciono para ayudar a los desarrolladores que puedan estar pensando que pueden usarlo de esa manera.
Ron C
1
Creo que su objeción realmente resalta la diferencia entre los conceptos de relleno y delimitación. En general, no se espera que los resultados de la concatenación incluyan suficiente información para que sea reversible. No sabrá si "c3dpenpsZXJz" era originalmente "c3dpenps" + "ZXJz" o "c3dp" + "enpsZXJz". Pero tampoco sabe si "swizzlers" era originalmente "swi" + "zzlers" o "swizzl" + "ers".
GargantuChet
1
Al copiar mi comentario de una respuesta de relleno de Base64 relacionada :> La concatenación de Base64 [con '=' relleno] permite a los codificadores procesar grandes fragmentos en paralelo sin la carga de alinear los tamaños de los fragmentos a un múltiplo de tres. Del mismo modo, como detalle de implementación, puede haber un codificador que necesite vaciar un búfer de datos interno de un tamaño que no sea múltiplo de tres.
Andre D
7

http://www.hcidata.info/base64.htm

Codificando "Mary tenía" a la Base 64

En este ejemplo, estamos usando una cadena de texto simple ("Mary tenía") pero el principio se mantiene sin importar cuáles sean los datos (por ejemplo, archivo de gráficos). Para convertir cada 24 bits de datos de entrada en 32 bits de salida, la codificación Base 64 divide los 24 bits en 4 fragmentos de 6 bits. El primer problema que notamos es que "Mary tenía" no es un múltiplo de 3 bytes, tiene una longitud de 8 bytes. Debido a esto, el último grupo de bits tiene solo 4 bits de longitud. Para remediar esto, agregamos dos bits adicionales de '0' y recordamos este hecho poniendo un '=' al final. Si la cadena de texto que se convertiría a Base 64 tenía 7 bytes de longitud, el último grupo habría tenido 2 bits. En este caso, habríamos agregado cuatro bits adicionales de '0' y recordar este hecho al poner '==' al final.

Dev
fuente