Charger un fichier
  1. base64hub
  2. Apprendre Base64
  3. Erreurs Base64
Dépannage

Erreurs de décodage Base64 et comment les corriger

La plupart des échecs Base64 ont l’une de ces cinq causes : le mauvais alphabet, un remplissage manquant, des caractères parasites, le mauvais jeu de caractères ou des données encodées deux fois. Trouvez votre message d’erreur ci-dessous et passez directement à la solution.

Les messages d’erreur en un coup d’œil

MessageOù vous le voyezCause la plus probable
binascii.Error: Incorrect paddingPython base64.b64decode= manquant à la fin, souvent à cause de Base64URL ou d’une chaîne tronquée
binascii.Error: Invalid base64-encoded string: number of data characters (5) cannot be 1 more than a multiple of 4PythonEntrée tronquée, ou -/_ supprimés en silence
binascii.Error: Only base64 data is allowedPython avec validate=TrueSaut de ligne, espace, - ou _ dans l’entrée
InvalidCharacterError: Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.Chrome, EdgeCaractères Base64URL, caractères parasites, longueur incorrecte
InvalidCharacterError: String contains an invalid characterFirefoxIdem
InvalidCharacterError: Invalid characterNode.js atobIdem
IllegalArgumentException (« Illegal base64 character … »)Java java.util.Base64Mauvais décodeur pour l’alphabet, ou sauts de ligne
FormatException.NET Convert.FromBase64StringCaractères Base64URL ou remplissage manquant
base64: invalid inputGNU coreutils base64 -dCaractères hors de l’alphabet

Corriger les erreurs du décodeur

« Incorrect padding » en Python

Une sortie Base64 a toujours une longueur multiple de 4, complétée par des = à la fin. Le décodeur de Python exige ce remplissage :

>>> import base64
>>> base64.b64decode("SGVsbG8")
Traceback (most recent call last):
  ...
binascii.Error: Incorrect padding
>>> base64.b64decode("SGVsbG8=")
b'Hello'

Un remplissage manquant signifie en général que la chaîne est en Base64URL (les JWT, les jetons d’URL et de nombreuses API suppriment les =), ou que quelque chose l’a rognée. Rajoutez le remplissage :

s = "SGVsbG8"
s += "=" * (-len(s) % 4)

Quand la longueur dépasse de un un multiple de 4, le remplissage n’y peut rien. Python signale alors number of data characters (5) cannot be 1 more than a multiple of 4. Un caractère restant ne contient que 6 bits : une partie des données manque. Ce message peut aussi apparaître sans que la chaîne soit tronquée : sans validate=True, Python écarte les caractères hors de l’alphabet, y compris - et _. base64.b64decode("SGk_Pg==") supprime le _ et se retrouve avec 5 caractères de données. Utilisez base64.urlsafe_b64decode pour une entrée Base64URL.

« Invalid character » et échecs d’atob

Les navigateurs implémentent atob avec le même algorithme, mais formulent l’erreur différemment. Chrome dit « The string to be decoded is not correctly encoded », Firefox « String contains an invalid character », Node.js « Invalid character ». Tous trois lèvent une InvalidCharacterError pour ces entrées :

  • Des caractères Base64URL. atob("SGk_Pg") échoue à cause du _. Remplacez d’abord - par + et _ par /.
  • Une longueur de 4n+1 une fois les espaces retirés, comme atob("A").
  • Des caractères qui n’ont rien à faire là : guillemets copiés depuis du JSON, préfixe data:, %2F issu de l’encodage d’URL.

atob pardonne certaines choses. Il ignore les espaces et les sauts de ligne, et accepte un remplissage manquant quand la longueur le permet : atob("SGVsbG8") renvoie "Hello". L’erreur inverse, btoa qui échoue avec « characters outside of the Latin1 range », concerne le texte Unicode et est traitée dans Uint8Array.toBase64.

Un décodeur tolérant qui gère les deux alphabets, les espaces et le remplissage manquant :

function decodeLoose(s) {
  s = s.replace(/\s+/g, "").replace(/-/g, "+").replace(/_/g, "/");
  s += "=".repeat((4 - (s.length % 4)) % 4);
  return Uint8Array.from(atob(s), (c) => c.charCodeAt(0));
}

new TextDecoder().decode(decodeLoose("SGk_Pg")); // "Hi?>"

L’équivalent en Python :

import base64

def b64decode_any(s: str) -> bytes:
    s = "".join(s.split())
    s = s.replace("-", "+").replace("_", "/")
    s += "=" * (-len(s) % 4)
    return base64.b64decode(s, validate=True)

L’outil Réparer Base64 applique le même nettoyage et vous dit ce qu’il a modifié.

« Illegal base64 character » en Java et FormatException en .NET

Le java.util.Base64 de Java fournit trois décodeurs, chacun strict sur son propre alphabet. Le message donne le caractère fautif en hexadécimal : 5f pour _, 2d pour -, 2f pour /, 20 pour une espace, a pour un saut de ligne.

L’entrée contientUtilisez
+ et /Base64.getDecoder()
- et _Base64.getUrlDecoder()
Des sauts de ligne (MIME, corps PEM)Base64.getMimeDecoder()

Le décodeur basic rejette les sauts de ligne et les espaces. Il accepte en revanche un remplissage manquant : SGVsbG8 se décode sans protester.

Convert.FromBase64String de .NET lève une FormatException pour les caractères Base64URL et pour un remplissage manquant. Il ignore les espaces et les sauts de ligne. Corrigez l’alphabet et le remplissage comme montré plus haut avant de l’appeler. Voir Base64 en Java et Base64 en C# pour des exemples complets.

Le texte sort illisible

Le décodage a réussi, mais le texte a l’air faux. Base64 stocke des octets, et ces octets ont été produits à partir d’un texte avec un certain encodage de caractères. Relisez-les avec un autre et vous obtenez du mojibake.

Vous voyezOriginalCe qui s’est passé
CaféCaféOctets UTF-8 lus comme du Latin-1 ou du Windows-1252
Caf�CaféOctets Windows-1252 lus comme de l’UTF-8
H e l l o ou H\0e\0l\0l\0o\0HelloOctets UTF-16LE lus comme de l’UTF-8

La première ligne est le piège classique d’atob. atob("Q2Fmw6k=") renvoie "Café", car atob associe chaque octet à un caractère. Décodez plutôt les octets en UTF-8 :

const bytes = Uint8Array.from(atob("Q2Fmw6k="), (c) => c.charCodeAt(0));
new TextDecoder().decode(bytes); // "Café"

L’UTF-16LE est courant avec les outils Windows : le -EncodedCommand de PowerShell et de nombreuses API .NET en produisent. Base64 en texte vous permet de changer de jeu de caractères jusqu’à ce que la sortie soit lisible, et Base64 en UTF-16 gère le cas des caractères larges.

La sortie ressemble à du binaire

Si le résultat décodé est plein de �, de caractères de contrôle ou de fragments PNG, PK et %PDF, le contenu est un fichier. Regardez les premiers caractères du Base64 : iVBORw0KGgo indique un PNG, JVBERi0 un PDF, H4sI du gzip. La liste complète se trouve dans les préfixes Base64 courants. Ouvrez les données avec Base64 en fichier, qui détecte le format et propose un téléchargement. Pour H4sI, utilisez décoder du gzip en Base64.

Le décodage donne d’autres octets que prévu

Pas d’erreur, mais les octets sont faux. Voici les raisons habituelles :

  • Un saut de ligne final au moment de l’encodage. echo "hello" | base64 donne aGVsbG8K (avec \n), tandis que echo -n "hello" | base64 donne aGVsbG8=. Utilisez printf '%s' ou echo -n.
  • Un + transformé en espace. Dans les chaînes de requête d’URL et les corps de formulaire, + signifie espace. URLSearchParams("t=PGI+Ym9sZDwvYj4=").get("t") renvoie PGI Ym9sZDwvYj4=. Certains décodeurs lèvent alors une erreur, d’autres suppriment l’espace et produisent des octets sans queue ni tête. Encodez le Base64 en pourcentage avec encodeURIComponent avant de le placer dans une URL, ou utilisez Base64URL.
  • Un encodage en pourcentage resté en place. SGk%2FPg%3D%3D doit être décodé comme une URL en SGk/Pg== avant le décodage Base64.
  • Des séquences d’échappement copiées depuis du JSON. Copier une chaîne depuis du JSON brut peut ramener un \n littéral (deux caractères). Le décodeur tolérant de Python supprime la barre oblique inverse, garde le n et renvoie des octets faux sans erreur : b64decode("SGVs\\nbG8=") donne b'Hel\x9d\xb1\xbc'. Analysez le JSON au lieu d’y copier des valeurs. Le décodeur Base64 pour JSON le fait pour chaque champ.
  • Espaces : strict ou tolérant. Python sans validate=True, atob, .NET et le décodeur MIME de Java ignorent les sauts de ligne. Python avec validate=True et le décodeur basic de Java les rejettent. Les données MIME et PEM sont coupées à 76 ou 64 caractères : choisissez un décodeur qui les accepte.

Des données encodées deux fois

Décoder U0dWc2JHOGdkMjl5YkdRaA== donne SGVsbG8gd29ybGQh, qui est de nouveau du Base64 valide et se décode en Hello world!. Quand le résultat d’un décodage ne contient que des caractères Base64, avec une longueur multiple de 4, soupçonnez un double encodage.

Cela arrive souvent avec les Secrets Kubernetes. Les valeurs sous data: sont en Base64, et kubectl create secret --from-literal encode pour vous. Si vous encodez d’abord la valeur vous-même, le pod reçoit du texte Base64 au lieu du mot de passe. Utilisez stringData: pour les valeurs en clair, ou vérifiez ce qui est stocké avec le décodeur de secrets Kubernetes. En cas de doute, le validateur Base64 indique si une chaîne est valide et combien d’octets elle contient.

FAQ

Comment se débarrasser de binascii.Error: Incorrect padding ?

Ajoutez des = jusqu’à ce que la longueur soit un multiple de 4 : s += "=" * (-len(s) % 4). Si la chaîne est en Base64URL, remplacez aussi - par + et _ par /, ou utilisez base64.urlsafe_b64decode.

Pourquoi atob échoue-t-il sur un JWT ?

Les JWT utilisent Base64URL, qui contient - et _. atob ne connaît que + et /. Convertissez d’abord les caractères, ou collez le jeton dans le décodeur JWT.

Pourquoi mon texte décodé affiche-t-il é au lieu de é ?

Les octets sont en UTF-8 mais ont été lus comme du Latin-1 ou du Windows-1252. Décodez les octets en UTF-8, par exemple avec TextDecoder en JavaScript ou .decode("utf-8") en Python.

Peut-on réparer une chaîne Base64 de longueur 4n+1 ?

Non. Un caractère restant ne porte que 6 bits, moins qu’un octet : au moins un caractère manque. Retrouvez la source d’origine ou vérifiez où la chaîne a été coupée.

Comment savoir si des données ont été encodées deux fois en Base64 ?

Décodez-les une fois. Si le résultat est de nouveau une chaîne composée uniquement de A-Z a-z 0-9 + / = et dont la longueur est un multiple de 4, décodez-la encore.

Continuer la lecture