Часто попадается популярная иллюстрация к протоколу Диффи-Хеллмана, использующая аналогию “смешивания красок”: то есть, стороны, пытающиеся получить общий секрет, смешивают исходную краску, которая известна всем, каждая со своей секретной краской, а потом обмениваются результатами по открытому каналу и смешивают со своим секретом уже результат второй стороны (см. ниже), получая, таким образом, одинаковый “цвет”. Например, в английской “Википедии” сейчас дана именно такая иллюстрация.

Screenshot

(Source: Wikimedia)

Оказывается, такая картинка – не самый плохой способ объяснить что-то содержательное про протокол DH “на пальцах”, пусть некоторые требования и остаются за кадром. Например, эта схема не позволяет показать, почему атакующая сторона не может “перебрать все краски” (естественно, в практическом случае с числами).

Посмотрим на основные моменты, которые подразумевает имеющаяся картинка. Во-первых, результат смешивания красок должно быть трудно обратить – важнейшее свойство для DH, который строится на “однонаправленных” функциях (об этом написано на исходной картинке). То есть, сторона, наблюдающая обмен, не может простым способом разделить краски. Вспомните, что исходная краска, – которая соответствует генератору в “настоящем” DH, – известна всем, в том числе, стороне, пытающейся взломать обмен. По условию – выделить эту краску из смешанных “цветов” оказывается вычислительно невозможно. Во-вторых, операция смешивания красок должна быть “коммутативной” (условно!) – то есть, результат не отличается от порядка подмешивания ингредиентов сторонами. Это не менее важный математический момент “настоящего” протокола, который позволяет обобщить его и перенести с классических вычетов на совсем другие структуры.

Вообще, “коммутативность” тут именно в кавычках, поскольку математическая структура несколько сложнее. Запишем операцию в виде формулы, где “*” соответствует смешиванию красок и действует слева: α * G – означает, что секретная краска α смешана с краской G (чтобы как-то обосновать “левое и правое” действие – считаем, что колер α добавлен в банку к краске G). Тогда: β * (α * G) == α * (β * G) – это то, что происходит в протоколе с красками. То есть, сторона A получает результат смешивания (β * G) и замешивает свою краску α: α * (β * G). Сторона B – наоборот. Казалось бы, должно выполняться (α * β) == (β * α), тогда работает схема. Именно так устроено в классическом DH, но с показателями степенй: (G^β)^α == (G^α)^β. Однако для протокола на красках, вообще говоря, (α * β) == (β * α) хоть и очевидно работает в “локальном” случае, но не применимо в иллюстрируемой схеме – ведь ни у стороны A, ни у стороны B нет готового состава (α * β) – они не могут его приготовить по условию “неразделимости” красок. Вариант (α * β) * G провернуть не получится, по условиям задачи: краски – это не натуральные числа. Поэтому-то “коммутативность” тут – это не настоящая коммутативность (без кавычек). Требуется именно “одинаковость” действия и краски α, и краски β на уже смешанные и подходящие краски. Это можно переписать в других обозначениях: A := α * G (подмешали α в G); B := β * G (подмешали β в G); α * B == β * A – потребовали выполнения базового свойства, необходимого для работы протокола DH на красках: β переводит A в тот же цвет, в который α переводит B.

И это вовсе не беспричинно въедливое разбирательство. Любой химик вам подтвердит, что в химии – далеко не всегда порядок подмешивания ингредиентов не влияет на результат. Формулы веществ это хорошо, но иногда нарушение порядка смешивания может так повлиять, что лабораторию придётся ремонтировать или даже строить новую.

Дело не только в химии: именно обобщение структурной особенности, которая переводит две разных “краски” строго в одну при действии разными элементами (другими “красками”) как раз и позволяет максимально обобщить и сам протокол DH, переписав его в терминах того, что в математике называется “действием группы”. Это, впрочем, отдельная история.

С “красочной” иллюстрацией к DH связан и ещё один занимательный момент. Хорошо, разобрать смешанный “цвет” на составляющие краски трудно – это по условию задачи. Но что мешает атакующему перебрать все доступные краски, подмешивая их к исходной? Результаты смешивания сравниваются с переданными в открытом виде “цветами” (они соответствуют открытым ключам DH) – если цвет совпал, то угадана секретная краска. Естественный вариант защиты: красок слишком много – перебор окажется неприемлемо долгим, а вот сторонам протокола легко выбрать одну секретную краску. Это, опять же, важный математический момент протокола: краски выбрать может быть легко, – вот тысячи, допустим, банок стоят на складских полках, – но реальный DH работает не на красках и там тоже требуется, чтобы был вычислительно простой метод равновероятного случайного выбора нужного числа (секретной “краски”). Да, в классическом варианте с целыми числами – выбрать число случайно и равновероятно не трудно. Вот только тут возникает другая проблема.

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



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

Тавтологические формулировки в условии задачи по математике – это, обычно, очень плохо. Однако их можно использовать в роли некоторой капчи, позволяющей отличить выдачу LLM от попытки осознанного решения. Это особенно актуально, когда то и дело заявляют об “успешном решении ЕГЭ по математике” ИИ/LLM.

Речь тут вот о чём. Любое минимально содержательное утверждение можно переписать в виде набора усложнений, описывающих всё то же утверждение. Тавтологическое переписывание является традиционным источником околоматематических шуток: “возьмём формулу 1 == 1, перепишем единицу справа как определённый интеграл exp(-x) от нуля до бесконечности, а левую – как π/π” и т.д. – в итоге можно получить сколь угодно сложное, многоэтажное сочетание загадочных символов, которое, тем не менее, будет верным. При этом, что удобно именно в учебных задачах уровня ЕГЭ, так это то, что исходное утверждение можно вообще не приводить – оно считается известным.

Сумма углов треугольника равна 180°. Запишем это так: дан треугольник ABC, в котором сумма углов при стороне AC равна сумме двух прямых углов минус третий угол треугольника. Это, очевидно, верно для всякого треугольника в “школьной” геометрии на плоскости, прежде всего потому, что это всего лишь перфразированная аксиома (да, которая делает геометрию евклидовой, но эти детали сейчас не рассматриваем). Однако, во-первых, для записи используется достаточно много слов, что имеет ключевое значение для LLM; во-вторых, выглядит как формулировка свойства, применимого только к данному треугольнику данной задачи; в-третьих, в основе лежит верный геометрический факт, широко используемый в задачах.

Может присутствовать возможность тривиального решения. А может быть – тривиальное решение только подразумевается, то есть, приводится лишь запись как бы задачи, решить которую невозможно, поскольку не хватает данных. Получается своего рода капча – LLM в любом случае будет генерировать “ответ” или вывод “противоречий”, учитывая слова формулировки.

Пример первый – это просто набор утверждений, который подразумевает тривиальные соотношения, постоянно используемые в задачах по планиметрии:

В равностороннем треугольнике ABC углы обозначены α, β, γ, а из вершины B проведена медиана BP. Сумма углов α и β при стороне AC равна сумме двух прямых углов минус угол γ. Найдите высоту треугольника ABC.

Когда я задал эту “задачу” ChatGPT-4o, LLM верно перечислила все фундаментальные свойства равностороннего треугольника (углы – 60° и т.д.), верно распознала углы при стороне AC (в тексте, не на чертеже – см. ниже), но дальше – принялась “рассуждать” о том, что сумма двух прямых углов это (внимание!) 360°, а поэтому сумма углов α и β даст 300°, но должно быть 120°.

120° ≠ 300°. Противоречие. […] Очевидно, что если треугольник равносторонний, то углы не могут давать такую сумму” – написала данная языковая модель свой вывод, перепутав прямые и прямые углы.

То есть, капча сработала. Если бы капча не сработала, если бы ответ был “интеллектуальным”, то LLM должна была бы написать что-то типа такого: “в задаче не хватает данных – найти высоту треугольника невозможно, но можно, например, утверждать, что высота равна медиане”.

Второй пример – в ту же формулировку дописываем длину медианы:

В равностороннем треугольнике ABC углы обозначены α, β, γ, а из вершины B проведена медиана BP длиной 5. Сумма углов α и β при стороне AC равна сумме двух прямых углов минус угол γ. Найти высоту треугольника ABC.

Казалось бы, тут рассказы про углы можно отбросить: из того, что треугольник равносторонний – сразу же следует, что высота равна медиане, то есть ответ – 5. Но если эту же, “уточнённую”, задачу задать ChatGPT в том же потоке, где была задана предыдущая, то выясняется, что данная LLM не только не может отбросить тавтологическую часть условия, но ещё и продолжает считать, что сумма углов – 360° == 180° + 180°. Я не привожу весьма объёмные и подробные “рассуждения” ChatGPT, чтобы не перегружать текст. Если кратко, то LLM предположила, что имеются в виду углы, “образованные при построении медианы BP”, сложила углы уже в двух получившихся треугольниках, и объявила, что “Всё сходится!” (ну конечно, “сходится” – ведь сумма углов двух треугольников это 360°, как и сумма “двух прямых”, в представлении LLM; заметьте, что это, без сомнения, одна из лучших систем в мире, но почему-то предполагается, что данная LLM, якобы, может успешно решать не только ЕГЭ, но и задачи “олимпиадного уровня”).

Далее ChatGPT продолжает “решать” задачу и, используя формулу для длины медианы в равностороннем треугольнике, вычисляет, – в лучших традициях, по формуле! – высоту, подставив найденное значение стороны в формулу высоты. Ответ верный – 5.

Сработала ли и тут “тавтологическая капча”? Да, сработала. Смысла в вычислении по формулам не было: то, что высота равна медиане – этой свойство треугольника ABC. Можно ли трактовать этот момент как желание LLM действовать в парадигме “подставляем числа в формулы так, чтобы получилась хорошая оценка”? Нет. Этому противоречат подробные и точные рассуждения о свойствах треугольника и данная рядом глубоко неверная трактовка суммы двух прямых углов. Естественно, если ChatGPT подсказать, что с прямыми углами тут что-то не то получилось, и что практический смысл интерпретации дополнительных слов условия – тёмен, система тут же исправляется – и сумма углов становится равной 180°, и признаётся, что можно сразу определить, чему равна высота.

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

И посмотрите на чертёж, нарисованный к данной задаче ChatGPT. Казалось бы, система “умеет выводить” формулы и “решать задачи ЕГЭ”, но почему-то не может верно обозначить углы и провести медиану в соответствии с условием.
Triangle



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

Воскресное чтение манускриптов. Манускрипт Vat.gr.1605 из Ватиканской Апостольской библиотеки уже несколько раз упоминался на dxdt.ru. Например, в связи с “кубосом”, иллюстрирующим способ вычисления объёмов. На соседней с “кубосом” странице этого манускрипта, а также на странице предыдушей, описаны и нарисованы круги, тоже с вычислениями. Их и рассмотрим.

Специалиста, подготовившего исходные тексты манускрипта, называют иногда Героном Византийским (не Александрийским, на которого он ссылается), иногда Героном Младшим, а также – византийским Анонимом. Манускрипт Vat.gr.1605 датируют одинадцатым веком, первая часть труда посвящена осадным машинам, методам взятия крепостей и прочим хитростям военного дела, а вторая часть называется “Геодезия” и посвящена сугубо практическим методам измерений “на местности”, которые необходимы, кроме прочего, “для правильного определения высоты крепостных стен, без приближения к ним”. Методы дистанционного измерения здесь, конечно, оптические и основаны на применении диоптры (διόπτρα) – угломерного прибора, предшественника теодолита. (Способы применения диоптры подробно разобраны у более известного Герона – Александрийского.) Именно при помощи диоптры предлагается измерять первый круг. Соответствующая схема круга – на скриншоте из манускрипта.

Manuscript Screenshot

Буквой α обозначен центр круга, по периметру которого сидят кустики и лежат камни (и они тут не просто так нарисованы – см. ниже). Радиус круга – ρε под чертой (черта обозначает запись числа); это число 105, в греческих буквенных обозначениях: ρ == 100; ε == 5; Единица измерения длины: оргия (ὄργυια); то есть, буквально, сажень, однако это не важно для геометрической интерпретации. Слева, в вертикальной записи, обозначена длина окружности: χξ, что соответствует 600 + 60 == 660. Ближе к центру, снизу от α, – площадь круга: λδ καὶ χν, что означает 34 (λδ) [тысячи] и (лигатура ϗ) 600 + 50 == 650, всё вместе: 34650 (квадратных саженей). Тысячи на иллюстрации обозначены диагональной чертой перед λ, а в тексте – прямо записаны словом как “тысячи” (χιλιάδων), что хорошо видно на скриншоте (нижняя строка, я отметил зелёными линями и буквами).

Manuscript Screenshot

Зачем кустики и камни? Герон Византийский в тексте подробно описывает, как нужно строить окружность на местности. Это ведь практическое руководство. Описание такое: установить диоптру в будущий центр, в точку α, после чего взять прямую линию визирования по некоторой другой точке, обозначив её β, – тогда αβ будет радиусом, – и дальше, поворачивая визир диоптры, отмечать в плоскости круга на земле опорные точки по визуальным ориентирам – кустам, камням или другим хорошо заметным предметам; на иллюстрации соответствующие интервалы обозначены буквами по алфавиту. Потому что диоптра – это такой инструмент с транспортиром (диском), винтами и визиром, установленный на моноподе. Так что, пусть манускрипт и подготовлен почти тысячу лет назад, но логика текста отражена на иллюстрации почти во всех необходимых для практического руководства деталях: не хватает только изображения, собственно, диоптры.

В тексте манускрипта приводится и подробный расчёт параметров размеченного на земле круга, исходя из радиуса, который определяется при помощи измерения диоптрой. А именно: радиус нужно удвоить, получив диаметр: 105 * 2 == 210; так как длина окружности составляет “3⅐ диаметра”, то она равна 660, “поскольку это число содержит три раза по 210 и одну седьмую от 210”. Здесь отношение длины окружности к диаметру принято 3⅐, – приблизительно 3.14 в десятичной записи, – неплохое рациональное приближение современного π. Площадь круга находится из тех соображений, что произведение диаметра на длину окружности – это четыре площади круга, соответственно, нужно взять одну четверть от 210*660, что и даст 34650.

Manuscript Screenshot

Заметьте, между прочим, что хоть это и 11 век, но одна четверть, как ни странно, тут уже сокращённо записывается с горизонтальной чертой, и очень похоже на 1/4 (см. в центр скриншота, отмечено зелёными цифрами и стрелкой).

Со вторым кругом всё несколько проще. Так пишет и сам Герон Византийский: здесь окружность рисуется при помощи натянутой от центра верёвки, человеком, у которого не оказалось экзотического прибора – диоптры.

Manuscript Screenshot

Этот круг поменьше. Радиус: λε == 30 + 5 == 35 саженей; периметр: ςκ == 200 + 20 == 220 саженей; площадь круга: γων == 3 (тыс) + 800 + 50 == 3850 саженей – ровно в девять раз меньше предыдущего круга, что очередной раз подчёркивает полезные свойства рациональных чисел.



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

CAA-запись в DNS позволяет управлять тем, какие УЦ могут выпускать сертификаты для имён в соответствующей доменной зоне. Проще говоря, в DNS публикуется имя УЦ, которому разрешено выпускать сертификаты. Чьё имя не указано – тем выпускать нельзя. (Есть тонкости с Wildcard-именами и уведомлениями о попытках заказа сертификата.) Интересно, что отсутствие CAA-записи в зоне разрешает выпуск всем. А если в CAA для имён УЦ указать пустой список (“;”), то выпускать нельзя никому.

То есть, тут мы неожиданно, на практике, сталкиваемся с весьма важной особенностью из области теоретической математики вообще и математической логики в частности. Речь про логики и формальные системы разного уровня. Пустой ящик – имеет совсем другой смысл, чем отсутствие ящика. Отсутствие ящика – это отсутствие CAA-записи, которое отсутствие вовсе и не эквивалентно пустому значению CAA-записи. Ящик есть, но он пуст – это наличие CAA-записи, значение которой – пустое множество. В первом случае, пустое множество – это “количество” CAA-записей в зоне. Во втором случае – количество УЦ, имена которых указаны в CAA-записи. Пустое множество при этом одно и то же, но оно укладывается в разные, рекурсивные ящики. Так можно построить натуральные числа.

Конечно, в спецификации этот подход использован не с целью построения натуральных чисел, а всего лишь с целью сделать использование CAA мягким. Иначе без доступа к DNS вообще не получилось бы сертификаты заказывать у УЦ, которые следуют CAA-записям.



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

В продолжение недавней записки про числа в ML-KEM. Один из ключевых параметров ML-KEM, одинаковый для всех наборов, это число (модуль) 3329. Почему выбрано именно 3329? Был ли выбор “случайным” (а иногда используют проверяемые методы для выбора параметров) или это число подобрано специально?

Число 3329, обозначаемое q, в ML-KEM выбрано строго специально. И вот из каких соображений. Весь практический вычислительный смысл ML-KEM (Kyber) в преобразовании (NTT), позволяющем быстро производить арифметические операции с полиномами. Чтобы быстрые операции NTT стали возможны в ML-KEM, число q должно быть простым, а (q-1) должно делиться на 256. (Более “общо” – делиться должно на степень двойки.) 256 – это другой параметр ML-KEM, его значение продиктовано разрядностью операций (256 бит).

То есть, 3329 – простое, (3329 – 1)/256 == 13. Если эти требования не выполняются, быстрый NTT работать должным образом не будет, поскольку это не настолько универсальный алгоритм, умножать полиномы “в лоб” – очень медленно, и другие быстрые алгоритмы – тоже оказываются медленными по сравнению с NTT. Неподалёку от 3329 не так много чисел, обладающих описанными свойствами: 257, 769, 3329, 7681, 7937. При этом, нужно выбрать число поменьше (важна экономия каждого бита), но чтобы не слишком выросла вероятность получения неверного результата при работе криптосистемы. Для 257 и 769 вероятность ошибки заметно больше. Поэтому авторы алгоритма выбрали 3329.



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

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

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



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

Продолжаем тему “про алгоритмы“, на примере циклов и компиляторов. Запись алгоритма на языке высокого уровня (ЯВУ) – это некоторый пересказ того, что должно выполняться вычислителем. На то он и язык высокого уровня. При этом, обычно, вычислителем исполняется не запись на ЯВУ, а некоторый результат преобразования компилятором. То есть, алгоритм, казалось бы, один. Но, во-первых, может быть много разных записей этого алгоритма на многих разных языках. Даже если удалось удачно определить, что означает фраза “две программы реализуют один алгоритм” (отдельная проблема), то, при минимально содержательном определении, машинное доказательство того, что разные записи соответствуют одному алгоритму – составит большую трудность (в общем виде соответствующее сравнение вообще неразрешимо, но это другая история, а несложные конечные автоматы, обычно, как-то эффективно сравнить всё же можно). Трудности на этом направлении гарантируют, что даже если реализован некий автоматический перевод с одного ЯВУ на другой, это вовсе и не означает, что результат не менее автоматического анализа переведённой программы применим к программе исходной.

Другими словами, если у вас есть добротный анализатор для языка Fortran (для языка, не для алгоритмов), то он вовсе не обязательно эффективен для программ на Haskell, которые транслированы (ну, предположим) в код на Fortran: проверяться всё равно будет Fortran-программа. Это сильно сужает возможности по созданию полезных универсальных “анализаторов кода на ЯВУ”.

Во-вторых, на практике записи алгоритма обрабатывают разные компиляторы, которые переводят его в разный машинный код для разных вычислителей – то есть, для разной аппаратуры. Можно ли тут что-то вообще доказывать о программе, выбросив из рассмотрения компилятор и аппаратуру? Вряд ли. Вообще, а если две реализации некоторого алгоритма дают одинаковый вывод на эталонном наборе входных данных, то означает ли это, что и в рамках реализации записан один и тот же алгоритм? Не обязательно, но степень соответствия действительности кодирования тут сильно зависит от строгости определений.

Предположим, что на процессоре “Имярек-7” команда MOV (“копирующая/перемещающая какие-то данные”) не просто сама по себе Тьюринг-полная (как в x86), но ещё и содержит “особенность” реализации, приводящую к тому, что число 0xFFFFFFFF превращается в 0x0, если сделать два MOV подряд из ОЗУ в регистр REG1. Поэтому, чтобы какие-то детали гарантировать относительно программы и реализации алгоритма, нужно в рассмотрение включить и аппаратные особенности. Сделать это автоматическим способом непросто. Отчасти поэтому-то и появляются всякие разные трансляции в “байт-код”, пригодный для исполнения “песочницей” (например, “Java-машиной”, если хотите): в такой конфигурации можно построить какие-то формальные описания и для языка, и для “машины”, которая его интерпретирует. Можно показать, что тут, при следовании некоторым принципам, всё разрабатывается безопасно (и это, действительно, так, но далеко не в общем случае).

Если же что-то всё же пошло не так, то оно пошло из-за дефекта реализации “машины”, а эта реализация находится за пределами модели. Это удобное сужение темы: если у вас код вылезает из песочницы, то проблема существует над песочницей, а не в ней; песочница хороша по определению: существовала бы проблема в ней – вылезать и не требовалось бы, да.

Представьте, что сложную схему отношений между записями алгоритмов, разными языками высокого уровня, компиляторами и аппаратурой зарисовали в виде графа, где направленные рёбра – это стрелки, обозначающие преобразование кода. Например, перевод с одного ЯВУ на другой. Или перевод в машинный код. Или перевод в подмножество состояний конечного автомата, соответствующего процессору. Тут за каждой стрелкой скрываются целые наборы “схлопывающих” и забывающих отображений, при которых различные способы представлений на стороне начального узла все переводятся в единственный способ на стороне узла конечного (такое вот “ядро” отображения). Например, циклы for, while, do – все схлопываются в сочетание операторов if, потому что только так позволяет записывать целевой язык. Тогда базовые логические преобразования, записываемые формально, могут и совпадать, но вот большое количество возможностей по внесению особенностей и ошибок в исходный код – останется вне пределов доступности для того или иного анализатора, схлопнувшись, что называется, до неразличимости.



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

Как понять, что факторизация числа 15 не может ничего говорить о реализации квантового алгоритма Шора? Понять это несложно: один из делителей числа 15 должен быть меньше 4 (потому что 4^2 == 16), единица не рассматривается по условиям задачи, и это не 2 (потому что только нечётные подходят). Так что любой процесс поиска, каким бы аналоговым он ни был, если вообще сходится, то неизбежно попадёт в 3, что и будет верным ответом.

Заметьте, что ещё и 5 = 3 + 2, а простых чисел, меньших 15, только шесть: поэтому, учитывая, что умножение здесь коммутативно (это очень важно для квантовых алгоритмов), число 2 отбрасывается, а схема поиска расщепляется на пары, то, в самом худшем случае, вероятность, что аналоговый аппарат, состояния которого переключаются по возможным узлам дерева, промахнётся – меньше трети. (На практике, ещё раз, для промахов там просто нет места.)



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

Недавняя записка про оптимизацию циклов и микроконтроллеры иллюстрирует весьма важный момент, связанный с пониманием алгоритмов, записи алгоритмов и реализаций этих алгоритмов. Не менее рельефный пример в этом же направлении касается базовых логических операций и понимания записи формул. Речь про вопрос из области логики, логических выражений: является ли P и ¬¬P – одним и тем же? Даже разработчики-программисты нередко говорят, что “да, является”.

Знак “¬” – это логическое отрицание, проще говоря – “не”, или “!”, как будет во многих привычных языках. То есть, казалось бы, тут, во второй части, написано, что “не-не-P”, а тогда, если P имеет значение TRUE, то “не-не-P” тоже TRUE; то же верно и для P == FALSE. Понятное двойное отрицание, поэтому, что P, что ¬¬P – разницы нет: одно и то же. Это, впрочем, не совсем так.

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

Понятно, что тут очень многие соглашения вынесены за скобки, но, тем не менее, это хороший пример базовых свойств процесса оптимизации. Да, компилятор мог бы заменить ¬¬P на P. Почти что то же самое компилятор и проделывает, когда заменяет запись цикла, тело которого не вносит изменений в результаты работы фрагмента кода, на простое присваивание:

b = 14; 
for(a = 0; a < 8; a++){ 
 b = b + a;
} 

заменяется на эквивалентное

b = 42;

(или это не эквивалентная замена?)

Вообще, запись алгоритма, содержащая определение цикла, описывает повтор неких операторов/команд, но не определяет, как этот повтор должен реализовываться на оборудовании. В принципе, тело цикла можно прямо выписать в качестве повторений команд, это известный приём оптимизации, он так и называется - "развернуть циклы". Очень часто, будучи применённым к программе на языке высокого уровня (ЯВУ), приём даёт заметный прирост производительности. Почему? Потому что исчезли накладные вычислительные расходы. При обычной обработке представления цикла на ЯВУ - появляются необходимые машинные команды, соответствующие "записи" цикла, а процессор вынужден их исполнять. Команд может оказаться неожиданно много: например, потребуется сложная обвязка для реализации обработки переменной цикла.

Занятно, что автоматическая "обратная оптимизация", по размеру кода, когда повторяющиеся логические блоки сворачиваются в циклы, - представляет трудность. Тут, впрочем, уже недалеко и до алгоритмической неразрешимости.



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

Где именно в криптосистеме электронной подписи ECDSA “работает” эллиптическая кривая?

Посмотрим, для начала, на значение подписи, которое состоит из двух параметров – (R, S). Здесь R – это координата X точки на используемой эллиптической кривой, а именно, X-координата точки k∘G, где G – точка кривой, называемая генератором (зафиксированный параметр криптосистемы), а k – секретное уникальное значение (ECDSA nonce). Запись k∘G, – “умножение на скаляр”, – означает повторное сложение точек: G⊕G⊕G⊕…⊕G, где G встречается k раз, а “⊕” – обозначает операцию в группе точек кривой, то есть, сложение точек. (Умножение тут лучше было бы записать [k]G, например, но это детали.)

На значение k накладываются различные ограничения, но это всего лишь натуральное число (конечно, так можно сказать про всё, что встречается “в компьютерах”). Структура кривой такова, что есть пары точек с совпадающими X-координатами, но различными Y-координатами. Этот момент нередко используется в атаках на реализации ECDSA. В данном случае – R это именно X-координата.

Эллиптическая кривая непосредственно использована для вычисления одного параметра подписи – R, который, впрочем, сразу “превращается” из точки, как кортежа значений, задаваемых дополнительной структурой уравнения кривой, в единственное число.

Нетрудно заметить, что здесь, в процессе вычисления R, не использовано никаких значений, связанных с подписываемым сообщением или с секретным ключом – эти элементы пока что даже не упоминались. Параметр R служит в качестве опорного значения, необходимого для проверки подписи – к R должно сойтись значение после “невидимых сокращений”, заложенных в уравнение проверки подписи.

Это основная математическая идея ECDSA: базовое уравнение так устроено, что части структуры преобразования, вынесенные наружу в составе публичных значений, сокращаются, если ключ проверки соответствует подписи (и параметрам), но не сокращаются в прочих случаях.

Сокращающиеся структуры не видны, а вычислить их, – то есть, обратить, – по открытым значениям и параметрам, сложно. Концептуально это напоминает, например, RSA, где внутри открытого ключа всегда содержится структура, связанная с разложением на простые множители, благодаря которой криптосистема работает. Тут необходимо обратить внимание на то, что, во многих практических реализациях, значение k может вычисляться с использованием и подписываемого сообщения, и секретного ключа – например, так делается в схеме детерминированной ECDSA. Но “классическая” ECDSA такого, вообще говоря, не требует. Это, впрочем, один из самых проблемных моментов реализаций данной криптосистемы – так, если третья сторона знает параметры генератора псевдослучайных чисел, который использовался для получения k, то эта третья сторона без особых трудностей может вычислить секретный ключ по значению подписи и подписанного сообщения (см. ниже).

Итак, эллиптическая кривая, заданная для ECDSA, использовалась для вычисления R. Где ещё встречаются операции с точками? Прежде всего – вычисление открытого ключа. Открытый ключ в ECDSA это точка на кривой, а получается он из секретного значения d путём умножения генератора: Q == d∘G. То есть, d – целое число. Принцип эквивалентен вычислению r. Однако, в отличие от r, открытый ключ Q повсеместно записывают как пару координат (X,Y), но это только способ записи, потому что достаточно сохранять X и один “бит знака” для Y.

Вторая часть подписи ECDSA – параметр s. И значение этого параметра вычисляется уже без использования операций с точками кривой. Уравнение для s следующее:

S == k^(-1)*(H + Rd)

– здесь, кроме уже определённых k, R и d (d – секретный ключ), используется значение H – это и есть подписываемое сообщение (технически, это значение хеш-функции от сообщения).

Все значения в данной формуле – это натуральные числа (даже k^(-1)), а не точки. Поэтому тут использованы другие значки для обозначения операций: “+”, “*”, “^(-1)” – это “обычные” операции сложения, умножения и взятия обратного по умножению. “Обычные” в кавычках по той причине, что вычисления проводятся по модулю некоторого числа. То есть, это привычная арифметика остатков. Положительное число, по модулю которого проводятся операции, это так называемый порядок группы точек кривой. Можно считать, что порядок – это количество доступных для вычислений точек кривой. Порядок обозначают, например, P, а тот факт, что это арифметика остатков “по P” записывают как (mod P). Так что свойства кривой тут участвуют только косвенно. Взятие обратного по умножению – k^(-1) – это нахождение такого числа, которое даст 1 (mod P) при умножении на k. Так как вычисления выполняются (mod q), то k^(-1) тоже будет целым числом. Пример: 4*2 == 1 (mod 7) – так как 8/7 – даст остаток 1. Обратите внимание, что все вычисления дальше – тоже (mod P), но отдельно этот момент упоминаться не будет, так как, для практических целей ECDSA и для простого P, свойства вычислений совпадают с привычными операциями в рациональных числах (кроме сложения точек кривой).

Раз это обычная арифметика, то и по формуле для S нетрудно увидеть, что если известны k, H, R, S, то легко вычислить секретный ключ d – просто перепишем уравнение относительно неизвестной переменной d. Значения H, R, S – публично доступны: первое из них это подписанное сообщение, а два других – сама подпись. Никаких “хитростей” эллиптической кривой тут уже не задействовано, поэтому и никакие особенности арифметики эллиптических кривых конкретно на этом направлении криптосистему не защищают. (Более того, если известно не точное значение, но какие-то дополнительные свойства k, то уравнение S можно превратить в неравенство, составить набор “приближений”, который позволит найти приближённое значение для секретного ключа, чтобы потом быстро подобрать его точно по значению открытого. Но это тема для другой записки.) Итак, при вычислении S операции на эллиптической кривой не используются.

Проверка подписи в ECDSA использует следующее уравнение:

C == (H*S^(-1))∘G ⊕ (R*S^(-1))∘Q

– обратите внимание, что тут разные обозначения операций, чтобы можно было различить операции с точками и операции с числами; а значение Q, – открытый ключ, – это d∘G. Работает вся эта схема потому, что, из-за свойств сложения в группе точек кривой, можно операцию сложения точек ⊕ спустить в натуральные числа, вот как: 3∘G ⊕ 5∘G == (G⊕G⊕G)⊕(G⊕G⊕G⊕G⊕G) == 8∘G. При этом, если подставить вместо S формулу вычисления S (см. выше), то в правой части сократится всё, кроме k∘G. Получим, что C == k∘G, а X-координата C должна совпасть с R, если, конечно, подпись верна и вычисления верны. И здесь эллиптическая кривая используется непосредственно для вычисления итогового значения, а именно – умножение на скаляры точек G (генератор) и Q (открытый ключ), сложение получившихся точек.



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

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

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

Понятно, что в статье обнаружатся ошибки и она потребует, как минимум, уточнений. Так, сегодня опубликована записка (Omri Shmueli), указывающая на недостижимые значения параметров, которые использованы в доказательстве корректности алгоритма. Это, впрочем, только добавляет арифметической занимательности, поскольку доказательство недостижимости основано на оценке количества простых чисел, меньших заданного. Дело в том, что описанная версия алгоритма, для корректной работы, требует построения набора из некоторого количества попарно простых натуральных чисел, меньших заданного порогового значения – но для определённых значений параметров таких чисел может не найтись в нужном количестве, поскольку не хватит простых. Если алгоритм нельзя исправить (это ещё тоже не факт) и это удастся доказать, то может даже так оказаться, что постквантовая стойкость криптологических задач теории решёток зависит от количества простых чисел, меньших заданного порога. А это весьма сильное и интересное ограничение. (Но, конечно, вряд ли это так.)

(Update, 13/10/2024: в исходной работе довольно быстро обнаружилась критическая ошибка и автор пока не нашёл способа эту ошибку исправить. Из этого не следует вывод, что “задачи на решётках” обладают строго доказанной стойкостью к “квантовым атакам”.)



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