Français

Outils de développement · Encodeur et décodeur Base64

Base64 vs base64url : pourquoi un décodeur standard rejette - et _

· Comment ça marche

base64 codage flux de travail du développeur

Alphabet base64 vs substitutions base64url
Illustration vectorielle originale de ToolAcre

base64url échange + et / pour - et _ afin que la sortie puisse voyager dans les URL et les noms de fichiers sans s'échapper. Cet article explique les deux alphabets, comment les convertir entre eux et pourquoi le remplissage est également généralement supprimé.

Le jeton qui décode partout sauf votre code — une erreur de caractère invalide provoquée par un seul - ou _

Un segment JWT ne parvient pas à être décodé dans le décodeur Base64 standard avec un tiret de dénomination d'erreur de caractère non valide. Mais visuellement, aucun tiret n’apparaît. Regardez encore, c'est le cas. La version base64url utilise - où la norme Base64 utilise +, et _ où elle utilise /. De nombreux décodeurs n'acceptent qu'un seul alphabet, et le jeton codé pour la sécurité de l'URL sera rejeté par le code attendant la norme RFC 4648 Base64.

Les deux alphabets sont équivalents ; la conversion entre eux est un remplacement de caractère mécanique. Le problème se pose car + et / ont des significations dans les URL. Un signe plus représente l'espace dans les données du formulaire application/x-www-form-urlencoded. La barre oblique est le séparateur de chemin dans l'URL. Si vous intégrez Base64 directement dans le paramètre de requête URL sans pourcentage de codage + et le décodeur /, pourrait les interpréter mal.

Pourquoi + et / sont un problème dans les URL et les noms de fichiers — la signification réservée de / dans les chemins et de + en tant qu'espace dans les données de formulaire

Un + peut être lu comme un espace avant d'atteindre le décodeur. Un / pourrait diviser la valeur du paramètre au mauvais endroit. La section 5 de la RFC 4648 définit l'alphabet base64url pour éliminer toute ambiguïté : utilisez - au lieu de + et _ au lieu de /, afin que la sortie soit sécurisée dans les URL et les noms de fichiers. Les deux alphabets sont identiques sauf deux caractères.

Standard Base64 utilise des caractères aux positions 62 et 63 : A–Z (0–25), a–z (26–51), 0–9 (52–61), + (62), / (63). base64url utilise A–Z (0–25), a–z (26–51), 0–9 (52–61), - (62), _ (63). Tout le reste (regroupement de bits, règles de remplissage, mappage de bits aux index) est identique. La chaîne d'index pour Base64 standard produira une chaîne d'index pour base64url ; seul le caractère aux positions 62 et 63 sera différent.

L'alphabet base64url de la section RFC 4648 5 — les deux caractères substitués et pourquoi rien d'autre ne change

Si l'entrée ne contient aucun index 62 ou 63 (pas de + ou / en standard, non - ou _ en base64url), les deux alphabets produisent une sortie identique. La conversion de Base64 standard en base64url est une opération simple de recherche et de remplacement : échangez + pour - et / pour _. Le décodage de la chaîne base64url en Base64 standard nécessite l'inverse : swap - pour + et _ pour /.

La conversion est symétrique et toujours valide. Si vous rencontrez un jeton dont le décodage échoue avec une erreur de dénomination de caractère non valide - ou _, vérifiez si le décodeur accepte l'url base64. Sinon, appliquez la substitution de caractères, et si la saisie est par ailleurs bien formée, le décodage devrait réussir. Considérez l'en-tête JWT {"alg": "HS256", "typ": JWT"} codé en base64url. Les octets standard UTF-8 subissent un regroupement de bits : trois octets deviennent quatre indices, recherchés dans l'alphabet base64url. ToolAcre expose le remplissage comme choix d'encodeur plutôt que de le lier à la bascule alphabétique. Cette séparation est une preuve utile : la sortie sécurisée pour les URL peut être complétée ou non, tandis que le décodeur normalise l'une ou l'autre forme avant d'appeler la primitive du navigateur. L'alphabet et le remplissage sont des conventions liées, pas un seul commutateur.

Le remplissage dans base64url est facultatif par convention - pourquoi les JWT omettent = et comment un décodeur peut le restaurer à partir de la longueur

Lorsque l'index est 62, le caractère de sortie est - ; lorsque 63, la sortie est _. Des octets identiques via l'alphabet standard produiraient + à l'index 62 et / à l'index 63. La conversion du résultat base64url en standard s'effectue caractère par caractère : recherchez - et remplacez par +, recherchez _ et remplacez par /, puis décodez comme d'habitude.

Les octets que vous récupérez sont identiques car les index étaient identiques ; seuls les symboles diffèrent. Le remplissage dans base64url est facultatif par convention, même si la norme le permet. Les JWT sont structurés comme trois segments base64url reliés par des points ; chaque segment utilise un remplissage si nécessaire, mais de nombreuses implémentations l'omettent et s'appuient sur le fait que l'application consommatrice connaît la longueur d'octet attendue.

Exemple pratique : conversion d'un segment d'en-tête JWT en Base64 standard – remplacement de caractères, ajout de remplissage, décodage en JSON

Un décodeur peut restaurer le remplissage manquant en divisant la longueur de la chaîne par quatre, en calculant le reste, en ajoutant 0, 1 ou 2 signes égaux. Si la longueur de la chaîne n’est pas un multiple de quatre, un remplissage manquant est évident. Si la longueur est un multiple de quatre, la chaîne a été soit complétée puis le remplissage supprimé, soit entrée déjà un multiple de quatre octets (se terminant par trois octets dans le bloc final, ne nécessitant aucun remplissage).

La concaténation de segments base64url nécessite une attention particulière au remplissage. Si trois segments se terminent chacun par =, la concaténation produit directement des chaînes comme AAAA=BBBB=CCCC=, où le remplissage au milieu est désormais constitué de caractères parasites, et non de marqueurs de fin. C'est pourquoi les JWT omettent le remplissage dans chaque segment : la structure à trois segments est explicite, donc le décodage se déroule indépendamment sur chaque partie, et le remplissage au milieu de la chaîne concaténée est inutile et interromprait l'analyse.

Erreurs courantes : mélange d'alphabets dans une seule chaîne ou norme de codage en pourcentage Base64 au lieu d'utiliser base64url

Si vous créez une charge utile multi-segments, décidez de la convention de remplissage au début : soit incluez dans chaque segment et ne jamais concaténer directement, soit omettez et restaurez à partir de la longueur uniquement lors du décodage. La norme RFC 4648 fait autorité sur les deux alphabets. La section 4 spécifie la norme Base64 ; la section 5 spécifie l'url base64. Tout décodeur conforme doit indiquer clairement quel alphabet il accepte.

Le code acceptant base64url mais pas Base64 standard (ou vice versa) implémente uniquement un sous-ensemble. L'alphabet base64url existe pour la compatibilité avec les contraintes d'URL et de nom de fichier ; ce n'est pas une amélioration ou un remplacement, juste une variante pour un contexte spécifique. Lorsque vous créez une API ou un format de jeton, choisissez un alphabet et documentez lequel. Une erreur courante consiste à coder en pourcentage la norme Base64 au lieu d'utiliser base64url. L'implémentation explique également la limite de l'article. Il normalise les traits d'union et les traits de soulignement avant le décodage, mais il ne vérifie pas la signature du jeton ni n'interprète les revendications. La conversion d'un segment JWT en octets peut révéler JSON ; il ne peut pas établir qui a émis ce JSON ou si quelqu'un l'a modifié.

Ce que cela ne couvre pas : vérification des signatures JWT, base32 et des autres encodages RFC 4648

%2B est le code de pourcentage pour + ; %2F est le code de pourcentage pour /. Le codage en pourcentage transforme TWFu en TWFu inchangé (pas de caractères spéciaux) mais TE9S+g== en TE9S%2Bg%3D%3D (trop de caractères à gérer). La bonne solution consiste à utiliser base64url, qui produit déjà une sortie sécurisée pour les URL. Le codage en pourcentage en Base64 est superflu et inutile. Utilisez le bon alphabet pour le contexte. L'encodeur et décodeur Base64 accepte automatiquement les deux alphabets.

Si vous collez une chaîne contenant -, il la traite comme base64url ; si vous collez une chaîne contenant +, il la traite comme Base64 standard. L'outil accepte également les URL et les traite comme une entrée sécurisée pour les URL. Une vérification pratique a donc deux résultats indépendants : l'aller-retour des octets, et la représentation choisie correspond à son canal. Passer le premier indique que la transformation est réversible. Passer la seconde indique que la ponctuation et le remplissage ne seront pas réécrits par l'URL, le nom de fichier, le cookie ou le protocole qui les transporte.

À retenir : deux alphabets, une disposition en un bit – comment l'encodeur et le décodeur Base64 gèrent l'alphabet standard dans le navigateur et où sa page d'outils indique ce qu'il accepte

Lors du décodage du segment JWT ou du jeton sécurisé pour les URL, vous pouvez le coller directement sans conversion et l'outil identifie l'alphabet à partir du contexte. Le débogage du décodage échoué devient simple : collez le jeton, voyez si l'outil l'accepte, et sinon, échangez manuellement les caractères et réessayez.

La substitution elle-même est une ligne de code, mais un échec de décodage peut également provenir d'une longueur impossible, d'un remplissage mal placé, d'une corruption ou d'une entrée non Base64. L'outil normalise automatiquement les deux alphabets, donc l'acceptation confirme uniquement que les octets peuvent être récupérés. Une charge utile JWT décodée est toujours une réclamation non signée jusqu'à ce qu'un vérificateur distinct vérifie sa signature et l'algorithme attendu.