Год 2021, новый

За прошедший год на dxdt.ru записок появлялось мало (интересно, что я далеко не первый год сетую на это, но – куда деваться?), с другой стороны – я дописал и выпустил обновление описания TLS, исправил кое-какие недочёты и ошибки в тестовом сервере TLS 1.3, ну и, всё же, какие-то записки выходили, например, про Starlink, о протоколе ECDH “в числах”, и другие.

Да, чуть не забыл: с наступающим Новым годом! Спасибо, что читаете.



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

Небольшой переезд dxdt.ru

Перенёс dxdt.ru на другой сервер (другой экземпляр сервера). Это потребовалось для того, чтобы перевести всё под управление ОС Debian 10. Вроде, всё работает в новой конфигурации, но был небольшой перерыв при замене адресов.



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

В блоге Cloudflare подробная статья, рассказывающая популярно про технологию сокрытия имени сервера в TLS: Encrypted Client Hello (ECH).

ECH является полностью переработанным вариантом ESNI, однако, как пишут в статье, от ESNI на серверах Cloudflare пока отказываться не собирается, но лишь по той причине, что спецификация ECH ещё не достигла нужной “степени готовности”. Cloudflare сейчас является крупнейшим провайдером веб-доступа, поддерживающим ESNI и, собственно, единственным сервисом с массовой поддержкой этой технологии. При этом спецификация ESNI – так и не достигла статуса RFC, превратившись, на стадии очередного черновика, в ECH.

(Как работает ESNI – можно посмотреть на моём тестовом сервере https://tls13.1d.pw/, а вот поддержку ECH я ещё не собрался дописать.)



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

На сайте ТЦИ опубликована моя статья с результатами измерения распространённости поддержки TLS 1.3 на HTTPS-узлах Рунета. Под Рунетом подразумеваются имена второго уровня в зонах .RU, .SU, .РФ. Измерялось наличие поддержки TLS 1.3 для TCP-соединений на номере порта 443 (это номер HTTPS). TLS 1.3 уже довольно широко поддерживается, несмотря на относительную новизну протокола. Описание методики и результаты – в статье.



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

Немного занимательных математических основ криптографии.

Российская криптосистема электронной подписи (ГОСТ 34.10-2012) работает в группе точек эллиптической кривой над конечным полем, как и криптосистема ECDSA, широко используемая в TLS и в других протоколах защиты информации. Можно ли устроить так, чтобы открытый и секретный ключи для ГОСТ-подписи и ECDSA – совпадали? Дело в том, что если ключи одинаковые, то это добавляет удобства: например, можно использовать некие унифицированные сертификаты. Естественно, это чисто теоретической вопрос, но он довольно занятный. Если вынести за скобки криптографические параметры и способ интерпретации битовых строк, то главное отличие между ГОСТ-подписью и ECDSA состоит в уравнениях, используемых этими криптосистемами. Упростим ситуацию и рассмотрим лишь уравнения вычисления значения подписи:

ECDSA: s = k^(-1)(h + rd)

ГОСТ: s = (rd + kh)

Здесь использованы общие буквенные обозначения: h – это подписываемое значение (можно считать, что это значение хеш-функции от сообщения – натуральное число); k – случайный параметр (натуральное число); r – значение х-координаты вычисляемой на основе k “случайной” точки кривой (это элемент конечного поля, но и его в нашем случае можно понимать как натуральное число), d – секретный ключ (натуральное число). Здесь везде опущены упоминания того, что значения вычисляются по модулю порядка группы точек, связанной с точкой-генератором G, но, опять же, это нисколько не помешает изложению.

Итак, сразу видно, что секретные ключи d для обоих вариантов математически эквивалентны, так как секретный ключ – это натуральное число. Это так и есть на практике, с оговоркой, что значение секретного ключа должно лежать в некотором интервале, но это технические детали. На практике, вряд ли имеет смысл использовать небольшое значение d, которое может оказаться угадываемым. То есть и для ГОСТ-подписи, и для ECDSA в качестве секретного ключа можно использовать одно и то же значение. Если оно находится в подходящем интервале, то в работе алгоритмов, реализующих криптосистемы, равным счётом ничего не поменяется.

Как быть с соответствующими открытыми ключами? С открытыми – уже не так просто. Открытый ключ в обоих криптосистемах – это точка кривой, полученная в результате “умножения” точки-генератора G на число d (значение секретного ключа): открытый ключ Q == dG. “Умножение” здесь взято в кавычки по той причине, что для точек кривой никакого умножения не определяется, но есть “повторное сложение” точек: так, 3*A == A + A + A, где A – точка кривой. Повторное сложение и позволяет ввести умножение на скаляры (на целые числа). Итак, открытый ключ – точка кривой Q – это пара координат (x, y). Значения координат, x и y, – элементы поля, над которым рассматривается кривая. Именно здесь и кроется отличие: штатно, обсуждаемые криптосистемы используют разные кривые и разные поля, поэтому полученные значения открытого ключа будут различными, если, конечно, мы хотим сохранить корректность прочих операций (а корректность сохранить необходимо).

Таким образом, из-за использования разных криптографических параметров (уравнения кривой, базового поля, точки-генератора), для одного и того же значения секретного ключа значения открытых ключей, вообще говоря, в ECDSA и ГОСТ-подписи не совпадут. Однако, если использовать одно и то же поле, одну и ту же кривую и генератор, то и значения открытых ключей будут равны, поскольку и в одной, и в другой криптосистеме – открытый ключ Q == dG. Обе криптосистемы могут работать на общей кривой – математические операции не отличаются. Понятно, что так как уравнения подписи разные, то подписи для одного и того же значения не будут совпадать, даже если ключи удалось привести к “единому формату”. (Естественно, подписи для сообщений могут отличаться и из-за использования разных хеш-функций.) Однако все операции (вычисление подписи, проверка) останутся корректными и для ECDSA, и для ГОСТ-подписи. Поэтому использовать, буквально, одну и ту же пару ключей (секретный – для вычисления подписи, а открытый – для проверки) уже окажется возможным.

Конечно, так как практические криптосистемы включают в свой состав не только математические операции, но и конкретные значения параметров, подобное объединение ключей вряд ли реализуемо за пределами занимательного упражнения.



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

Важный момент про DNS-over-TLS (DoT) и DNS-over-HTTPS (DoH): в случае, когда валидацию DNSSEC проводит внешний рекурсивный резолвер, использование DoT/DoH на “последней миле” позволяет эффективно продолжить цепочку доверия DNSSEC до клиента; правда, через дополнительный шаг – аутентификацию сервера в рамках TLS. То есть, если некоторый клиентский stub-резолвер использует гугловый сервис 8.8.8.8 и доверяет его валидации DNSSEC, но сам валидацию не проводит, то, в классическом случае, никто не мешает на транзитном узле вмешиваться в трафик и присылать фиктивные ответы от имени 8.8.8.8, в которых будет что угодно. Использование же DoT/DoH позволяет клиенту аутентифицировать узел (DNS-сервер) и проверять подлинность ответов, что распространяет доверие к валидации DNSSEC на случай, когда клиент не верит транзитным узлам (а им верить давно нельзя).

(Первоначально опубликовано на Facebook.com, 22/11/2019.)



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

Для самоуправляемых боевых роботов, которые, например, передвигаются по пересечённой местности, весьма важным фактором оказывается непредсказуемость траектории. То есть, перед такими роботами стоят те же задачи, которые решают ракеты, предназначенные для преодоления тех или иных средств обороны.

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

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



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

У меня есть аккаунт в Facebook, где я размещаю разные заметки. Большинство из тех заметок совсем не подходят для публикации здесь, на сайте dxdt.ru, однако некоторые – хочется как-то сохранить, тем более, что перспективы сервиса Facebook несколько туманны. Поэтому я решил попробовать подходящие заметки иногда копировать сюда, даже если они достаточно старые (Facebook отдельно показывает прошлые заметки, которые опубликованы на актуальную дату, так что можно выбирать).

Например, вот заметка от 28.09.2018, про алгоритм Шора.

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

Между тем, квантовый алгоритм Шора и “скрытые классические методы” – это вообще вещи не связанные: то есть, квантовый алгоритм ничего не говорит нового об арифметике (ни в ту, ни в другую сторону), и всё это просто издержки “фольклорного” понимания квантовых вычислений, трактующих их как “параллельную проверку всех вариантов”. Скажем, алгоритм Шора, – в случае применения к RSA, если хотите, – говорит лишь о том, что мы можем построить квантовую машину, которая, после измерения, схлопнется в состояние, позволяющее уже классическим методом быстро провести факторизацию. Не более того. Другими словами: давно и хорошо известная структура, существующая в кольце, но, из-за своей огромной мощности, необозримая для классических компьютеров, может быть помещена в некоторую квантовую машину. Структуру, внутри квантовой машины, увидеть всё равно нельзя (это очень важный момент – нет там никакого «одновременного перебора»), но машина так устроена, что в результате интерференции состояний, соответствующих разным “симметриям”, она с достаточно большой вероятностью выдаст одно из значений, характеризующих исследуемую структуру (а целиком мы её всё равно не увидим, и ничего нового таким методом не узнаем). Изящный фокус алгоритма состоит в том, что, для успешной факторизации, нам именно этого значения (периода функции) и достаточно.



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

“В магазин привезли два ящика с апельсинами. В каждом ящике – пять апельсинов. Сколько всего апельсинов привезли в магазин?”. Эта задача для начальной школы, а точнее – обсуждение её требуемого способа решения, как выясняется, несёт с собой много занимательных трактовок. Задача существует в различных вариантах (“диваны/подушки”, “полки/книги” и пр.), а её решение с постоянством обсуждается “в интернетах” уже несколько лет. Обсуждение вращается вокруг следующего момента: вариант решения “5*2 == 10” – учитель признаёт неверным; требуется решать так: “2*5 == 10 (апельсинов)”, поскольку в первом варианте “получаются ящики, а не апельсины“. Возможна и иная трактовка, в которой левое умножение заменяется правым, но для нас это не важно, поскольку причина бурных обсуждений состоит в том, что результат вообще зависит от порядка множителей. Почему-то считается, что это невозможно, поскольку умножение в натуральных числах коммутативно. Вообще, если отвлечься от неясных вопросов преподавания в начальной школе, то задача, взятая вместе с методикой решения, оказывается связанной с интересными аспектами математики и их проекцией в привычный опыт.

Попробуем разобраться с задачей подробнее. Очевидно, что за рамками обсуждаемой формулировки условия оказывается структура, в которой задачу требуется решать. Эта структура предполагает, что тип (или класс, опять же, здесь не так важно) объектов результата определяется типом правого (или левого) операнда. Будем полагать, что нужная структура действительно была введена при определении операции умножения (см. ниже), иначе теряется смысл. Теперь – к самому решению.

Прежде всего, решение, учитывающее порядок, никак не отменяет коммутативности умножения. И в случае 5*2, и в случае 2*5 – ответ одинаков, это натуральное число 10. В результате получается десять объектов, а вопрос касается лишь типа этих объектов. Это всё может показаться странным, поскольку противоречит фольклорной интерпретации арифметики. Тем не менее, в натуральных числах – есть только натуральные числа, там нет апельсинов и ящиков. Процесс счёта, позволяющий сопоставить некоторой совокупности однотипных объектов натуральное число, обозначающее их количество, увеличивает уровень абстракции. Собственно, только потому, что натуральные числа столь универсальны, оказывается возможным вести счёт при помощи попарного сопоставления объектов разных типов: это обычный “счёт на пальцах”, когда каждому апельсину сопоставляется загибаемый палец. То есть, процесс решения задачи содержит некоторые неявные преобразования типов: апельсинам и ящикам, с помощью некоторого правила (функции, если хотите), сопоставляется натуральное число, обозначающее их количество. Это преобразование забывает какой тип имели объекты.

В процессе решения – умножаются натуральные числа. Мы хотим получить более или менее абстрактный метод, обладающий универсальностью. Поэтому представьте, что умножение чисел выполняет некая машина, на два входа которой поступают операнды, а на единственном выходе, покрутив ручку, получаем результат. Результат умножения – тоже натуральное число (а не “апельсины”, не “ящики”). Машина ничего не знает про апельсины и ящики. Чтобы закончить решение задачи, получившемуся натуральному числу нужно сопоставить тип объекта, выполнив обратное преобразование. На входе типов было два, как выбрать один из них для результата? Для этого требуется некоторое дополнительное соглашение, дополнительная структура, которая должна быть надстроена над нашей вычислительной машиной. Один из подходящих вариантов: просто взять тип правого (или левого) операнда. Обойтись без дополнительной структуры нельзя. Во-первых, наш процесс, пересчитывающий объекты, забывает их тип (но выдаёт натуральное число – количество); во-вторых, способа умножить “апельсины” на “ящики” – у нас нет, а только умножение в натуральных числах; в-третьих, на входе два типа, а результат нужно привести к одному из них.

Распространённое конструктивное возражение такое: у нас же даны не апельсины, а “апельсины на ящик”. Да, это весьма разумный довод, опирающийся на введение некоторого понятия “размерности”. Действительно, умножаем число с размерностью “апельсины/ящик” на число с размерностью “ящик”, “ящики” сокращаются – получаем искомые апельсины, вне зависимости от порядка множителей (операндов). Это очень привычно (м/сек., кг/м2 и др.), поэтому мало кто замечает, что введение такой “размерности” подразумевает построение некоторой дополнительной теории. Почему при умножении “апельсины/ящик”*”ящик” – сокращаются именно “ящики”? Что такое “сокращаются”? А можно ли записать наоборот “ящик/апельсины”? Заметьте, что привычное деление, которое приходит тут на ум, мало того, что легко выводит за пределы натуральных чисел, так ещё и является некоммутативной операцией! (В алгебре деление вообще не рассматривают в “повседневном” смысле, а только умножение на обратный элемент. В частности, поэтому в натуральных числах универсального деления, в строгом смысле, просто нет. Что, конечно, никак не запрещает утверждать, что оно там всё же имеется, поскольку 12/3 == 4.) Другими словами, для того, чтобы реализовать коммутирующее преобразование типов при помощи только что описанного понятия “размерности”, потребуется принять некоторые вспомогательные соглашения, например, что a/b*b == a, и ситуация не отличается от соглашения про выбор типа правого (или левого) операнда.

Почему же в исходной задаче выбирается именно правый (или левый) операнд в качестве носителя типа результата? Сложно сказать точно, тут возможны варианты. Одно из объяснений следующее: пусть умножение вводится как “повторное сложение”, тогда один из операндов задаёт количество шагов такого сложения. В случае апельсинов и ящиков, ящики разбивают некоторое подразумеваемое множество апельсинов на подмножества, используя отношение “быть в ящике”, а правила записи и преобразования предписывают “разбивающий тип” указывать слева, а в качестве типа результата – использовать тип правого операнда. Ну, или наоборот – тут можно и запутаться. Тем не менее, это позволяет достаточно строго, достаточно простым образом (используя минимум дополнительных понятий) построить универсальный механизм решения, который будет работать и для апельсинов в ящиках, и для подушек на диванах, и для книг на полках. Конечно, эти правила должны быть согласованы, прежде чем можно ставить задачу. Но если они согласованы, то попытка умножения 5 (апельсинов) на 2 (ящика) действительно даст в ответе 10 ящиков, сколь бы странным и неудобным это ни показалось. (Неудобным – потому что засовывать ящики в апельсины довольно сложно.)

Представьте гипотетический язык программирования, в котором предложения { 2 + “3” } и { “2” + 3 }, после преобразования компилятором, дают разные результаты: первый вариант – строку “23”, а второй – число 5. Исходя из рассмотренной выше задачи, нетрудно догадаться, почему такое происходит. Дело в том, что компилятор не только выполняет неявное преобразование типов, но ещё и “подгоняет” операции. В качестве главного типа компилятор выбирает тип правого операнда, приводя левый операнд к нему. Поэтому, в предложении { 2 + “3” } числовой тип двойки преобразуется в строку из символа “2”, а операция сложения превращается в конкатенацию (некоммутативная операция, кстати). Да. Не очень-то удобно, не то что апельсины по ящикам.



Комментарии (3) »
Навигация по запискам: Раньше »