Przejdź do zawartości

Punycode

Z Wikipedii, wolnej encyklopedii

Punycode – sposób kodowania napisów Unicode za pomocą ograniczonego zestawu znaków ASCII, zdefiniowany w dokumencie RFC 3492 na potrzeby mechanizmu nazw domen ze znakami narodowymi (IDNA). Przekształcenie jest jednoznaczne i odwracalne: znaki ASCII z napisu wejściowego są przepisywane dosłownie, a pozostałe znaki są reprezentowane za pomocą liter, cyfr i łączników, czyli znaków dozwolonych w etykietach nazw hostów[1]. Punycode jest szczególnym przypadkiem ogólniejszego algorytmu Bootstring, opisanego w tym samym dokumencie, z wartościami parametrów dobranymi dla IDNA[1]. W nazwach domen etykietę zakodowaną w ten sposób poprzedza się prefiksem xn--[2], na przykład nazwa kraków.pl przyjmuje postać xn--krakw-3ta.pl.

Historia

[edytuj | edytuj kod]

Dokument RFC 3492, którego autorem jest Adam Costello z Uniwersytetu Kalifornijskiego w Berkeley, powstał w grupie roboczej IDN organizacji IETF i został opublikowany w marcu 2003 roku ze statusem Proposed Standard[1][3]. W tym samym miesiącu ukazała się specyfikacja IDNA (RFC 3490), która w operacji ToASCII wskazała Punycode jako kodowanie etykiet zawierających znaki spoza ASCII[4]. W 2010 roku specyfikację IDNA zastąpiła nowa wersja, IDNA2008 (RFC 5890 i RFC 5891), która nie zmieniła algorytmu Punycode w żaden sposób, a jedynie formalnie zaktualizowała odwołania do niego[2][5].

Rejestr domeny .pl, prowadzony przez NASK, umożliwia rejestrację nazw ze znakami narodowymi od września 2003 roku i według NASK był pierwszym rejestrem w Europie, który to wprowadził. W 2024 roku NASK podawał, że znaków diakrytycznych użyto w ponad 25 tysiącach nazw w domenie .pl[6]. W domenie .pl dozwolone są między innymi polskie litery ą, ć, ę, ł, ń, ó, ś, ź i ż, a także znaki innych alfabetów, przy czym w jednej nazwie nie można mieszać znaków z różnych zestawów. Przedmiotem umowy z rejestrem jest nazwa w postaci ASCII z prefiksem xn-- i w takiej postaci jest ona przechowywana w DNS[7].

Punycode stosuje się także w nazwach domen najwyższego poziomu. Na przykład rosyjska domena .рф jest zarejestrowana w strefie głównej od 12 maja 2010 roku jako xn--p1ai[8].

Zasada działania

[edytuj | edytuj kod]

Algorytm Bootstring

[edytuj | edytuj kod]

Bootstring przedstawia dowolny ciąg kodów znaków (ang. extended string) jako ciąg podstawowych kodów znaków (ang. basic string). Specyfikacja wymienia jego cechy: zupełność (każdy ciąg rozszerzony ma reprezentację), jednoznaczność (istnieje co najwyżej jedna reprezentacja), odwracalność, wydajność (stosunek długości ciągu podstawowego do rozszerzonego jest niewielki), prostotę implementacji oraz czytelność (podstawowe kody znaków występują w wyniku jako one same)[1].

Kodowanie składa się z czterech elementów[1]:

  • Wydzielenie podstawowych kodów znaków – wszystkie podstawowe kody znaków z ciągu rozszerzonego są przepisywane dosłownie na początek wyniku, w pierwotnej kolejności, a po nich następuje ogranicznik, o ile liczba takich znaków jest niezerowa.
  • Kodowanie wstawień (ang. insertion unsort coding) – pozostała część wyniku opisuje kolejne wstawienia znaków spoza zbioru podstawowego. Dekoder zaczyna od części dosłownej i wstawia do niej brakujące znaki, przetwarzając je w kolejności rosnących wartości kodów, a nie w kolejności występowania. Jego stan opisują dwie zmienne: pozycja i w budowanym ciągu i licznik n, czyli bieżąca wartość kodu. Każda liczba delta jest długością serii stanów bez wstawienia, poprzedzających stan, w którym znak o kodzie n zostaje wstawiony na pozycji i.
  • Uogólnione liczby całkowite o zmiennej długości – delty są zapisywane cyframi w ustalonej podstawie, a koniec liczby rozpoznaje się po tym, że cyfra jest mniejsza od progu t(j), zależnego od jej pozycji j i parametru bias: t(j) = base · (j + 1) - bias, z ograniczeniem do przedziału od tmin do tmax.
  • Adaptacja parametru bias – po każdej delcie parametr bias jest dostosowywany, ponieważ bieżąca delta daje wskazówkę co do prawdopodobnej wielkości następnej, a pierwsza delta jest zwykle znacznie większa od drugiej.

Parametry Punycode

[edytuj | edytuj kod]

Punycode używa podstawy 36 oraz parametrów tmin = 1, tmax = 26, skew = 38, damp = 700, początkowej wartości bias równej 72 i początkowej wartości n równej 128 (0x80). Podstawowymi kodami znaków są kody ASCII (0..7F), ogranicznikiem jest łącznik (U+002D), a wartości cyfr mają litery od a do z (0–25, niezależnie od wielkości liter) oraz cyfry od 0 do 9 (26–35)[1]. Dekoder musi rozpoznawać zarówno wielkie, jak i małe litery, a koder powinien używać wyłącznie jednej wielkości liter[1].

Zakodowany napis może kończyć się łącznikiem tylko wtedy, gdy wejście składało się wyłącznie ze znaków podstawowych, a takich napisów IDNA nie koduje. Może natomiast zaczynać się łącznikiem, ale IDNA dodaje przed nim prefiks, dzięki czemu etykiety spełniają regułę z RFC 952, zgodnie z którą nazwa hosta nie zaczyna się ani nie kończy łącznikiem[1]. Specyfikacja ostrzega też przed wizualną wieloznacznością par znaków, takich jak O i 0 albo I, l i 1, w napisach przepisywanych ręcznie[1].

Przykłady

[edytuj | edytuj kod]

Dla nazwy kraków znaki podstawowe tworzą ciąg krakw, po nim następuje łącznik, a ciąg 3ta koduje wstawienie znaku ó (U+00F3) na pozycji 4, licząc od zera. Napis zawierający wyłącznie znaki ASCII otrzymuje jedynie końcowy łącznik: w przykładzie ze specyfikacji -> $1.00 <- daje -> $1.00 <--[1]. Czeskie zdanie Pročprostěnemluvíčesky koduje się jako Proprostnemluvesky-uyb24dma41a[1].

Nazwa ze znakami narodowymiPunycodeEtykieta w DNS (A-label)
krakówkrakw-3taxn--krakw-3ta
łódźd-uga0v4hxn--d-uga0v4h
żółww-uga1v8hxn--w-uga1v8h
gdańskgdask-y7axn--gdask-y7a
zażółćza-6ja4f8n1lxn--za-6ja4f8n1l
münchenmnchen-3yaxn--mnchen-3ya
рфp1aixn--p1ai

Zastosowanie w nazwach domen

[edytuj | edytuj kod]
 Zobacz też: Domain Name System.

W IDNA etykieta zapisana znakami Unicode w postaci znormalizowanej NFC nazywana jest U-label, a jej postać ASCII – A-label. Każdy A-label zaczyna się od prefiksu xn--, po którym następuje wynik algorytmu Punycode, a ponieważ etykieta DNS nie może przekraczać 63 oktetów, sam zakodowany ciąg ma najwyżej 59 znaków. Konwersja między obiema postaciami polega na zastosowaniu Punycode oraz dodaniu lub usunięciu prefiksu[2]. Prefiks może być zapisany dowolną wielkością liter[4]. Kodowaniu podlega każda etykieta nazwy osobno[4], a etykiet złożonych wyłącznie ze znaków ASCII IDNA nie koduje[1]. Punycode jest przeznaczony wyłącznie do konwersji etykiet nazw domen w IDNA, a specyfikacja wprost zastrzega, że nie służy do przetwarzania dowolnego tekstu[1].

Bezpieczeństwo

[edytuj | edytuj kod]

W Unicode istnieją znaki wyglądające identycznie jak litery łacińskie, na przykład cyrylickie а, е, о czy р, dlatego nazwa domeny ze znakami narodowymi może do złudzenia przypominać nazwę znanej witryny i służyć do phishingu. Atak tego rodzaju, nazwany atakiem homograficznym (ang. homograph attack), opisali w 2002 roku Evgeniy Gabrilovich i Alex Gontmakher, którzy w celu sprawdzenia jego wykonalności zarejestrowali wariant nazwy microsoft.com zapisany z użyciem liter rosyjskich[9]. W 2017 roku Xudong Zheng pokazał, że domena xn--80ak6aa92e.com, złożona wyłącznie z liter cyrylicy, była wyświetlana w przeglądarkach Chrome, Firefox i Opera jako apple.com, co omijało stosowane w nich zabezpieczenia przed homografami. Google wprowadziło poprawkę w Chrome 58[10]. W tym samym roku kampania złośliwych reklam Seamless, rozprowadzająca zestaw exploitów RIG, używała nazwy domeny złożonej ze znaków cyrylicy, zapisanej w Punycode[11].

W ruchu DNS nazwy ze znakami narodowymi występują wyłącznie w postaci ASCII z prefiksem xn--, dlatego zapytania o takie nazwy można wyodrębnić po tym prefiksie i porównać z podobnymi, legalnymi nazwami bez Punycode, co pozwala wykrywać próby podszywania się pod znane domeny[12]. Na przykład nazwa аpple.com, w której pierwszą literę zastąpiono cyrylicką а (U+0430), wygląda na ekranie jak apple.com, ale w DNS ma postać xn--pple-43d.com[10].

Przeglądarki internetowe same decydują, czy pokazać użytkownikowi nazwę w postaci Unicode, czy w postaci Punycode. Google Chrome podejmuje tę decyzję osobno dla każdej etykiety nazwy hosta i wyświetla postać Punycode między innymi wtedy, gdy etykieta zawiera znaki niedozwolone, miesza pisma w niedopuszczalny sposób, miesza systemy liczbowe, zawiera znaki niewidoczne albo jest myląco podobna do innej nazwy według kryteriów Unicode Technical Standard #39[13]. Standard ten określa mechanizmy wykrywania napisów wizualnie mylących (ang. confusable)[14].

Implementacje

[edytuj | edytuj kod]

Dokument RFC 3492 zawiera w załączniku przykładową implementację kodera i dekodera[1]. Biblioteka standardowa języka Python udostępnia kodek punycode, implementujący RFC 3492, oraz kodek idna, implementujący RFC 3490 i korzystający z poprzedniego, przy czym dokumentacja ostrzega, że algorytmy kodowania i dekodowania słabo się skalują, więc długość niezaufanych danych wejściowych należy ograniczać[15]. Rejestr NASK udostępnia na swojej stronie narzędzie do tłumaczenia nazw domen między postacią ze znakami narodowymi a postacią ASCII[7].

Zobacz też

[edytuj | edytuj kod]

Przypisy

[edytuj | edytuj kod]
  1. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 A. Costello, Punycode: A Bootstring encoding of Unicode for Internationalized Domain Names in Applications (IDNA), RFC 3492, IETF, marzec 2003, DOI: 10.17487/RFC3492, ISSN 2070-1721, OCLC 943595667 (ang.).
  2. 1 2 3 Internationalized Domain Names for Applications (IDNA): Definitions and Document Framework, RFC 5890, IETF, sierpień 2010, DOI: 10.17487/RFC5890, ISSN 2070-1721, OCLC 943595667 (ang.).
  3. ↑ RFC 3492: Punycode: A Bootstring encoding of Unicode for Internationalized Domain Names in Applications (IDNA). IETF Datatracker. [dostęp 2026-10-10]. (ang.).
  4. 1 2 3 P. Faltstrom, P. Hoffman, A. Costello, Internationalizing Domain Names in Applications (IDNA), RFC 3490, IETF, marzec 2003, DOI: 10.17487/RFC3490, ISSN 2070-1721, OCLC 943595667 (ang.).
  5. ↑ Internationalized Domain Names in Applications (IDNA): Protocol, RFC 5891, IETF, sierpień 2010, DOI: 10.17487/RFC5891, ISSN 2070-1721, OCLC 943595667 (ang.).
  6. ↑ Dzień Domeny Internetowej. NASK, 2024-03-15. [dostęp 2026-10-10].
  7. 1 2 IDN wprowadzenie. NASK. [dostęp 2026-10-10].
  8. ↑ Delegation Record for .РФ. IANA. [dostęp 2026-10-10]. (ang.).
  9. ↑ Evgeniy Gabrilovich, Alex Gontmakher, The Homograph Attack, „Communications of the ACM”, 45 (2), 2002, s. 128, DOI: 10.1145/503124.503156 (ang.).
  10. 1 2 Xudong Zheng: Phishing with Unicode Domains. 2017-04-14. [dostęp 2026-10-10]. (ang.).
  11. ↑ Jérôme Segura: Seamless campaign serves RIG EK via Punycode (updated). Malwarebytes Labs, 2017-12-04. [dostęp 2026-10-10]. (ang.).
  12. ↑ Adam Ziaja: Threat hunting using DNS firewalls and data enrichment. REDTEAM.PL, 2019-08. [dostęp 2026-10-10]. (ang.).
  13. ↑ Internationalized Domain Names (IDN) in Google Chrome. Chromium Docs. [dostęp 2026-10-10]. (ang.).
  14. ↑ Unicode Technical Standard #39: Unicode Security Mechanisms. Unicode Consortium, 2026-08-27. [dostęp 2026-10-10]. (ang.).
  15. ↑ codecs – Codec registry and base classes. Python 3 documentation. [dostęp 2026-10-10]. (ang.).

Linki zewnętrzne

[edytuj | edytuj kod]