Aussi disponible en : English · Español · Português · العربية
Encoder et décoder du base32
Du texte vers le base32 et retour, avec les deux alphabets de la RFC 4648, de vraies règles de remplissage et un avertissement quand un encodage n’est pas canonique.
Qu’est-ce que le base32 ?
Le base32 représente des octets quelconques au moyen de 32 caractères imprimables, afin que des données qui ne sont pas du texte puissent traverser des endroits qui n’acceptent que du texte. Il est défini par la RFC 4648, la spécification qui définit aussi le base64 et le base16, et il travaille par groupes de cinq octets : quarante bits répartis en huit groupes de cinq, chaque groupe devenant un caractère.
La question évidente est de savoir pourquoi l’employer alors que le base64 existe et prend moins de place. Le base32 coûte huit caractères pour cinq octets contre quatre pour trois au base64 : un rapport de 8/5 contre 4/3, ce qui place le base32 exactement à 6/5, soit 20 pour cent de plus. Ces 20 pour cent achètent une seule propriété : l’alphabet ne distingue pas la casse. Le base64 a besoin des minuscules et des majuscules pour atteindre 64 caractères, si bien que tout ce qui unifie la casse le détruit. Le base32 n’utilise que 26 lettres et six chiffres : il survit donc aux systèmes de fichiers insensibles à la casse, aux étiquettes DNS, aux noms d’hôtes, et au fait d’être lu à voix haute ou recopié à la main.
C’est là tout l’arbitrage, et il explique où le base32 apparaît réellement : dans les enregistrements DNSSEC, dans les liens magnet des réseaux d’échange, et dans les secrets partagés que conservent les applications d’authentification à deux facteurs, où c’est parfois un humain qui doit saisir la chose.
Comment l’utiliser
- Choisissez Encoder ou Décoder, puis un alphabet. Le standard est celui qu’il vous faut, sauf si vous savez le contraire. L’hex étendu est l’autre alphabet que définit la RFC 4648, et la section ci-dessous explique quand c’est le bon.
- Collez votre texte ou votre base32 dans la zone. À l’encodage, l’outil affiche les octets en entrée, les caractères en sortie et le rapport d’expansion. Au décodage, il est tolérant sur les espaces et sur les minuscules, car ni l’un ni l’autre ne porte de sens ici.
- Copiez le résultat. À l’encodage vous pouvez retirer le remplissage final par des signes égal, puisque les vraies spécifications le retirent. Et si vous collez quelque chose qui n’est pas un encodage canonique, l’outil le décode quand même et vous le signale, plutôt que de faire comme si l’entrée allait de soi.
Deux alphabets, et celui que personne n’implémente est celui qui se trie
La RFC 4648 définit le base32 deux fois. La section 6 donne l’alphabet connu : de A à Z, puis les chiffres de 2 à 7. La section 7 en donne un second, qu’elle appelle hex étendu : les chiffres de 0 à 9, puis de A à V. Presque toutes les implémentations ne proposent que le premier, et la raison d’être du second est exacte plutôt que décorative.
L’alphabet hex étendu suit l’ordre ASCII croissant. Les valeurs vont de 0 à 9 puis de A à V, c’est-à-dire l’ordre dans lequel ces caractères se trient déjà : la chaîne encodée se trie donc exactement comme les octets qu’elle représente. L’alphabet standard, lui, n’est pas dans l’ordre ASCII : il associe la valeur 0 à la lettre A, soit 0x41, et la valeur 26 au chiffre 2, soit 0x32. Les six dernières valeurs se trient donc avant les vingt-six premières, et l’ordre est rompu.
Voilà une affirmation qu’il vaut mieux mesurer que reprendre, et les tests la mesurent. Sur vingt mille paires générées de chaînes d’octets de même longueur, l’alphabet hex étendu préserve l’ordre de chacune d’elles sans exception. L’alphabet standard le préserve dans 74 pour cent des cas, autrement dit il a généralement l’air de fonctionner et il échoue précisément quand on compte dessus.
Cette propriété a un utilisateur réel, ce qui en est la meilleure confirmation. Les enregistrements NSEC3 de DNSSEC, spécifiés par la RFC 5155, stockent des noms de propriétaire hachés en base32 avec l’alphabet hex étendu, et la spécification dit pourquoi en toutes lettres : cet ordre est le même que l’ordre canonique des noms DNS lorsque les noms sont encodés ainsi. NSEC3 fonctionne en prouvant qu’aucun nom ne tombe dans l’intervalle entre deux voisins ; l’ordre n’y est donc pas un confort, c’est le mécanisme. La RFC 5155 se passe en outre entièrement du remplissage, et c’est pourquoi cet outil permet de le retirer.
Le prix est visuel, et plus subtil qu’il n’y paraît. L’alphabet standard n’évite pas simplement les caractères d’aspect ambigu : il conserve les lettres O et I, qui sont justement les ambiguës. Ce qu’il évite, ce sont les paires ambiguës — les chiffres 0 et 1 ne figurant pas dans l’alphabet, un O ne peut être qu’une lettre et un 1 ne peut jamais apparaître, si bien qu’aucune mauvaise lecture n’est possible. L’hex étendu contient 0, 1, O et I à la fois, et cette ambiguïté bien réelle est ce qu’il paie pour se trier.
Le remplissage, et trois longueurs qui ne peuvent pas exister
Les règles de remplissage du base32 sont plus strictes que celles du base64 et se trompent plus souvent. Comme huit caractères portent cinq octets, un groupe final incomplet laisse un corps de 2, 4, 5 ou 7 caractères, complété jusqu’à huit par 6, 4, 3 ou 1 signes égal respectivement. Ces quatre nombres ne sont pas une convention, c’est de l’arithmétique, et un décodeur qui accepte une autre quantité accepte une sortie qu’aucun encodeur n’a produite.
La conséquence la plus tranchante, c’est que trois longueurs sont impossibles. Le corps d’un base32 ne peut jamais dépasser un multiple de huit de 1, 3 ou 6 caractères, parce qu’aucun nombre d’octets en entrée ne les produit. À comparer au base64, où une longueur sur quatre seulement est impossible. Une chaîne base32 de mauvaise longueur n’est donc pas simplement courte ou tronquée : c’est la preuve que quelque chose est cassé en amont, et cet outil le dit au lieu de deviner ce qui était voulu.
Le remplissage lui-même est facultatif en pratique. Les exemples de la RFC l’incluent, DNSSEC l’omet explicitement, et les secrets d’authentification s’écrivent le plus souvent sans lui. Cet outil accepte l’entrée dans les deux formes et vous laisse choisir à l’encodage, parce que les deux sont légitimes et qu’un outil qui n’en imposerait qu’une aurait tort à propos de la moitié du monde.
Quand les mêmes octets ont plusieurs écritures
La section 3.5 de la RFC 4648 s’intitule Encodage canonique et décrit un problème que la plupart des outils ignorent. Lorsque le groupe final est incomplet, le dernier caractère porte quelques bits de données réelles et quelques bits résiduels. La spécification impose à tout encodeur conforme de mettre ces bits résiduels à zéro, et avertit que, dans le cas contraire, il n’existe pas de représentation canonique et que plusieurs chaînes différentes se décodent vers les mêmes données binaires.
Le nombre d’écritures est fixé par l’arithmétique. Un corps se terminant sur 2 caractères dispose de 2 bits libres : quatre chaînes différentes se décodent donc vers le même octet. Un corps de 4 caractères a 4 bits libres et seize écritures ; un corps de 5, 1 bit libre et deux ; un corps de 7, 3 bits libres et huit. Concrètement, la lettre f seule s’encode en MY, et MZ, M2 et M3 se décodent eux aussi en f.
La spécification se borne à dire qu’un décodeur peut rejeter une telle entrée, et comme il s’agit d’un peut, presque rien ne le fait. La bibliothèque standard de Python est un exemple honorable d’implémentation soignée : elle a accepté deux mille chaînes mutées sur deux mille, renvoyant les octets d’origine dans chaque cas sans un mot. C’est un comportement conforme, et c’est aussi ainsi que des données identiques finissent avec plusieurs représentations dans des systèmes qui les supposaient uniques.
Cet outil prend la troisième voie. Il décode l’entrée non canonique, parce qu’un refus serait peu utile et vous apprendrait moins, puis il indique que l’encodage n’était pas canonique et montre ce qu’un encodeur conforme aurait écrit. Si vous comparez quelque part des chaînes base32 par égalité — comme clés de cache, comme identifiants, pour éliminer des doublons — cette différence est exactement le bogue que vous cherchez.
Limites honnêtes
Cet outil encode et décode du texte, non des fichiers. L’entrée est traitée comme du texte et convertie en octets UTF-8 avant l’encodage ; au retour, les octets doivent former de l’UTF-8 valide, sinon l’outil le dit au lieu de vous rendre des caractères de remplacement. Cette dernière vérification signifie que vous ne pouvez pas faire transiter du binaire quelconque par le sens décodage, et c’est délibéré : abîmer des octets en silence est pire que les refuser.
Le base32 est un encodage et non un chiffrement. Il ne cache rien. Quiconque reconnaît le jeu de caractères le décode en quelques secondes, et le fait qu’une chaîne paraisse opaque ne protège de rien. Si vous voulez un texte que les autres ne puissent pas lire, il vous faut du chiffrement, qui est une autre page de ce site.
Enfin, les deux alphabets proposés ici sont les deux que définit la RFC 4648. D’autres variantes de base32 circulent — celle de Crockford, qui retire plusieurs lettres et en fusionne d’autres, ou z-base-32, qui réordonne l’alphabet pour l’usage humain — et elles ne sont interopérables ni avec celles-ci ni entre elles. Si une chaîne refuse de se décoder ici, la variante est la première chose à vérifier.
Pourquoi est-ce gratuit ?
Parce que cela ne coûte rien à faire tourner. L’encodage et le décodage se font dans votre navigateur au fil de la frappe ; rien n’est envoyé, rien n’est journalisé, et aucun serveur ne voit votre texte puisqu’aucun serveur n’intervient.
Il n’y a donc ni compte, ni inscription, ni rien réservé derrière l’un ou l’autre. Les alphabets et les règles de remplissage viennent de la RFC 4648 elle-même, les vecteurs de test de la suite sont ceux que publie la spécification, et les résultats sont confrontés à la bibliothèque standard de Python comme implémentation indépendante.