У меня есть аккаунт в 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”, а операция сложения превращается в конкатенацию (некоммутативная операция, кстати). Да. Не очень-то удобно, не то что апельсины по ящикам.



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

Если взглянуть на “график” эллиптической кривой из недавней записки про протокол Диффи-Хеллмана, то практически сразу можно заметить, что эта картинка обладает хорошо различимой симметрией (как минимум, с горизонтальной осью). Поэтому часто задают вопрос: как же так, это же криптография, а картинка настолько регулярная? Предполагается, что криптографические объекты обязательно должны быть неотличимы от шума.

Эллиптическая кривая над конечным полем.

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

Что именно отображено на картинке (см. рисунок выше)? Каждой точке соответствует пара значений — элементов конечного поля. Сами эти элементы, обозначенные натуральными числами, формируют горизонтальную и вертикальную оси. А поскольку значения отображаются парами, то вся картинка соответствует F×F. Пары элементов — это пары, удовлетворяющие уравнению кривой: y2 = x3 + 2020x2 + x. Обратите внимание, что слева здесь квадрат, и уже из этого вытекает необходимость симметрии на картинке.

Возьмём более наглядный пример. На картинке ниже – нарисованы точки эллиптической кривой y2 = x3 + 17x2 + 1 над полем из 101 элемента; горизонтальная черта – разделяет “график” на верхнюю и нижнюю части (симметричные). Для двух точек – написаны их координаты: (26, 53) и (26, 48).

Кривая над полем из 101 элемента.

Почему точки симметричны? Потому что они обратные, их сумма в группе точек эллиптической кривой равна нулю (нейтральному элементу группы). Координаты X у этих точек совпадают, а координаты Y – обратные по сложению в базовом поле: 53 + 48 == 101, а это 0 (mod 101). Как уже упоминалось выше, левая часть уравнения – квадрат. Это означает, что у нас обязательно есть два элемента поля, соответствующих подстановке элемента 26 в правую часть. Полностью аналогично привычному 22 == (-2)2 == 4. Проверяем: 532 (mod 101) == 482 (mod 101) == 82, а 82 == (263 + 17*262 + 1) (mod 101). Понятно, что в группе, по определению, у каждого элемента есть обратный, поэтому картинка “ветвится” таким образом.

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



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

Мы рассмотрим конкретный (хоть и игрушечный) пример реализации протокола Диффи-Хеллмана (DH) в группе точек эллиптической кривой (ECDH), а потом проведём на этот пример элементарную алгебраическую атаку, основанную на свойствах выбранных параметров, тем самым выясним, что параметры требуется выбирать аккуратно.

В качестве базового поля выберем GF(8191) – конечное поле порядка 8191 (8191 – простое число). Это поле изоморфно вычетам по модулю 8191, то есть, мы рассматриваем остатки от деления на 8191: 0, 1, 2… – поэтому далее элементы поля обозначаются целыми числами.

Выберем уравнение, задающее эллиптическую кривую E:
y2 = x3 + 2020x2 + x.
Это уравнение в форме Монтгомери, общий вид таких уравнений:
y2 = x3 + Ax2 + x, где A – элемент базового поля; в нашем примере A == 2020.

Не всякую эллиптическую кривую над конечным полем можно представить в форме Монтгомери. (Нетрудно заметить, что все кривые в форме Монтгомери вполне определяются значением коэффициента А, это удобно.)

Точки кривой соответствуют парам (X, Y) элементов базового поля, удовлетворяющим уравнению, включая особую точку “бесконечность”, которая в группе точек является нейтральным элементом. Пример точки: (839, 7305). Можно проверить (например, в WoframAlpha), что 73052 (mod 8191) == (8393 + 2020*8392 + 839) (mod 8191). Заметьте, что пара (0,0) лежит на кривой, но не является нейтральным элементом! Нейтральный элемент мы будем обозначать пустой парой () или буквой O, а точка (0,0), если её сложить с точкой (839, 7305), даст точку (1523,5367). Групповую операцию на E обозначим символом “+”.

Группа точек нашей кривой E имеет порядок 8176, то есть, состоит из 8176 элементов. Сразу заметим, что эта кривая не подходит для практического использования, и не только потому, что здесь “мало точек”, но и из-за разложения числа 8176 == 24 * 7 * 73. Однако для нашего примера – именно это и нужно. Кроме базового поля и эллиптической кривой, параметры протокола ECDH включают точку кривой, которая называется генератором. Поскольку генератор – это точка на кривой, он является элементом её группы. Выбираем точку (1029, 895) на роль генератора. Обозначим генератор буквой G. Если генератор G складывать с самой собой, то на каком-то шаге получим нейтральный элемент группы. Количество экземпляров G, которые нужно сложить, чтобы получить нейтральный элемент, называется порядком элемента. Для выбранного значения G порядок равен 1022. Обратите внимание, что порядок точки-генератора меньше порядка группы. G – генерирует подгруппу в E, порядок подгруппы всегда делит порядок группы (теорема Лагранжа): 8176 == 8*1022.

Протокол ECDH основан на умножении точки на скаляр (мы определим эту операцию ниже), то есть, на повторном сложении точки с самой собой. Значение 1022 порядка для генератора G означает, что операции протокола с этим генератором не будут затрагивать все точки группы кривой, а “зацикливаются” в меньшей подгруппе. На практике, выбор кривой и генератора представляет собой довольно сложную процедуру, цель которой – избежать возможных атак. Например, во многих реализациях специально выбирают кривые, группа точек которых имеет простой порядок.

Итак, мы выбрали поле GF(8191), уравнение кривой E y2 = x3 + 2020x2 + x, и генератор G = (1029, 895).

Кривая E

Введём умножение на скаляр: G + G + G = [3]G == 3*G. То есть, мы определили, что сложение трёх экземпляров точки с самой собой – записывается как 3*G. Важно заметить, что такое умножение – это не операция в группе точек кривой, а некоторая дополнительная конструкция.

Перейдём к протоколу ECDH между двумя сторонами. Стороны выбирают секретные скаляры – m и n, это целые положительные числа, меньшие порядка генератора G (понятно, что брать в качестве секретного скаляра единицу – особого смысла тоже нет). Стороны обмениваются по открытому каналу значениями m*G и n*G. Эти значения – точки на кривой, соответствующие n- и m-кратному сложению генератора G. Общий секрет стороны вычисляют так: m*(n*G) == n*(m*G) == (n*m)*G. Ограничение по порядку генератора вызвано тем, что нет смысла использовать числа, превышающие порядок: соответствующая точка всё равно будет находиться в подгруппе генератора.

Пример в числах:

m = 731
n = 395

m*G == (5720, 2990)
n*G == (6695, 8044)

m*(n*G) = [731](6695, 8044) == (4647, 2580) == n*(m*G) = [395](5720, 2990)

Таким образом, стороны получили общий секрет – точку на кривой с координатами (4647, 2580). Эта точка равна точке [731*395]G. Обратите внимание, что произведение 731 * 395 == 288745, можно привести по модулю 1022, то есть, по модулю порядка генератора G. (Но можно и не приводить – результат не изменится.) Значение общего секрета используется в качестве входных данных для вычисления ключей симметричного шифра. Именно так ECDH применяется в TLS. Точке соответствует пара (X, Y) элементов поля, но в качестве источника данных для ключа может использоваться только один элемент, обычно, это X-координата.

Сторона, прослушивающая канал, получила значения n*G и m*G, знает параметры поля, кривую, значение G, но не знает n и/или m. Вычисление n (или m) по известному n*G (или m*G) – называется задачей дискретного логарифмирования в конечной группе и, для произвольных групп точек эллиптической кривой достаточно большого порядка, вычислительно трудна. На практике используются параметры с порядками, близкими к 2256 (и более). Методов, позволяющих даже на специализированном суперкомпьютере за разумное время решить задачу дискретного логарифмирования для произвольных параметров и групп таких порядков – пока не найдено. Однако для некоторых специальных случаев – методы известны. Некоторые из этих методов элементарны, как будет видно из примера ниже.

Попробуем теперь взломать нашу “криптосистему” ECDH на эллиптической кривой. Конечно, в случае использованных параметров, не составляет труда простым перебором найти нужное значение секретного скаляра (оно лежит в интервале [2..1021]). Однако простой перебор здесь работает только потому, что порядок далёк от практических значений. Но есть гораздо более эффективный метод, который, с некоторыми упрощениям, и описан ниже.

Заметим, что число 1022 == 2 * 7 * 73. Это означает, что внутри нашей подгруппы генератора G могут быть меньшие подгруппы, порядок которых делит порядок генератора. Всякий элемент подгруппы представим в виде l*G – то есть: G + G+…+ G (l раз). Так что, возможно, найдутся такие элементы, которые конструируются из G, но при этом их порядок гораздо меньше 1022. Пусть такой элемент – P = (6736, 4842) == 14*G, где 14 == 1022/73 == 2 * 7. Используя P, мы можем “разбить” все элементы подгруппы генератора на подмножества с меньшим количеством элементов, каждый из которых соответствует той или иной “кратности” P. P имеет порядок 73, то есть 73*P == O, где O – нейтральный элемент группы (или, в других обозначениях: P + P + … + P = O). Это всего 73 различных значения (включая нейтральный элемент). Атака работает следующим способом. Сгенерируем и запишем в опорную таблицу все пары (k, k*P), где k пробегает [1..72]. Получив значение m*G (открытый ключ ECDH Q == m*G), мы будем вычитать из него G до тех пор, пока не обнаружим элемент, кратный P, который находится в опорной таблице. (Вычитание в группе эквивалентно сложению с обратным элементом, то есть -G, обратный к данному элемент группы кривой нетрудно вычислить.) Пусть мы на шаге q последовательного вычитания нашли подходящее k*P в таблице, тогда, зная k, мы можем вычислить секретный скаляр m == k * 1022/73 + q.

Проверим для m == 731, как в примере выше.

731*G == (5720, 2990). Вычитаем генератор G равный (1029, 895). Обратная к G точка – (1029, 7296), т.к. 7296 + 895 = 0 (mod 8191).

(5720, 2990) + (1029, 7296) == (5623, 8124)
(5623, 8124) + (1029, 7296) == (6316, 6614)
(6316, 6614) + (1029, 7296) == (7183, 6772)

Точка (7183, 6772) является кратной точкой для элемента P, который выбран нами выше в качестве опорного: [52]P == (7183, 6772). Таким образом, мы провели три операции сложения точек кривой (q == 3) и нашли заранее вычисленную опорную точку. Теперь мы можем определить секретный скаляр: 52 * 1022/73 + 3 == 731. Заметьте, что в одно значение P как бы “входит” 14 экземпляров G, то есть, чтобы гарантированно попасть в одну из точек опорной таблицы, потребуется не более 13 операций сложения точек. Для определения значения m == 731 прямым полным перебором – пришлось бы выполнить 730 сложений (если, конечно, не оптимизировать процесс поиска другим способом). Очевидно, что можно использовать и другие подгруппы для этой атаки – в каких-то случаях потребуется больше памяти для хранения опорной таблицы, но меньше операций с точками для поиска элемента таблицы; в других случаях – меньше памяти, но больше операций с точками.

Посмотрим, почему это работает, с другой стороны. В группе точек генератора все элементы представимы в виде l*G, для некоторого целочисленного l. Мы выбрали точку P == l*G. На следующем шаге мы вычисляем все значения k*P (их конечное количество) и записываем их в таблицу вместе с соответствующим k. То есть, мы построили таблицу дискретных логарифмов для P. Каждое из значений в таблице равно k*(l*G), что можно переписать как (k*l)*G (важно понимать, что здесь использованы два различных умножения: в целых числах, для k*l, и умножение скаляра на точку кривой для G). Соответственно, открытый ключ ECDH Q == m*G можно переписать как (k*l + r)*G, где k*l + r == m – представление целого m, где r – остаток от деления на l (0 <= r < l). Перепишем выражение: Q = (k*l)*G + r*G. (Здесь знак “+” уже превратился в обозначение операции сложения точек, но общий смысл не поменялся.) Мы вычитаем из значения Q генератор G до тех пор, пока полученный результат не совпадёт с каким-то из элементов нашей таблицы логарифмов для P, таким образом – подсчитывается значение остатка r. Как только мы нашли подходящий элемент в таблице, мы знаем все значения, нужные для вычисления секретного ключа m: значение k – из таблицы, l – известно из построения P, r – остаток, равный количеству операций вычитания, потребовавшихся для того, чтобы Q указало на тот или иной элемент таблицы. Таблица логарифмов содержит всего 72 элемента, что значительно меньше, чем 1022.

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



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

Немного занимательной теории чисел, применительно к одной весьма экзотической особенности TLS (как известно, это основной защищённый протокол современного Интернета). Изучая настройки и параметры данного протокола, можно столкнуться с интересной формулой:

p = 2ⁿ – 2ⁿ⁻⁶⁴ + 2⁶⁴(⌊2ⁿ⁻¹³⁰e⌋ + x) – 1

Для чего она нужна и что обозначает?

В новой версии TLS 1.3 зафиксированы практически все криптографические параметры, которые только можно как-то зафиксировать. Так, зафиксированы группы для протокола Диффи-Хеллмана (DH), причём, даже группы для “классического” варианта (“классический” – это который в мультипликативной группе кольца вычетов; а если говорить проще, то тот вариант, который по модулю простого числа, с взятием остатков, а не эллиптический). С наперёд заданными параметрами криптосистем связаны опасения: а вдруг эти параметры специально выбраны с бэкдором? Поэтому существуют методы, позволяющие генерировать параметры некоторым проверяемым и, вместе с тем, “непредсказуемым” способом. Теперь переходим к формуле.

Это формула, по которой генерируются простые числа, задающие группу для DH в TLS. n – требуемая разрядность, e – основание натурального логарифма, x – переменная, принимающая целые положительные значения. То есть, можно сказать, эта формула извлекает из числа e подходящее целое простое число нужной разрядности (подходящее – потому что подходит не всякое, но это детали). Для получения именно простого числа – нужно подбирать значение x (используется минимальное подходящее). Механизм описан в RFC 7919 (но попробуйте “нагуглить” эту формулу).

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

Впрочем, с фиксированными параметрами DH связаны и более простые рассуждения: стойкость DH базируется на сложности дискретного логарифмирования, но для классического варианта и заранее заданной группы (параметра, то есть) известно, что можно предвычислить некоторые алгебраические структуры, которые потом позволят вычислять логарифм быстро. Правда, такие вычисления требуют огромных мощностей и/или затрат времени. Но если вы теоретико-числовая служба специального агентства и заранее знаете, что набор из нескольких групп позволит раскрывать почти весь TLS-трафик, то можно и потратиться. Ключевой момент тут – нужно заранее знать группу, а универсальные методы неизвестны.



Comments Off on Формула для групп из TLS

Многие слышали про криптографию на эллиптических кривых. Но эллиптические кривые, которые давно являются мощным инструментом теории чисел, можно успешно применить к решению элементарной (по формулировке) арифметической задачки про бананы, яблоки и ананасы. Текст ниже – несколько сокращённая версия моего перевода ответа Quora.com, который дал Alon Amit (англ.).
Читать полностью



Comments Off on Фрукты и эллиптические кривые

Около года назад я кратко описывал возможную атаку на протокол биткойн, основанную на быстром вычислении дискретного логарифма при помощи квантового компьютера, что ломает подпись ECDSA. Вот, появилась весьма подробная научная публикация на эту же тему: Quantum attacks on Bitcoin, and how to protect against them – в работе рассматриваются и квантовые атака на алгоритм “доказательства проведённой работы” (PoW), они, впрочем, признаны неэффективными на практике.



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

ksks7 (Техничная записка из области популярной криптологии, которая, думаю, будет полезна и на dxdt.ru.)

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

Если третья сторона записывает TLS-трафик, то вместе с ним сохраняются и данные, послужившие источником сеансовых ключей (в случае использования DH). Фактически, можно говорить о том, что эти ключи тоже сохраняются вместе с записанным трафиком. В этом и состоит тонкость, относящаяся к области различий между реально уничтоженными (или отсутствующими) и зашифрованными данными. Для восстановления ключей DH из записи трафика нужно обладать дополнительной информацией (либо уметь решать вычислительные задачи, которые сейчас считаются трудными). К такой дополнительной информации относится, скажем, состояние генератора псевдослучайных чисел, который использовался на стороне сервера (или клиента) при выработке сеансовых параметров DH.

Когда говорят о прогрессивной секретности (PFS), которой позволяет добиться использование DH, то имеется в виду вовсе не то, что ключи невозможно восстановить после того, как сессия завершилась, а лишь то, что утечка долговременного ключа не раскрывает сессионных ключей. Не более того. Обычно, долговременный ключ в TLS – это ключ, используемый для аутентификации сервера, при помощи электронной подписи. Если прогрессивная секретность отсутствует, то восстановление сеансовых ключей, если у вас есть долговременный секретный ключ (это будет, соответственно, RSA) оказывается тривиальной задачей – просто расшифровываем исходные данные из трафика.

Трафик приложений в TLS зашифровывается симметричным алгоритмом, который и использует сеансовые ключи. То есть, в принципе, для того, чтобы раскрыть трафик, можно “просто” правильно подобрать симметричные сеансовые ключи. Однако эта задача вовсе не эквивалентна восстановлению ключей из записанного обмена параметрами DH. Скорее всего, с DH разобраться легче (теоретически; а на практике – приходится надеяться на уязвимости, которых, впрочем, немало).

Для детального понимания ситуации нужно рассмотреть следующий случай: предположим, что стороны, обменивающиеся данными в рамках защищённой сессии, используют заранее известный им разовый (относительно сессии) набор секретных сеансовых симметричных ключей и, скажем, AES. То есть, симметричные ключи не генерируются при помощи обмена в рамках DH, а известны заранее. По каналу связи они не передаются, канал не используется для их генерации. (Аутентификацию оставим за скобками.) Пусть используется добротный режим потокового шифрования: генерируется ключевой поток (гамма), совпадающей по длине с открытым текстом, а шифротекст является результатом операции XOR над открытым текстом и ключевым потоком. Примерно так работает GCM (аутентификацию мы договорились оставить за скобками) и всякий другой “режим счётчика”. Так как полученный ключевой поток будет, вообще говоря, вычислительно неотличим от псевдослучайной функции, то для записавшей трафик стороны ситуация окажется, условно говоря, семантически неотличима от абсолютно стойкого шифрования.

Думаю, понятно, что при использовании DH ситуация отличается в корне: теперь в составе сеанса появляются открытые ключи DH, которые представляют собой новый вектор атаки, а кроме того – они сохраняются вместе с трафиком. А вот в предыдущем случае – физическое уничтожения носителя ключей, действительно, приводит к уничтожению и самих ключей.

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

(Впрочем, для AES тоже можно предложить научно-фантастический компьютер, решающий соответствующую систему уравнений: но такому компьютеру потребуется известный открытый текст, а для случая DH и логарифмирования – он не нужен.)



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

Продолжим тему восстановления недоуничтоженных шредером документов. В комментариях к прошлой записке jno подтверждает, что восстановить простую “лапшу” – возможно. Напомню, что “лапша” – это вариант, в котором шредер разрезает лист на множество одинаковых узких полос, в одном из направлений, например, вдоль. Вообще, почему-то часто в ответ на вопрос о том, сколько вариантов потребуется перебрать для восстановления документа, разрезанного на n аккуратных полосок, приходится слышать о числе n! – очень много, да. Естественно, если бы это было так на практике, то для уверенного уничтожения оказалось бы достаточно резать листы вдоль на, скажем, 29 полосок (любой ширины, заметьте!). К счастью исследователей мусора, всё обстоит иначе, и факториал, задающий верхний предел для перестановок полосок, тут не играет решающей роли.

Из-за того, что в исходном документе содержится некоторая дополнительная структура, для восстановления не нужно перебирать все варианты перестановок. Так, если вы можете точно определить, что две данные полоски были (или не были) соседними (даже без выяснения правый или левый “сосед” обнаружился), то сложность восстановления всего документа из “лапши” не превысит n2. Занятно, что восстановление чистого белого листа оказывается более проблематичным, чем листа с текстом. Если, конечно, предполагать, что в качестве опорной структуры используется начертание букв и строк текста (или некий рисунок). С другой стороны, зачем восстанавливать чистый лист?

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

И, конечно, можно устроить шредер так, что восстановить документ будет невозможно: достаточно измельчать бумагу в труху, пусть и механическим способом.



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