Czym jest Punycode?
Punycode to składnia kodowania zdefiniowana w RFC 3492, która przekształca ciągi Unicode w ograniczony zestaw znaków ASCII obsługiwany przez DNS. Stanowi techniczną podstawę umiędzynarodowionych nazw domen (IDN), dzięki czemu nazwy w dowolnym języku mogą działać z istniejącą infrastrukturą DNS.
Problem rozwiązywany przez Punycode
System nazw domen zaprojektowano w latach 80. z myślą wyłącznie o znakach ASCII. Etykiety DNS mogą zawierać tylko:
- Małe litery (a-z)
- Cyfry (0-9)
- Łączniki (-)
To ograniczenie wykluczało miliardy użytkowników Internetu, którzy nie posługują się głównie alfabetem łacińskim. Punycode usuwa tę barierę, kodując dowolny ciąg Unicode do poprawnego ASCII.
Jak działa kodowanie Punycode
Punycode korzysta z algorytmu, który zachowuje znaki ASCII, a znaki spoza ASCII koduje do zwartej reprezentacji ASCII.
Proces kodowania
1. Rozdziel znaki: Podziel znaki ASCII i spoza ASCII
2. Skopiuj ASCII: Zachowaj wszystkie znaki ASCII na pierwotnych pozycjach
3. Zakoduj pozostałe znaki: Użyj uogólnionego kodowania liczb całkowitych o zmiennej długości
4. Dodaj prefiks: Dodaj „xn--”, aby oznaczyć kodowanie Punycode
Przykłady
| Oryginał (Unicode) | Zakodowany (Punycode) |
|---|---|
| münchen | xn--mnchen-3ya |
| 北京 | xn--fiqs8s |
| münchen.de | xn--mnchen-3ya.de |
| 中文.com | xn--fiq228c.com |
| café.com | xn--caf-dma.com |
Prefiks „xn--”
Prefiks „xn--” nosi nazwę prefiksu ACE (ASCII Compatible Encoding). Informuje resolvery DNS i aplikacje, że etykieta zawiera treść zakodowaną w Punycode. Prefiks ten:
- Zawsze jest zapisany małymi literami
- Nigdy nie występuje w zwykłych domenach ASCII
- Uruchamia dekodowanie Unicode w zgodnym oprogramowaniu
Punycode w praktyce
Obsługa przez przeglądarkę
Nowoczesne przeglądarki automatycznie obsługują Punycode:
User types: 中文.com
Browser sends: xn--fiq228c.com (to DNS)
Browser displays: 中文.com (in address bar)
Implementacja dla programistów
JavaScript (Node.js):const punycode = require('punycode/');
// Encode to Punycode
const encoded = punycode.toASCII('münchen.de');
// Result: xn--mnchen-3ya.de
// Decode from Punycode
const decoded = punycode.toUnicode('xn--mnchen-3ya.de');
// Result: münchen.de
Python:
domain = 'münchen.de'
encoded = domain.encode('idna').decode('ascii')
# Result: xn--mnchen-3ya.de
Obsługa adresów URL
Pracując z URL zawierającymi IDN:
// URL API handles Punycode automatically
const url = new URL('https://中文.com/path');
console.log(url.hostname); // xn--fiq228c.com
console.log(url.href); // https://xn--fiq228c.com/path
Konsekwencje bezpieczeństwa
Możliwość reprezentowania dowolnych znaków Unicode przez Punycode stwarza zagrożenia bezpieczeństwa:
Podszywanie wizualne
Atakujący mogą rejestrować domeny wyglądające identycznie jak legalne witryny:
аррlе.com (Cyrillic 'а' and 'р')
apple.com (Latin letters)
W niektórych czcionkach oba adresy wyglądają tak samo, ale są różnymi domenami.
Ochrona przeglądarek
Aby ograniczać podszywanie, przeglądarki stosują następujące mechanizmy:
1. Wykrywanie mieszania pism: Wyświetlanie Punycode dla podejrzanych domen łączących różne pisma
2. Wykrywanie znaków mylących: Oznaczanie domen ze znakami przypominającymi ASCII
3. Biała lista: Zezwalanie na wyświetlanie Unicode tylko dla znanych TLD
Praca z Punycode w API
Podczas tworzenia narzędzi domenowych:
Zawsze przechowuj Punycode: Używaj wewnętrznie formy ASCII dla spójności i indeksowania bazy danych. Akceptuj obie formy: Pozwól użytkownikom podawać Unicode lub Punycode i konwertuj je w razie potrzeby. Wyświetlaj Unicode: W interfejsach pokazuj postać czytelną dla człowieka.function normalizeDomain(input) {
const punycode = require('punycode/');
// Convert to lowercase Punycode for internal use
return punycode.toASCII(input.toLowerCase());
}
Punycode jest przezroczysty dla większości użytkowników, ale jego znajomość jest niezbędna programistom tworzącym umiędzynarodowione aplikacje internetowe.