“Яндекс” окончательно отключил бесплатную “почту для домена” – один из немногих полезных сервисов старого “Яндекса”. Я довольно долго использовал этот сервис для некоторых доменов. Формально, “Яндекс” не совсем всё отключил, однако теперь почтовые сообщения пользователям можно только принимать, но не отправлять (“режим чтения”). Реалии развития интернетов. Надо заметить, что это весьма старый бесплатный сервис, который в своё время был, без преувеличения, прорывным, и к которому, в старом “Яндексе”, ещё и прилагался ценный DNS-хостинг, оснащённый пусть и несколько минималистичным, но удобным редактором записей. Потом это всё переиначили, заменив с отдельными плясками на малопонятный новый интерфейс, как бы “ориентированный на бизнес”, но, тем не менее, как-то там продолжало работать. А теперь даже и основной “Яндекс”, как веб-сервис, называется иначе, так что не удивительно – почту отключили окончательно: предлагается переходить на платный тариф с какими-то не совсем понятными, но явно недешёвыми, уровнями оплаты “за пользователя” (да ещё и дополнительные данные передавать). Конечно, смысла в таком переходе нет: если вдруг кто столкнулся, то я бы рекомендовал просто перенести почту к тому или иному хостеру; часто услугу хостинга электронной почты предоставляет регистратор домена (иногда – даже за сумму продления регистрации).

(Надо заметить, что Google, в сходном “порыве монетизации”, старые аккаунты GoogleApps, которые идут ещё с какой-то там “закрытой бета-версии”, всё же пока оставил бесплатными – по крайней мере, в моём случае. Не ясно, конечно, останется ли оно так и дальше.)



Комментарии (5) »

Очень полезный тест SSLLabs для TLS пока что не умеет обнаруживать поддержку криптосистемы X25519Kyber768 сервером – см. фрагмент результатов для tls13.1d.pw на скриншоте ниже (Supported Named Groups). Это, собственно, понятно и логично: использование данной криптосистемы всё ещё находится в экспериментальном статусе, а поддержка на стороне сервера совсем не распространена.

SSL Labs TLS web test image

(Кстати, в результатах указано, что имена групп/криптосистем выведены в порядке предпочтений сервера, но для tls13.1d.pw это не так – сейчас “предпочтение” есть только для X25519Kyber768, остальные криптосистемы выбираются по наличию клиентских key_share, перечню поддерживаемых групп, но при этом ещё и случайным образом отправляется HelloRetryRequest – именно из соображений, что иногда нужно отправить HelloRetryRequest, а не по составу полученных клиентских параметров; обычные TLS-серверы так вряд ли делают.)



Комментировать »

В продолжение недавней записки про X25519Kyber768 на TLS-сервере – подробности встраивания данной гибридной криптосистемы в схему работы TLS 1.3.

1. Как нетрудно догадаться, X25519Kyber768 состоит из X25519 и Kyber768, поэтому криптосистема и гибридная. X25519 – это хорошо известный вариант протокола Диффи-Хеллмана (DH), здесь используется без изменений, обычным образом (см. кстати, заметку с задачей про 2^255 – 19). Kyber768 – схема KEM (инкапсуляции ключа), построенная на криптосистеме Kyber с “постквантовой стойкостью”. Эта криптосистема реализует зашифрование с открытым ключом (важный момент).

2. В TLS рассматриваемая криптосистема используется для получения симметричного сеансового секрета. Открытый ключ передаётся клиентом в составе ClientHello, в расширении key_share, а ответная часть сервером – в ServerHello, key_share. В логике сообщений тут ничего не меняется.

3. Изменяется часть внутри key_share, соответствующая X25519Kyber768 – клиент передаёт результат конкатенации байтов, составляющих клиентскую часть DH X25519 и открытый ключ клиента Kyber768. Эти данные имеют фиксированную длину, определяемую алгоритмами: 32 начальных байта для X25519 и 1184 для Kyber768, 1216 байтов всего. На сервере данные разделяются (просто, по длине) и используются для обеих криптосистем. А именно: для X25519 сервер вычисляет общий секрет DH и серверную открытую часть DH (B), так же, как это делалось бы в случае отдельной криптосистемы X25519; для Kyber768 – сервер генерирует общий секрет и оборачивает его в KEM (то есть, зашифровывает исходное секретное значение, используя открытый ключ Kyber, присланный клиентом – тем самые 1184 байта). Два секрета сервер объединяет в один массив – здесь, опять же, простая конкатенация: BaseSecret = x25519[] + Kyber_Shared_Secret[]. Обратите внимание на важное техническое отличие: для X25519 общий секрет, на сервере, это результат умножения открытой части DH клиента (A) на секретный скаляр сервера d: s = d*A; а для Kyber – сервер выбирает исходное значение, которое отправляет клиенту в зашифрованном виде (очень похоже на устаревшую схему с RSA-шифрованием в TLS, но устроенную наоборот). При этом внутри KEM Kyber для вычисления секрета по исходному значению используется отдельная функция (KDF), подмешивающая ещё и значение открытого ключа, это необходимый шаг, но, с точки зрения логики получения секрета, это не так важно. Секрет, генерируемый в рамках Kyber768 в TLS – это тоже 32 байта (256 бит). После завершения данного этапа – сервер получил общий симметричный секрет, представляющий собой объединение выдачи двух алгоритмов: 32 байта и 32 байта. Также сервер получил открытую часть DH и зашифрованный Kyber симметричный секрет (это только часть, предназначенная для Kyber, результат X25519 сюда не попадает).

4. Сервер формирует ответное расширение key_share, присоединяя к 32 байтам открытой части DH X25519 байты шифротекста с симметричным секретом, который зашифрован Kyber – длина шифротекста 1088 байтов, всего 1120 байтов. Ответное key_share сервер отправляет клиенту в открытой части сообщений, в ServerHello, после чего генерирует на основе общего секрета набор симметричных сессионных ключей и переходит к зашифрованному обмену данными.

5. Клиент, получив key_share X25519Kyber768, разделяет данные на открытую часть обмена DH X25519 (B) и шифротекст Kyber768. По значению B DH клиент вычисляет общий секрет DH X25519 (здесь – 32 байта), который совпадает с серверным. Используя секретный ключ, клиент расшифровывает шифротекст и вычисляет общий секрет Kyber. Оба полученных значения объединяются, результат должен совпасть с серверным. (Тут слово “должен” использовано потому, что в Kyber, к сожалению, есть вероятностный элемент: так как это схема, концептуально происходящая из кодов с коррекцией ошибок, то имеется очень небольшая вероятность, что “ошибка” всё же останется, а клиент и сервер получат разные значения секрета.) На основе объединённого секрета клиент вычисляет набор симметричных ключей и может проверить подлинность и расшифровать следующие сообщения сервера.

Таким образом, Kyber простым и понятным способом добавляет 256 бит “постквантовой стойкости” к исходному симметричному секрету TLS-сессии, какие-то другие параметры – не изменяются.



Комментировать »

Развивающаяся “битва за банхаммер” приводит к тому, что в “этих интернетах” появляются новые плоскости для осуществления сегментации, поскольку блокирование сейчас модно делать на достаточно высоком уровне – на уровне приложений. Недавний пример – стена (временная) регистрации в Twitter. Есть масса других примеров, где администраторы вроде бы “глобального” массового сервиса ограничивают к нему доступ для некоторых IP-адресов, но не на уровне транспорта, а средствами HTTP или внутри приложения на смартфоне. Вообще, может показаться, что, с точки зрения “маршрутов” и BGP – ничего не меняется: пакеты если ходят, то так и ходят, как ходили. Для инженера NOC, допустим, прежде всего важно, что отправленный по заданному адресу пакет до этого адреса добрался, а что там происходит на уровнях, которые строятся из пакетов, HTTP это или QUIC какой-нибудь, – дело десятое.

Однако, хоть популярное нынче блокирование и выполняется на один или два уровня выше, чем IP, это самое блокирование может спуститься ниже, но уже в виде технологического спагетти. Это происходит в тот момент, когда просят как-то повзаимодействовать с этим блокированием (неважно, в какую сторону) на сетевом уровне. Всем знакомый пример: VPN-доступ, позволяющий прийти на сервис с другим (географически) сетевым адресом. IP заворачивается внутрь UDP, а туннели неожиданным образом проходят между логическими уровнями. А IP в туннеле используется для создания TLS-соединения со скрытым сервисом. Туннелирование туннелей. Сегментация на уровне приложений спускается в маршрутизацию, где порождает неожиданные эффекты доставки пакетов, особенно, если пересекается с anycast-узлами. Попробуйте зарисовать логику на листочке бумаги – получится путаница из спагетти, напоминающая нехорошую практику в области кабельных соединений.

Дело в том, что хоть блокировать многие предпочитают на разных уровнях, но привычный идентификатор, по которому ставят задачи блокирования, это всё равно IP-адрес (не всегда, но очень часто). Конечно, никто не отменял локального блокирования на уровне физических портов, на уровне приёма BGP-анонсов, однако для массовых и популярных сервисов, которые работают поверх Интернета, – это всё ещё применяется редко. Напротив, сейчас видно, как довольно быстро выстраивается новый перемешивающий уровень (хороший пример – технология ECH, создающая каналы “TLS внутри TLS”). Это нивелирует возможности прицельного блокирования на уровне базового транспорта или, условно, “физических портов”, но позволяет построить банхаммер уровня приложений. Если, конечно, сохранится связность Сети, пусть и через спагетти-коммутацию транспортного уровня.



Комментировать »

Всё же я пока восстановил свой экспериментальный сервер TLS 1.3 – tls13.1d.pw (некоторое время назад я писал, что собираюсь его совсем отключить). А чтобы восстановление выглядело поинтереснее, я реализовал на сервере поддержку постквантовой схемы получения общего секрета (KEM) X25519Kyber768. TLS с Kyber768 там реализован вручную, но я, впрочем, использовал криптопримитивы из удобной библиотеки Cloudflare.

Криптосистему с постквантовой схемой KEM Kyber768 в конце августа Google внедрил в браузер Chrome (в порядке эксперимента), так что можете проверить – на сервере у X25519Kyber768 повышен приоритет, поэтому, при наличии соответствующего открытого ключа в сообщении клиента, выбираться она должна довольно часто.

Вообще, открытый блок клиентского KeyShare в X25519Kyber768 весит аж 1216 байтов (32 + 1184, потому что это ключ X25519, 32 байта, плюс ключ постквантовой части Kyber768, который большой). Тем не менее, я всё же пока что сделал вывод этого ключа без сокращений, что, возможно, выглядит тяжеловато, но видно будет только в браузере с поддержкой данной криптосистемы. (Дополнение, 12/09/2023: технические подробности об использовании криптосистемы.)

Поддержка есть только в самых свежих версиях Chrome (>=116), а включать её нужно через флаги: chrome://flags, набрать “TLS13” в поиске, флаг называется “TLS 1.3 hybridized Kyber support”.

Screenshot with TLS 1.3 Kyber768

(Не знаю, будет ли у меня возможность поддерживать сервер далее, так что в какой-то момент он может отключиться, теперь уже даже и без предупреждения, но посмотрим; ошибки подключения, естественно, могут быть и по другим причинам – это, всё ж, экспериментальный сервер.)



Комментировать »

Обычно, DNS-резолвер должен работать внутри VPN-сервиса – то есть, это может быть буквально обособленный резолвер, используемый именно в составе VPN (желательно, с DNSSEC). Но так делается далеко не всегда. Напомню, что DNS-резолвер (в данном случае, речь про рекурсивный резолвер) – это сервис, который проводит опрос серверов DNS, отыскивая, например, IP-адреса по именам узлов – адрес, по которому нужно браузеру обращаться к веб-серверу под именем test.ru. Резолвер выполняет то, что называется рекурсивным опросом: обращается к авторитативным DNS-серверам разных уровней. Эти серверы видят IP-адрес резолвера, но не клиента резолвера, который (вероятно) будет подключаться к сервису по обнаруженному в DNS адресу. При этом, для целей балансировки нагрузки на “целевой” сервис, DNS-серверу удобно было бы знать что-то о клиенте, для которого работает конкретный резолвер – потому что балансировка выполняется именно для клиента сервиса, а не для клиента DNS (сервис доменных имён (DNS) в этот момент уже на нужной стороне отработал). Это особенно актуально для больших открытых сервисов DNS-резолверов, например, Google Public DNS, так как эти сервисы обслуживают клиентов из самых разных точек сети. Чтобы как-то помочь оптимизации, довольно давно придумали расширение DNS под названием EDNS Client Subnet (ECS).

Данная технология (ECS) позволяет резолверу передать в сторону авторитативного сервера сведения об IP-подсети клиента, который обратился с запросом. Проще говоря – авторитативный сервер увидит IP-адресный блок, который соответствует клиенту, находящемуся за резолвером, что позволит определить провайдера. ECS как раз поддерживается Google Public DNS (и не только). Предполагается, что авторитативный сервер, определив провайдера клиента резолвера, сможет применить какие-то правила оптимизации. Если VPN используется для сокрытия IP-адреса пользовательского подключения, но DNS-трафик направляется не через VPN в какой-то DNS-сервис, то наличие ECS в этом сервисе (при прочих равных) означает, что внешние авторитативные DNS-серверы увидят скрываемую подсеть. Об этом нередко забывают.

Технический пример (не учитывающий NAT и другие тонкие настройки): предположим, клиентское устройство использует провайдерский доступ с адресом 10.11.12.13, ему соответствует подсеть 10.11.12.0/24; выход из VPN использует подключение с IP 10.22.22.22 (подсеть 10.22.22.0/24); DNS-трафик направляется напрямую (не через VPN) резолверу 10.53.53.53, резолвер поддерживает ECS. Тогда, при попытке определить значение A-записи (адрес), внешние серверы DNS узнают, что к ним подключается резолвер с адресом 10.53.53.53 для клиента из подсети 10.11.12.0/24. А вот на веб-сервере, к которому обращение произойдёт через VPN, адрес клиента будет виден как 10.22.22.22 – внешняя точка VPN. Естественно, если DNS-трафик маршрутизируется устройством через VPN, то внешний DNS-сервис с ECS сможет передать наружу только подсеть точки выхода VPN (10.22.22.0/24), поскольку именно адрес из этой подсети он видит в качестве источника запроса. Но лучше, конечно, если вообще используется собственный резолвер без ECS в составе VPN-сервиса, потому что возможны и другие каналы утечки метаинформации.



Комментировать »

В Chrome свежих версий добавлена экспериментальная поддержка “постквантового алгоритма” получения общего симметричного секрета для TLS 1.3 – X25519Kyber768. Это гибридный вариант, в котором в дополнение к “обычной” схеме X25519 используется криптосистема Kyber с заявленной высокой стойкостью ко взлому на гипотетическом универсальным квантовом компьютере (естественно, в дополнение к классической стойкости).

Технически это работает следующим образом: при установлении TLS-соединения Chrome добавляет в начальное сообщение ClientHello клиентскую часть данных X25519Kyber768 (и, естественно, индекс данной криптосистемы указывается в перечне поддерживаемых), если TLS-сервер может использовать данную криптосистему, то он выбирает соответствующий ключ из ClientHello, вычисляет симметричный секрет и использует его на дальнейших этапах. Это работает для TLS 1.3, при этом никак не изменяет каких-то других аспектов процесса установления соединения – не влияет на сертификаты и ключи к ним, не меняет шифров и т.д. На серверной стороне – обещают поддержку от Cloudflare и на некоторых узлах Google. Не вдаваясь в детали, можно смело считать, что X25519Kyber768 – это просто присоединение байтов секрета, полученного Kyber768, к байтам секрета, полученного X25519, на входе функции вычисления ключей для симметричного шифра, в полном соответствии с имеющейся схемой преобразования симметричных ключей TLS 1.3. То есть, схема, как минимум, не хуже криптосистемы X25519, которая уже давно используется, но не обладает постквантовой стойкостью (поскольку это вариант протокола Диффи-Хеллмана с логарифмированием в группе точек эллиптической кривой).

Насколько близки квантовые компьютеры, позволяющие быстро решать задачи отыскания соответствующих секретов асимметричных криптосистем, пока что не очень понятно. Однако постквантовые криптосистемы внедряются из предположения, что такой компьютер всё же может быть создан и позволит расшифровать ранее записанный трафик, из этого делается логичный вывод, что защиту нужно начинать внедрять заранее. Кстати, тут возникает не менее логичный вопрос: почему данный подход не применялся к разнотипным криптосистемам в том же TLS ранее, без требований о квантовых компьютерах? Например, можно же взять какую-нибудь экзотическую криптосистему и прикрепить её к распространённой реализации классического протокола Диффи-Хеллмана (DH), чтобы, если через двадцать лет будет найден неквантовый метод эффективного взлома классического DH, записанный трафик всё ещё оказался бы защищён (улучшения вычислительных атак на классический (“мультипликативный”) DH есть весьма существенные). Вопрос интересный, да. С одной стороны, задачи, на которых строятся распространённые сейчас асимметричные криптосистемы, нередко имеют математически эквивалентную структуру, с точки зрения сложности: то есть, одну задачу можно перевести в другую “с точностью до некоторой константы” (но тут есть куча оговорок – иногда “константа” получается слишком большой, например). С другой стороны, использование отдельного симметричного секрета, распределяемого по защищённому каналу, возможно и в TLS (называется PSK – Pre-Shared Key).



Комментировать »

Пишут, что в Microsoft не сумели корректно поменять SPF-запись для hotmail.com, а поэтому почта из данного домена попадает в категорию “Спам”. Детали я не проверял, но, похоже, IPv6-блоков в SPF там сейчас нет совсем. SPF – среди магических методов Нового Средневековья.

(Update: починили, через полсуток.)



Комментарии (1) »

Что касается STARTTLS. Для доставки электронной почты между почтовыми серверами в Интернете повсеместно используется протокол SMTP. SMTP – это “текстовый протокол”, то есть, его работа основана на командах, отправляемых в виде человекопонятного текста (ну, с точностью до числовых кодов состояний, которые, впрочем, тут тоже записываются ASCII-текстом) через любой подходящий транспорт. Многие достаточно древние протоколы в Интернете – текстовые. Потому что текстовые протоколы – это очень удобно и понятно. Там, где применимо. Сейчас, постепенно, этот подход возвращается (примеры: текстовые, REST-подобные API с JSON и др.), но, конечно, не везде.

Вернёмся к SMTP. Классические SMTP-сессии проходят в открытом виде, это означает, что содержание письма, доставленного электронной почтой, будет нетрудно просмотреть на любом промежуточном узле, которых легко могут быть десятки. (Обратите внимание, что дополнительные методы зашифрования содержания письма – PGP, S/MIME и т.д. – они относятся к другому уровню, не к SMTP.) Чтобы иметь возможность дополнительно защитить содержание писем в процессе доставки и используется STARTTLS: этот механизм позволяет SMTP-клиенту и SMTP-серверу перейти на защищённый канал “точка-точка” (см. пояснение ниже) после того, как они уже начали сессию в открытом варианте.

Для перехода к TLS, если сервер поддерживает STARTTLS, клиент просто отправляет команду STARTTLS (в виде текстовой строки, в открытом виде). Если сервер подтверждает, что готов к TLS, клиент в этом же “транспортном” сокете отправляет начальный пакет TLS-соединения (ClientHello, начинает “хендшейк”), после чего стороны могут согласовать защищённый сокет. Далее, если процесс установления TLS-соединения успешно завершился, SMTP-сессия начинается, фактически, заново, в текстовом формате, но уже внутри защищённого TLS транспорта. То есть, на логику SMTP использование STARTTLS влияет минимальным образом.

Оговорка об уровне “точка-точка”: естественно, под “точка-точка” тут подразумевается соединение между конкретным клиентом SMTP и конкретным сервером, но не далее. Доставка почты так устроена, что почтовые серверы (“релеи”) часто используются цепочкой, поэтому конкретное письмо может проходить через несколько почтовых серверов (не следует путать с промежуточными узлами уровня IP и ниже – здесь речь про уровень SMTP, там тоже есть пересылающие серверы). Так что использование TLS-соединения на каком-то этапе (“звене”) доставки сообщений не означает, что данное письмо поедет через TLS и дальше.

Поскольку сам SMTP полностью открыт, его не так уж трудно проксировать с изменениями, даже подменяя IP-адреса узлов. Серверное сообщение о поддержке STARTTLS можно просто вырезать из соответствующего ответа – если клиент допускает доставку без TLS, то он уже не будет пытаться установить TLS-соединение, а перейдёт к доставке в открытом виде. Это давно известная особенность, указанная в RFC.

В практике SMTP, при доставке писем между почтовыми серверами, принято не особенно строго подходить к обработке параметров TLS. Причина в том, что иначе почта перестанет ходить совсем. Поэтому TLS тут является примером того, что называется “приспособительным” (или “ситуативным”) подходом в использовании криптографии для защиты от прослушивания: “если удалось, то будем зашифровывать, а если нет – тогда ладно”. (В английском варианте – “opportunistic encryption”; однако переводить тут opportunistic на русский как “оппортунистическое” – не верно: соответствующие коннотации слишком сильно отличаются; это даже хуже, чем Чарльз, превращающийся в Карла.) Для защищённой работы SMTP есть и вариант использовать TLS-соединение сразу, до начала SMTP-сессии (SMTPS и др.), однако этот подход уже не имеет отношения к STARTTLS.



Комментировать »

Сервис audit.statdom.ru проверяет разнообразные настройки по доменному имени и выводит отчёт. В том числе, проверяются настройки электронной почты (по MX-записям). Недавно добавили проверку TLS для STARTTLS. STARTTLS в SMTP означает возможность использовать TLS при доставке сообщений на сервер. О поддержке STARTTLS сервер может заявить в перечне опций, который передаёт клиенту в ответ на начальную команду EHLO. Собственно, раньше сервис audit.statdom.ru проверял только наличие флага STARTTLS, но не пытался установить TLS-соединение. В очередном обновлении – добавили фактическую проверку наличия TLS и сопоставление имён из сертификата, если сертификат сервера удалось получить. (Вообще, в практике SMTP, проверка соответствия имени в TLS-сертификате имени хоста не относится к необходимым процедурам: уже хорошо, что сервер хоть какой-то всё ещё валидный сертификат прислал – это позволяет перейти к защищённому соединению, а это часто лучше, чем открытый канал. Но, конечно, ещё лучше, если сертификат соответствует по имени.)

Ссылка: audit.statdom.ru



Комментировать »

IDN – это “многоязычные доменные имена” (Internationalized Domain Names), подразумевающие преобразование кодировок на стороне клиента: Unicode кодируется при помощи Punycode, поскольку в DNS, пока что, Unicode не используется (полезная технология, вообще говоря, полезна лишь там, где действительно нужна и может быть внедрена, но это история для другой записки). Весьма неудобный дополнительный слой, который образуется из-за обработки IDN, постоянно приводит к проблемам. Самая “заковыристая”, а поэтому постоянно вылезающая тут и там, проблема – нормализация unicode-записи. Собственно, не так давно мне пришлось исправлять эту проблему в одном из сервисов, работающих с доменными именами. Но если сейчас посмотреть и потестировать те или иные профильные веб-интерфейсы, преобразующие IDN, то, думаю, данная экзотическая проблема проявится у многих (это особенно близко регистраторам доменных имён). Кстати, если этот текст читают разработчики подобных инструментов, то потестируйте имеющиеся реализации. Строки для тестирования я привожу ниже, вместе с описанием логики проблемы (впрочем, она уже упоминалась в прошлогодней записке про шумерские цифры, которую вряд ли много кто прочитал).

Итак, Unicode устроен весьма продвинутым способом. Настолько продвинутым, что там есть поддержка дорисовывания различных дополнительных значков (диакритических, например) к символам. То есть, имеются “закорючки” со “знакоместом”, на которое знакоместо ставится связанный символ. Это весьма полезно во многих системах письма. Однако некоторые буквы некоторых алфавитов имеют и “основное” представление в качестве отдельного кода, уже включающее в себя “закорючку”. Пример – русская буква “й”. Графически, это буква “и”, но с “чёрточкой” (называется “бреве” или “кратка”). Unicode позволяет закодировать “чёрточку” разными способами, как минимум, двумя – вместе с буквой и отдельно.

Посмотрите на две строки: “биткойн.рф” (1) и “биткойн.рф” (2) – они должны выглядеть одинаково. Эта одинаковость обманчива, потому что в первом случае “й” записано как U+0438 + U+0306 – буква “и” + “знак бреве”, два значения; а во втором случае – это просто буква “й” (U+0439, одно значение), где, так сказать, всё включено.

Графически, строки эквивалентны, что производит неизгладимое впечатление на разработчиков, столкнувшихся с этим явлением впервые (ну и на тех, кто столкнулся в третий или в пятый раз – тоже впечатление производит). Расщепление сущностей тут случается на два уровня выше, чем графическая отрисовка. Промежуточный итог: две разных строки кодов выглядят абсолютно одинаково, чтобы протестировать различие – строки нужно скопировать через совместимый буфер обмена, так как при помощи привычной раскладки кириллической клавиатуры набрать их не получится (в некоторых других раскладках разная “диакритика” и прочие “дополнения” доступны отдельно, но далеко не факт, что результат сохранится именно как пара кодов).

Возвращаемся к IDN. Эта технология требует преобразования кодов Unicode к DNS-записи, алфавит которой допускает (без учёта регистра) для подстрок имён хостов символы [a-z] (от “a” до “z”), [0-9] и “минус” “-” (точки тут не считаем). Для кодирования этими ASCII-символами байтовых значений Unicode используется алгоритм, называемый Punycode. Принцип тут аналогичен тому, как работает, например, Base32 (или “кодирование в рунах”), детали отличаются, но нам это здесь не так важно. Важно, что Punycode ничего не знает про особенности Unicode и просто отображает в подмножество ASCII значения unicode-байтов (и обратно), то есть, разные кодовые записи одной буквы отобразятся в разные punycode-последовательности. Что не так трудно продемонстрировать на нашем примере: “биткойн” == “qsa11dvaajue4a”, а “биткойн” == “90aoddqe0a” (выглядит занятно, да).

Однако с точки зрения DNS “qsa11dvaajue4a” и “90aoddqe0a” – разные значения, поэтому имена, их содержащие, тоже будут разными. Разный способ записи одного и того же графического представления для целей DNS не подходит – в реестрах имён, на серверах имён, первоочередное значение имеет ASCII-представление. Поэтому и используется процесс, называемый нормализацией, который описывает соглашение о том, как разные “чёрточки” так приклеить к буквам, чтобы привести всё к одной последовательности кодов, а уже её использовать, например, в DNS. Естественно, unicode-нормализация важна не только в DNS, но подробное описание принципов остаётся за рамками этой записки – его можно найти в соответствующем документе. Отмечу, что современные библиотеки для работы с IDN, обычно, позволяют прозрачно использовать нормализацию, нужно только не забыть её правильно включить при вызове функций преобразования. И, вообще говоря, алгоритмов нормализации – несколько, что делает ситуацию интереснее. А полагать, что столкнуться с подобным на практике невозможно, будет ошибкой – копирование символов иностранных письменностей в составе имён, которые не удалось ввести с клавиатуры, вполне себе встречается.



Комментировать »