Français

Outils de développement · Encodeur et décodeur d'URL

Punycode vs codage en pourcentage : comment les domaines et chemins non-ASCII sont gérés

· Contexte

internationalisation punycode encodage d'URL

Noms de domaine convertis en punycode tandis que les chemins restent codés en pourcentage
Illustration vectorielle originale de ToolAcre

Une URL avec un nom d'hôte non-ASCII et un chemin non-ASCII utilise deux encodages complètement différents. Cet article explique l'IDNA et le punycode pour l'hôte, le codage en pourcentage pour tout le reste et pourquoi la division existe.

L'adresse qui affiche « münchen.example » dans un navigateur et « xn--mnchen-3ya.example » dans un autre — un hôte, deux orthographes

La ville München apparaît dans un nom de domaine allemand. Dans la barre d'adresse de votre navigateur, vous pourriez voir münchen.example affiché normalement. Copiez l'adresse d'une autre application et elle apparaît sous la forme xn--mnchen-3ya.example, une chaîne uniquement ASCII qui ne ressemble en rien au texte allemand. Une URL, deux orthographes, toutes deux absolument valides. Ni l’un ni l’autre n’a tort ; ils représentent le même domaine en utilisant des jeux de caractères complètement différents. Cette différence reflète une contrainte fondamentale sur le fonctionnement du DNS et sur la manière dont l'infrastructure Internet s'attend à ce que les noms d'hôtes soient transmis.

Les segments de chemin comme /café/ nécessitent un encodage mais utilisent un système différent. Le é non-ASCII devient %C3%A9 dans les chemins. Pourquoi cette différence ? Les contraintes DNS nécessitent du punycode pour les noms d'hôtes.

Pourquoi les noms d'hôtes ne peuvent pas utiliser le codage en pourcentage : étiquettes DNS, caractères autorisés et limites de longueur

Les étiquettes DNS, les segments individuels d'un nom d'hôte séparés par des points, ont des règles très strictes. Ils ne peuvent contenir que des lettres ASCII, des chiffres, des traits d'union et des traits de soulignement. Ils ont des limites de longueur : chaque étiquette peut contenir au maximum 63 octets, et le nom d'hôte complet ne peut pas dépasser 255 octets. Il s’agit de contraintes strictes issues du protocole DNS lui-même, défini il y a des décennies avant même que les noms de domaine internationaux ne soient un concept. Le codage en pourcentage ne peut pas fonctionner pour les noms d'hôtes car la chaîne résultante dépasserait probablement les limites des étiquettes sur les mots plus longs.

Plus important encore, le DNS est un système mondial exploité par des routeurs et des serveurs du monde entier. Tous ne comprennent pas UTF-8 ou Unicode. Un caractère codé en pourcentage tel que %C3%A9 comporte toujours trois caractères ASCII, il correspond donc aux contraintes DNS. Mais cette approche signifie que chaque recherche doit coder en pourcentage à l’entrée et décoder à la sortie, ce qui ajoute de la complexité à la couche de protocole elle-même. Une meilleure solution était nécessaire pour les noms d'hôtes en particulier.

IDNA et punycode en bref - le préfixe xn-- et l'algorithme de démarrage, décrits qualitativement

IDNA, la spécification des noms de domaine internationalisés dans les applications, résout le problème du nom d'hôte en codant les noms de domaine non-ASCII en ASCII que DNS peut gérer. Le codage utilisé est appelé punycode, un algorithme de compression qui transforme le texte Unicode en ASCII en utilisant le préfixe xn-- suivi d'une représentation codée en chaîne de démarrage. L'algorithme est déterministe : münchen devient toujours xn--mnchen-3ya à chaque fois. Tout nom d'hôte non-ASCII doit être converti de cette manière avant que la résolution DNS puisse avoir lieu.

Le préfixe xn-- signale au DNS et aux logiciels compatibles IDNA que les caractères suivants sont du punycode, et non des lettres ASCII littérales. Un domaine tel que example.xn--mnchen-3ya.com est compris comme signifiant example.münchen.com par un logiciel compatible IDNA. Punycode utilise uniquement des lettres, des chiffres et des traits d'union ASCII, il s'intègre donc parfaitement et sans problème dans les étiquettes DNS. L'algorithme compresse les informations non-ASCII dans cette représentation ASCII.

Les chemins, requêtes et fragments restent codés en pourcentage — UTF-8 octets à %XX, comme ailleurs

Tout le reste d'une URL (le chemin, la chaîne de requête, le fragment) utilise à la place un codage en pourcentage. Un caractère non-ASCII est d'abord converti en UTF-8 octets, puis chaque octet est écrit sous la forme %HH où HH est hexadécimal. Le chemin /café/ devient /caf%C3%A9/. La chaîne de requête ?name=josé devient ?name=jos%C3%A9. Le codage en pourcentage est standard partout sur le Web : dans les URL de requête HTTP, dans les formulaires HTML, dans les API. Il ne nécessite pas de traitement particulier de la part du DNS ou des routeurs.

Le codage en pourcentage permet également de représenter en toute sécurité d'autres caractères spéciaux. Un espace devient %20, une barre oblique (si elle doit apparaître à l'intérieur d'une valeur) devient %2F, et ainsi de suite. Le schéma est cohérent et universel. Il n'est pas utilisé pour les noms d'hôte car DNS ne comprend pas les URL ou le codage en pourcentage ; il ne comprend que les étiquettes ASCII.

Exemple pratique : une URL avec les deux : l'hôte converti en punycode, le chemin codé en pourcentage, côte à côte

Prenez l'URL "https://münchen.example/café?city=münchen". Le nom d'hôte münchen doit être converti en punycode avant la recherche DNS : https://xn--mnchen-3ya.example/café?city=münchen. Mais attendez, le chemin et la requête sont également non-ASCII. Convertissez-les également : https://xn--mnchen-3ya.example/caf%C3%A9?city=m%C3%BCnchen. Maintenant, le nom d'hôte est en punycode, le chemin et la requête sont codés en pourcentage. Un navigateur affiche la version Unicode originale pour plus de lisibilité ; la requête HTTP transporte le version codée.

Dans l'outil d'encodage et de décodage d'URL, collez un chemin contenant du texte non-ASCII et comparez le mode à valeur unique (juste le chemin) avec le mode d'adresse entière (URL complète). L'outil vous montre le résultat codé en pourcentage pour le chemin. Le nom d'hôte, cependant, nécessite une conversion punycode distincte ; la plupart des outils de codage ne gèrent pas cela en ligne, alors lisez-le dans la documentation de l'outil.

Attaques d'homographes et raisons pour lesquelles les navigateurs affichent parfois du punycode : le raisonnement de sécurité derrière les règles d'affichage

Un acteur malveillant pourrait enregistrer un domaine en utilisant des lettres cyrilliques visuellement identiques aux lettres latines, comme "https://xn--80akhbyknj4f.example" (une version cyrillique de "example.example" en punycode). Si un navigateur l'affiche décodé sous forme de texte cyrillique, les utilisateurs risquent de ne pas remarquer la différence. Pour éviter les attaques d'homographes, les navigateurs affichent parfois la version punycode au lieu de la décoder. Un avertissement apparaît : ce domaine est entièrement ou majoritairement non-ASCII et vous risquez de ne pas reconnaître les caractères.

L'encodeur et le décodeur d'URL sont un outil d'encodage et de décodage, et non d'évaluation de la sécurité. Si vous travaillez avec des noms de domaine internationaux, sachez que la représentation punycode est ce que voit le réseau.

Ce que cela ne couvre pas : exécuter l'algorithme punycode à la main ou les différences IDNA 2003 par rapport à 2008

IDNA a connu plusieurs versions au fil du temps : IDNA 2003 et IDNA 2008 gèrent certains cas extrêmes différemment, en particulier en ce qui concerne la normalisation et les caractères Unicode autorisés par la spécification. Certains systèmes plus anciens utilisent toujours IDNA 2003 tandis que d'autres ont migré vers IDNA 2008 pour une meilleure conformité. Les différences sont significatives si vous créez des systèmes qui doivent être compatibles entre plusieurs versions. Vérifiez toujours soigneusement la configuration requise de votre système.

Punycode utilise la compression bootstring. Des implémentations existent dans des langages courants, mais vérifiez la politique IDNA avec votre système de nom d'hôte. Testez la résolution et le comportement d’affichage plutôt que de supposer.

À retenir : deux encodages pour deux tâches – comment l'encodeur et le décodeur d'URL gèrent les parties codées en pourcentage et pourquoi un encodeur en pourcentage n'est pas le bon outil pour le nom d'hôte.

Les noms d'hôtes ont besoin de punycode car DNS est un ancien protocole qui ne comprend que les étiquettes ASCII et a des contraintes strictes de longueur et de caractères. Les chemins, requêtes et fragments utilisent le codage en pourcentage car il est universel sur le Web et ne présente pas ces contraintes. Ce sont deux solutions distinctes pour deux problèmes complètement différents. Lorsque vous rencontrez une URL non-ASCII, le nom d'hôte est d'abord converti en punycode, puis le reste utilise un codage en pourcentage.

Pour la plupart des travaux de développement, votre framework ou bibliothèque gère automatiquement cette conversion en arrière-plan. Mais comprendre pourquoi deux encodages différents existent évite toute confusion lors du débogage d’URL internationales ou de la mise en œuvre réussie de votre propre code de gestion d’URL.