El último carácter contiene bits sin datos
RFC 4648 §3.5 exige que los codificadores conformes pongan a cero los bits de relleno. Con un byte de entrada solo los dos bits superiores del segundo carácter Base64 contienen datos; los otros cuatro son relleno. g tiene índice 32, 100000; h tiene 33, 100001. El byte de f es 01100110 y sus bits de datos coinciden. Zg== es la salida canónica; Zh== tiene bits de relleno distintos de cero. Los caracteres = finales no son los bits descartados.
Comprueba la decodificación y la nueva codificación
La decodificación tolerante de WHATWG Infra descarta cuatro bits finales de un grupo restante de 12 bits, o dos de uno de 18. HTML atob usa ese algoritmo. Moyoutil recupera bytes con atob y los interpreta como texto UTF-8. En los ejemplos ejecutados, Zg== y Zh== devolvieron f; Zm8= y Zm9= devolvieron fo. Al volver a codificar obtuvimos Zg== y Zm8=. El código siguiente recodifica bytes directamente, sin convertir binarios arbitrarios a texto UTF-8.
for (const input of ['Zg==', 'Zh==', 'Zm8=', 'Zm9=']) {
const bytes = atob(input);
const canonical = btoa(bytes);
console.log(input, bytes, canonical, input === canonical);
}
// Zg== f Zg== true
// Zh== f Zg== false
// Zm8= fo Zm8= true
// Zm9= fo Zm8= falseBytes iguales y cadenas originales iguales son condiciones distintas. Define qué igualdad necesita tu clave de caché o comparación. Si el protocolo receptor exige una representación canónica, valida sus reglas. No recomendamos modificar cadenas firmadas antes de verificarlas. Esta comparación solo abarca Base64 estándar con relleno; no valida todos los protocolos.
Preguntas frecuentes
¿Todos los decodificadores aceptan Zh==?
No. RFC 4648 permite rechazar bits de relleno no nulos, y otra especificación puede definir el comportamiento. Estos resultados corresponden a HTML atob y a la implementación actual de Moyoutil.