Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

книги / Практическая криптография

..pdf
Скачиваний:
6
Добавлен:
12.11.2023
Размер:
16.23 Mб
Скачать

10.2 Модели атак на генератор псевдослучайных чисел

183

сложна, что попытка использовать такие числа может только ухудшить без­ опасность системы. Любое слабое место генератора истинно случайных чисел моментально приведет к потере безопасности. С другой стороны, если исполь­ зовать истинно случайные числа только для того, чтобы получить начальное число для генератора псевдослучайных чисел, можно позволить себе гораздо более придирчиво выбирать источники энтропии, что, безусловно, повышает наши шансы на создание действительно безопасной системы.

10.2Модели атак на генератор псевдослучайных чисел

Генераторы псевдослучайных чисел исследованы сравнительно мало. Са­ ма задача генерации случайных (псевдослучайных) чисел на основе некоторо­ го начального числа довольно проста. Проблема состоит в том, где взять слу­ чайное начальное число и как сохранить его в секрете [47]. Наилучшее реше­ ние этой проблемы, известное нам на данный момент, называется Yarrow [46]. Этот генератор псевдослучайных чисел, который пытается защитить систе­ му от всех известных типов атак, был разработан нами несколько лет назад вместе с Джоном Келси (John Kelsey).

В каждый момент времени у генератора псевдослучайных чисел есть внутреннее состояние. Запросы на получение случайных чисел обслужива­ ются криптографическим алгоритмом, который генерирует псевдослучайные числа. Этот алгоритм также обновляет внутреннее состояние генератора, что­ бы гарантировать, что в следующий раз генератор не возвратит те же самые случайные числа. Этот процесс не слишком сложен; с выполнением данной задачи вполне справится любая функция хэширования или блочный шифр.

Существуют различные формы атак на генераторы псевдослучайных чи­ сел. Прежде всего следует отметить прямую атаку, где злоумышленник пы­ тается воссоздать внутреннее состояние генератора на основе его выходных данных. Это классический тип криптоатаки, которому довольно легко про­ тивостоять, используя современные приемы криптографии.

Ситуация усложняется, если злоумышленник на каком-то этапе сможет заполучить внутреннее состояние генератора. Пока что нас не интересует, как это произойдет. Возможно, утечка информации была вызвана каким-то изъя­ ном в программном обеспечении, либо компьютер загружался в первый раз и еще не имел случайного начального числа, либо, скажем, злоумышленнику удалось считать файл начального числа с диска. Во всех этих случаях с гене­ ратором начнут происходить довольно неприятные вещи. Если злоумышлен­ нику удастся узнать внутреннее состояние классического генератора псевдо­ случайных чисел, он сможет воспроизвести значения всех последующих вы­

184

Глава 10. Генерация случайных чисел

ходных данных и всех обновлений внутреннего состояния. Из этого следует, что, если атака на генератор псевдослучайных чисел когда-нибудь окончится успехом, этот генератор никогда не сможет вернуться в безопасное состояние.

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

Даже если мы перемешаем внутреннее состояние генератора с небольши­ ми количествами энтропии, полученными в результате возникновения собы­ тия, у злоумышленника все еще останутся пути нападения. Он может посы­ лать генератору частые запросы на получение случайных данных. Посколь­ ку общее количество энтропии, добавляемое к внутреннему состоянию ге­ нератора в промежуток времени между двумя подобными запросами, будет ограничено, скажем, 30 битами, злоумышленник сможет просто перебрать все возможные варианты случайных входных данных и определить новое внутреннее состояние, полученное после перемешивания. Это потребует око­ ло 230 шагов, что вполне достижимо с помощью современных технологий1. Обнаружив правильное решение, злоумышленник сможет легко проверить его с помощью все тех же случайных данных, выдаваемых генератором.

Лучшее, что можно сделать для борьбы с описанным типом атак, — это ор­ ганизовать пул входящих событий, которые несут в себе энтропию. Мы будем собирать энтропию до тех пор, пока ее не окажется достаточно для того, что­ бы при перемешивании энтропии с внутренним состоянием генератора зло­ умышленник не мог угадать собранные случайные данные. Сколько же энтро­ пии для этого потребуется? Согласно нашим требованиям к уровню безопас­ ности, злоумышленник должен потратить на осуществление атаки минимум 2128 шагов, для чего понадобится 128 бит энтропии. Здесь, однако, мы стал­ киваемся с серьезной проблемой: получить какую-либо оценку количества эн­ тропии невероятно сложно, если вообще возможно. Оценка энтропии весьма существенно зависит от того, сколько знает или может знать злоумышлен­ ник, а эта информация еще не доступна разработчикам системы на стадии проектирования. В этом и состоит основная проблема генератора Yarrow. Он пытается измерить энтропию источника, используя оценку энтропии, а полу­ чить правильную оценку для всех ситуаций практически невозможно.

1Многие, наверное, будут возмущены небрежностью наших вычислений. В этом примере нам следовало использовать оценочную энтропию (guessing entropy), а не стандартную шенноновскую энтропию. Более подробно о мерах энтропии можно прочитать в [14].

10.3 Проект Fortuna

185

10.3Проект Fortuna

Во время работы над этой главой мы значительно усовершенствовали ге­ нератор Yarrow. Новое решение получило название Fortuna в честь Форту­ ны —древнеримской богини слепого случая и удачи2. Fortuna решает пробле­ му необходимости определения оценок энтропии, просто отказавшись от них. Оставшаяся часть этой главы в основном посвящена рассмотрению деталей ГПСЧ Fortuna3.

Fortuna состоит из трех частей. Генератор принимает на вход начальное число фиксированной длины и выдает произвольное количество псевдослу­ чайных данных. Аккумулятор собирает и накапливает энтропию из различ­ ных источников, а также время от времени изменяет начальное число генера­ тора. И наконец, система управления файлом начального числа гарантирует, что генератор сможет производить случайные данные даже непосредственно после перезагрузки компьютера.

10.4Генератор

Генератор преобразует некоторое состояние фиксированной длины в вы­ ходные данные произвольной длины. В качестве генератора мы будем ис­ пользовать AES-подобный блочный шифр. Выберите тот, что вам больше нравится, — AES (Rijndael), Serpent или Twofish (см. раздел 4.5.7). Внутрен­ нее состояние генератора включает в себя 256-битовый ключ блочного шифра и 128-битовый счетчик.

По своей сути генератор — это всего лишь блочный шифр, работающий в режиме счетчика. Напомним, что режим счетчика или CTR генерирует случайный поток данных, которые мы будем использовать в качестве вы­ ходных. Для повышения безопасности добавим к режиму работы блочного шифра еще несколько усовершенствований.

Если пользователь или приложение запрашивает случайные данные, ге­ нератор запускает свой алгоритм и производит псевдослучайные данные. Те­ перь предположим, что злоумышленнику удается раскрыть состояние гене­ ратора после выполнения очередного запроса. Было бы хорошо, если бы это не дискредитировало предыдущие результаты, выданные генератором. Для этого после выполнения каждого запроса будем генерировать еще 256 бит

2Виачале мы собирались назвать его по имени древнегреческой богини счастья и благо­ денствия Тюхе, но затем поняли, что многие не смогут правильно прочитать слово “ТусЬе”.

3Чтобы не путать генератор, являющийся одной из трех составных частей проекта For­ tune, и сам проект Fortuna (который, по сути, представляет собой реализацию криптогра­ фического генератора псевдослучайных чисел), будем обозначать последний аббревиату­ рой ГПСЧ (от “генератор псевдослучайных чисел"). — П рим, перев.

186 Глава 10. Генерация случайных чисел

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

Чтобы сгенерированные данные обладали статистической случайностью, не следует генерировать слишком много данных одновременно. Действитель­ но, в истинно случайных данных значения блоков могут периодически повто­ ряться, в то время как выходные данные режима счетчика никогда не содер­ жат повторяющихся блоков. (Более подробно это описано в разделе 5.8.2.) Су­ ществует несколько способов решения этой проблемы. Например, можно ис­ пользовать только половину каждого блока шифрованного текста, что прак­ тически устранит статистическое отклонение от истинно случайной последо­ вательности блоков. В качестве альтернативы вместо блочного шифра мож­ но было бы использовать так называемую псевдослучайную функцию (pseu­ dorandom function), но нам пока что не попадалось хорошо исследованных и эффективных предложений. Самое простое, что можно сделать в данной ситуации, — это ограничить количество байтов случайных данных, которые могут выдаваться в ответ на один запрос. Это значительно затруднит выявле­ ние статистического отклонения от истинно случайной последовательности.

Если бы нам понадобилось сгенерировать 264 блока данных с помощью одного и того же ключа, мы бы могли ожидать появления одной коллизии среди значений блоков. Несколько повторяющихся запросов такого размера быстро бы показали, что выходные данные генератора не являются истинно случайными; им не хватает ожидаемого числа коллизий. Поэтому мы ограни­ чиваем максимальный размер данных, которые могут быть выданы в ответ на один запрос, 216 блоками (т.е. 220 байт). Для идеального генератора слу­ чайных чисел вероятность обнаружения коллизии среди 216 блоков данных составляет около 2“ 07, поэтому полное отсутствие коллизий может быть об­ наружено только после выполнения около 297 запросов. Общее количество работы, которое придется проделать злоумышленнику, составит примерно 2113 шагов. Это, конечно же, меньше запланированных нами 2128 шагов, но все равно довольно неплохо.

Мы знаем, что изменяем своим принципам, соглашаясь на более низкий (правда, лишь немного более низкий) уровень безопасности. К сожалению, хорошей альтернативы этому решению, кажется, нет. У нас нет подходящих криптографических функций, на основе которых можно было бы построить генератор псевдослучайных чисел с полным 128-битовым уровнем безопас­ ности. Мы бы могли применить функцию SHA-256, но она слишком мед­ ленная. Люди всегда будут спорить о том, нужно ли использовать хороший криптографический генератор псевдослучайных чисел, и одним из аргумен­ тов против использования последнего является скорость. Заметное снижение скорости работы генератора для выигрыша еще нескольких бит безопасности

10.4 Генератор

187

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

Если бы у нас был блочный шифр с 256-битовым размером блока, то­ гда вопрос коллизий не стоял бы вообще. Впрочем, на практике описанная атака не представляет собой какой-либо серьезной угрозы. Для ее осуществ­ ления недостаточно тех самых 2113 шагов, которые должен выполнить зло­ умышленник. Атакуемому компьютеру тоже придется провести 2113операций шифрования. Как видите, успешность подобной атаки зависит не столько от скорости работы компьютера злоумышленника, сколько от скорости работы компьютера самого пользователя. Большинство пользователей не собираются увеличивать вычислительную мощность своего компьютера только для того, чтобы помочь злоумышленнику. Честно говоря, нам не нравятся подобные ар­ гументы в пользу безопасности решения. Они слишком неоднозначны, и если генератор псевдослучайных чисел когда-нибудь будет использован в непри­ вычном окружении, эти аргументы могут и не сработать. Все же, учитывая ситуацию, наше решение представляется наилучшим компромиссом, к кото­ рому мы могли бы прийти.

Когда по окончании выполнения каждого запроса мы пересчитываем ключ блочного шифра, то не сбрасываем счетчик. Это второстепенный мо­ мент, однако он позволяет избежать проблемы коротких циклов. Представим, что нам необходимо сбрасывать счетчик после выполнения каждого запроса. Если значение ключа когда-нибудь повторится во второй раз, а все запросы будут получать фиксированный объем данных, тогда следующее значение ключа также повторится во второй раз. В результате можно получить корот­ кий цикл значений ключа. Вообще-то подобная ситуация маловероятна, но, не сбрасывая счетчик, этой проблемы можно избежать вообще. Поскольку дли­ на счетчика составляет 128 бит, мы никогда не повторим значение счетчика (генерация 2128 блоков выходит за пределы вычислительных возможностей наших компьютеров), что автоматически не допустит образования каких-ли­ бо циклов. Вдобавок ко всему мы можем использовать значение счетчика О для указания того, что генератор еще не имеет ключа и, следовательно, не может выдавать данные.

Обратите внимание: ограничение максимального объема данных, кото­ рый может быть выдан в ответ на один запрос, до 1 Мбайт, вовсе не явля­ ется непреодолимым. Если вам нужно больше мегабайта случайных данных, просто повторите запрос. В действительности реализация системы может со­ держать интерфейс, который будет автоматически выполнять подобные по­ вторяющиеся запросы.

Сам по себе генератор является очень полезным модулем. Думаем, в боль­ шинстве реализаций он будет доступен не только как компонент ГПСЧ For-

188

Глава 10. Генерация случайных чисел

tuna, но и как часть его интерфейса. Взять хотя бы программу, которая вы­ полняет моделирование методом Монте-Карло4. Мы хотим, чтобы это моде­ лирование было случайным. Вместе с тем желательно, чтобы при необходимо­ сти мы могли воспроизвести нужные вычисления (например, для отладки или проверки). Для этого в начале программы можно единоразово вызвать встро­ енный генератор случайных чисел операционной системы. С его помощью мы получим случайное начальное число. Это число может быть зафиксировано как часть выходных данных программы, а затем использовано нашим гене­ ратором для вычисления всех оставшихся случайных данных, необходимых для моделирования. Зная исходное начальное число генератора, можно про­ контролировать правильность всех вычислений. Для этого достаточно еще раз запустить программу с теми же входными данными и начальным чис­ лом. А для отладки один и тот же процесс моделирования может запускать­ ся снова и снова, причем его поведение всегда будет одинаковым — лишь бы исходное начальное число оставалось неизменным.

Теперь рассмотрим функционирование генератора подробнее.

10.4.1Инициализация

Она довольно проста. Мы устанавливаем значения ключа и счетчика рав­ ными нулю, чтобы показать, что генератору еще не было передано начальное число.

ф у н к ц и я I N I T I A L I Z E G E N E R A T O R

выход: Q Состояние генератора.

Установим значения ключа К и счетчика С равными нулю. (К, С) <- (0,0)

Сформируем состояние. G «— С)

return Q

10.4.2 Изменение начального числа

Функция R E S E E D обновляет состояние генератора с помощью входной строки произвольной длины. На этом уровне нас не волнует, что будет содер­ жать входная строка. Чтобы гарантировать тщательное перемешивание вход­ ной строки с существующим ключом, мы применим функцию хэширования.

ф у н к ц и я R E S E E D

вход: Q Состояние генератора; изменяется этой функцией.

Моделирование методом Монте-Карло — это моделирование, управляемое случайным выбором некоторых величин.

10.4 Генератор

189

s Новое или дополнительное начальное число.

Вычислим новый ключ с помощью функции хэширования. К <- SHAd - 256 (К 1|а)

Увеличим на единицу значение счетчика, чтобы оно стало ненулевым, и пометим, что генератору было передано начальное число. В дан­ ном случае С рассматривается как 16-байтовое целое число, пред­ ставленное в формате, в котором наименее значимый байт запи­ сывается первым.

С ^ С + 1

Здесь значение счетчика С рассматривается как целое число. Позднее он будет выступать в качестве блока открытого текста. Для преобразования одного значения в другое будем использовать соглашение о формате записи целых чисел, при котором наименее значимый байт записывается первым. Блок открытого текста — это блок, состоящий из 16 байт: ро,... ,pisОн соответствует целочисленному значению

15

ЕР-2*'-

1=0

Используя это соглашение, мы можем рассматривать С и как 16-байтовую строку, и как целое число.

10.4.3Генерация блоков

Следующая функция генерирует заданное количество блоков случайных данных. Это внутренняя функция, которая будет использоваться только са­ мим генератором псевдослучайных чисел. Любой объект за пределами гене­ ратора не должен иметь доступа к этой функции.

ф у н к ц и я G E N E R A T E B L O C K S

вход:

Q

Состояние генератора; изменяется этой функцией.

 

к

Количество блоков, которое необходимо сгенерировать.

выход:

г

Псевдослучайная строка длиной 16fc байт.

assert С ф 0

Начнем с пустой строки.

Г i6

Присоединим к ней нужное количество блоков. for г = 1, . . . , k do

г4 - Г II Е(К, С)

С+ - С + 1

190

Глава 10. Генерация случайных чисел

od return г

Как вы, наверное, уже догадались, Е( К, С) — это функция шифрования блочного шифра, на вход которой подаются ключ К и блок открытого текста С. Вначале функция G E N E R A T E B L O C K S проверяет, не равно ли значение С нулю (это бы означало, что на вход данного генератора еще никогда не пода­ валось начальное число). Перед началом цикла переменной г присваивается пустая строка, после чего к ней поочередно присоединяется каждый следу­ ющий подсчитанный блок. Строка, сформированная таким образом, и будет выходным значением функции.

10.4.4Генерация случайных данных

Функция P S E U D O R A N D O M D A T A генерирует случайные данные по запросу пользователя генератора. Она позволяет получить псевдослучайную строку длиной до 220 байт и гарантирует, что после выполнения запроса любая ин­ формация о сгенерированных данных будет уничтожена.

ф у н к ц и я P S E U D O R A N D O M D A T A

вход: б Состояние генератора; изменяется этой функцией.

пКоличество байт случайных данных, которое необходимо сгенерировать.

выход: г Псевдослучайная строка длиной п байт.

Ограничим длину выходной строки, чтобы уменьшить статистиче­ ское отклонение от истинно случайных данных. Убедимсятакоюе, что заданная длина строки не является отрицательной.

a s s e r t 0 < п < 2 20

Сгенерируем выходные данные,

г *- первые- n - 6 a t f r ( G E N E R A T E B LOCKS {Q, [ n / 1 6 ] ) )

Изменим значение ключа, чтобы избежать возможной дискредита­ ции этих данных в будущем.

К *- G E N E R A T E B L O C K S (Q,2 ) r e t u r n г

К а к видите, результат функции P S E U D O R A N D O M D A T A генерируется пу­ тем вызова функции G E N E R A T E B L O C K S . Единственное различие между ними состоит в “усечении” результата функции P S E U D O R A N D O M D A T A до нужного количества байт. (Оператор [...] — это оператор округления сверху.) По­ сле этого мы генерируем еще два блока данных, чтобы сформировать новый ключ. Когда старый ключ К будет уничтожен, никто не сможет повторно

10,5 Аккумулятор

191

вычислить значение г. Если функция P S E U D O R A N D O M D A T A не сохранит ко­ пию значения г и очистит область памяти, в которой хранилось это значение, то по завершении работы функции у генератора просто не останется путей для утечки какой-либо информации об г. Именно поэтому даже последующий взлом генератора, если таковой когда-нибудь произойдет, никак не повлияет на секретность предыдущих выходных данных. Он будет угрожать лишь без­ опасности будущих выходных данных — проблема, решением которой должен заниматься аккумулятор.

Как уже отмечалось, объем данных, которые может возвратить функция P S E U D O R A N D O M D A T A , ограничен. Мы не будем описывать оболочку, которая сможет возвращать случайные строки большего размера путем многократно­ го вызова функции P S E U D O R A N D O M D A T A . Обратите внимание: увеличивать максимальный размер выходных данных, получаемых за один вызов функ­ ции, не следует, поскольку это увеличит статистическое отклонение от ис­ тинно случайной последовательности. Выполнение повторяющихся вызовов функции P S E U D O R A N D O M D A T A не приведет к снижению эффективности. До­ полнительные расходы состоят лишь в том, что на каждый мегабайт сгене­ рированных случайных данных система генерирует еще 32 байта случайных данных (для формирования нового ключа) и выполняет пересчет подклю­ чей блочного шифра. Для всех предложенных нами блочных шифров такие расходы являются незначительными.

10.4.5Скорость работы генератора

Генератор Fortuna, описанный в предыдущих разделах, является крип­ тографически сильным генератором псевдослучайных чисел в том смысле, что он преобразует начальное число в псевдослучайную строку произволь­ ной длины. Скорость работы генератора Fortuna практически равна скоро­ сти работы используемого блочного шифра. В системах с РС-совместимыми процессорами генерация одного байта псевдослучайных данных для больших запросов занимает менее 20 циклов работы процессора. Таким образом, наш генератор может легко применяться в качестве замены большинства библио­ течных функций генерации псевдослучайных чисел.

10.5Аккумулятор

Аккумулятор собирает истинно случайные данные из различных источни­ ков энтропии и применяет их для обновления начального числа генератора.

192

Глава 10. Генерация случайных чисел

10.5.1

Источники энтропии

Будем исходить из предположения, что в нашем окружении находится несколько источников энтропии. Каждый источник может генерировать со­ бытия, содержащие энтропию, в любой момент времени. Нас не интересу­ ет то, что конкретно будет использоваться в качестве источников энтропии. Достаточно, чтобы как минимум один источник генерировал данные, кото­ рые не будут предсказуемыми для злоумышленника. Поскольку мы не зна­ ем, как именно будет действовать злоумышленник, имеет смысл превращать в источники энтропии все данные, которые будто бы не являются предска­ зуемыми. В частности, в качестве неплохих источников случайных данных можно порекомендовать время нажатия клавиш и время перемещения мы­ ши. Постарайтесь найти как можно больше временных источников энтропии. Вы можете использовать (желательно одновременно) точное время нажатия клавиш, перемещений и щелчков кнопкой мыши, а также откликов жестких дисков и принтеров. Не страшно, если злоумышленник сможет предсказать или скопировать данные из некоторых источников; достаточно, чтобы он не мог этого сделать для всех источников сразу.

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

Идентифицировать каждый источник мы будем с помощью его уникаль­ ного номера, находящегося в диапазоне от 0 до 255. Разработчики могут са­ ми решать, как выделять номера источников — статически или динамически. Данные каждого события представляют собой короткую последовательность байтов. Источники энтропии должны включать в себя только те данные со­ бытий, которые невозможно предсказать. Например, информация о времени может быть представлена двумя или четырьмя наименее значимыми байта­ ми точного таймера. Включать в эти данные год, месяц или число не имеет смысла — злоумышленник их и так знает.

Мы будем выполнять конкатенацию событий, собранных из различных ис­ точников. Чтобы гарантировать, что строка, полученная в результате подоб­ ной конкатенации, будет кодировать события уникальным образом, ее нужно жестко структурировать. Каждое событие кодируется тремя или более байта­ ми данных. Первый содержит номер источника случайных данных; второй — количество дополнительных байтов данных; следующие байты содержат дан­ ные, полученные от источника.

Разумеется, злоумышленник будет получать информацию о событиях, сгенерированных некоторыми источниками энтропии. Чтобы смоделировать подобную ситуацию, предположим, что некоторые источники находятся в пол-