Base64 expliqué : groupement de 6 bits, inflation de taille ~33%, rembourrage et base64url vs standard
Ce qu'est Base64 — et ce qu'il n'est pas
Base64 est un schéma d'encodage binaire-vers-texte. Il convertit des données binaires arbitraires en une chaîne de caractères ASCII imprimables, rendant ces données sûres à intégrer dans des contextes conçus pour du texte lisible par l'homme. Base64 n'est pas une compression — il rend les données plus volumineuses. Ce n'est pas non plus un chiffrement — quiconque possède la chaîne encodée peut récupérer les octets originaux de manière triviale. Le nom vient du fait qu'il utilise un alphabet de exactement 64 caractères, choisi parce que 2⁶ = 64 permet à chaque caractère de représenter exactement 6 bits d'entrée.
Base64 n'a pas été inventé comme standard autonome ; il est né du besoin d'envoyer des pièces jointes d'e-mail binaires via une infrastructure SMTP qui ne transmettait de manière fiable que l'ASCII 7 bits. RFC 2045 (1996), qui définit MIME, a standardisé l'encodage pour les e-mails. Une décennie plus tard, RFC 4648 (2006) a consolidé base64 et ses variantes — notamment base32 et base64url — dans un seul document de référence. RFC 4648 reste la spécification faisant autorité utilisée aujourd'hui par tout nouveau protocole nécessitant un encodage binaire-vers-texte.
Le groupement de 6 bits : comment trois octets d'entrée deviennent quatre caractères
Le coeur de base64 est une opération simple de réempaquetage de bits. Les données binaires arrivent en groupes d'octets de 8 bits ; base64 regroupe ces bits en morceaux de 6 bits, chacun mappant vers un caractère dans l'alphabet de 64 caractères. Comme le plus petit commun multiple de 6 et 8 est 24, l'unité de traitement naturelle est 3 octets = 24 bits → 4 caractères. En prenant Man comme exemple concret : les trois octets sont 0x4D, 0x61, 0x6E, donnant la séquence de bits 01001101 01100001 01101110. Regroupés en quatre valeurs de 6 bits : 010011 (19 → T), 010110 (22 → W), 000101 (5 → F), 101110 (46 → u). Le résultat encodé est TWFu.
Ce rapport de 3 à 4 octets est la source directe de l'inflation de taille. Pour chaque 3 octets d'entrée, la sortie est toujours 4 caractères quelle que soit la valeur réelle des octets. Pour n octets d'entrée, la sortie encodée est ceil(n / 3) × 4 caractères, ce qui signifie que la sortie est toujours 33% plus grande que l'entrée (exactement 4/3 fois plus grande). Un fichier de 1 Ko s'encode en environ 1,37 Ko ; une image de 1 Mo s'encode en environ 1,37 Mo.
L'alphabet : A–Z, a–z, 0–9, +, /
L'alphabet base64 standard mappe les valeurs de 6 bits 0–63 vers des caractères ASCII imprimables dans cet ordre : les valeurs 0–25 mappent vers A–Z majuscules, les valeurs 26–51 vers a–z minuscules, les valeurs 52–61 vers les chiffres 0–9, la valeur 62 vers +, et la valeur 63 vers /. Cet ordonnancement place les lettres avant les chiffres pour des raisons historiques de compatibilité MIME. Le choix de + et / pour les deux dernières valeurs a causé des décennies de problèmes d'interopérabilité, car ces deux caractères ont une signification spéciale dans les URLs.
Une idée reçue courante est que base64 est indépendant du jeu de caractères. Ce n'est pas le cas : l'alphabet est de l'ASCII fixe. Un décodeur qui rencontre un caractère en dehors de l'ensemble de 65 caractères (64 caractères de données plus = pour le rembourrage) doit soit rejeter l'entrée, soit l'ignorer selon le contexte de la spécification. RFC 4648 recommande de rejeter les caractères hors alphabet en mode strict. Le signe égal = est un marqueur, pas un caractère de données — il marque le rembourrage et ne doit jamais apparaître ailleurs qu'à la fin d'une chaîne encodée.
Le rembourrage : pourquoi les signes égal existent et quand on peut les omettre
Comme l'encodage traite 3 octets à la fois, les entrées dont la longueur n'est pas divisible par 3 laissent un groupe partiel à la fin. Le rembourrage résout ce problème : il force la sortie encodée à toujours être un multiple de 4 caractères, ce qui permet de calculer le nombre d'octets d'origine uniquement à partir de la longueur de sortie. Si l'entrée a 1 octet restant, 2 caractères de rembourrage == sont ajoutés. Si l'entrée a 2 octets restants, 1 caractère de rembourrage = est ajouté.
Le rembourrage est optionnel dans les contextes où la longueur totale est connue par d'autres moyens. RFC 7515, la spécification JSON Web Signature, exige explicitement que les implémentations omettent le rembourrage = lors de l'encodage des composants JWT, car les points entre les trois parties d'un JWT délimitent déjà les segments. Les valeurs encodées en base64url dans les JWT ne se terminent donc jamais par =. Restaurer le rembourrage est simple : ajouter des caractères = jusqu'à ce que la longueur de la chaîne soit un multiple de 4.
Base64url : la variante URL-safe utilisée dans les JWT et les tokens OAuth
Les caractères + et / du base64 standard posent problème dans les contextes URL. Un + dans une chaîne de requête est interprété comme un espace sous l'encodage application/x-www-form-urlencoded. Un / est un séparateur de segment de chemin. Base64url, défini dans RFC 4648 Section 5, remplace + par - et / par _. Ces deux caractères sont sûrs dans les URLs sans encodage en pourcentage. Le rembourrage = est également généralement omis dans les contextes base64url.
Base64url est utilisé partout où une représentation binaire compacte et URL-safe est nécessaire : les sections en-tête et charge utile d'un JWT sont du JSON encodé en base64url ; les codes d'autorisation OAuth 2.0 sont souvent des octets aléatoires encodés en base64url ; les vérificateurs et défis de code PKCE (RFC 7636) utilisent base64url. Le taux d'inflation des données est identique au base64 standard — exactement 4/3 — car seul l'alphabet diffère, pas l'algorithme de groupement de bits.
Impact pratique sur la taille et comment choisir entre base64 et binaire
La surcharge d'environ 33% est le principal coût pratique de base64. Pour les URI de données — intégrer des images, polices ou SVG directement dans du HTML ou CSS avec data:image/png;base64,... — le compromis est d'éliminer un aller-retour HTTP au coût d'un document plus volumineux. Ceci est bénéfique pour les petites ressources (typiquement inférieures à 4–8 Ko) : l'aller-retour économisé compense l'augmentation de taille. Pour les ressources plus grandes, l'augmentation de taille dégrade les performances car le document HTML plus grand prend plus de temps à analyser et ne peut pas être mis en cache séparément.
L'authentification HTTP Basic encode les identifiants comme base64(nom:motdepasse) dans l'en-tête Authorization: Basic .... Ce n'est pas une mesure de sécurité — le nom d'utilisateur et le mot de passe sont trivialement récupérables par décodage. L'authentification Basic nécessite HTTPS pour être sûre ; l'encodage base64 existe uniquement parce que la spécification des en-têtes HTTP exige de l'ASCII imprimable. Si une charge utile contient des informations sensibles, base64 n'est pas un substitut au chiffrement. Utilisez le chiffrement authentifié (par exemple AES-GCM) ou JSON Web Encryption (JWE, RFC 7516) pour les données confidentielles.