Ремонт принтеров, сканнеров, факсов и остальной офисной техники


назад Оглавление вперед




[105]

Еще лучше рассматривать биты попарно . Если 2 бита одинаковы отбросьте их и взгляните на следующую пару. Если 2 бита различны, используйте первый бит в качестве выхода генератора . Это полностью устраняет смещение. Другие методы уменьшения смещения используют распределение переходов сжатие и быстрое пр е-образование Фурье [5ii].

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

Например, возьмите радиоактивный источник и присоедините счетчик Гейгера к вашему компьютеру . Возьмите пару шумящих диодов и записывайте в качестве события каждое превышение определенного значения . Измерьте атмосферный шум. Извлеките из каждого источника случайный бит и выполните их XOR друг с другом, получая случайный бит. Возможности бесконечны.

Одно то, что генератор случайных чисел смещен не обязательно означает его бесполезность . Это только означает, что он менее безопасен. Например, рассмотрим проблему Алисы, генерирующей 168-6итовый ключ для тройного DES. A все, что у нее есть, - это генератор случайных битов со смещением к 0 : с вероятностью 55 процентов он выдает нули и с вероятностью 45 процентов - единицы . Это означает, что энтропия на бит ключа с оставит только 0.99277 (для идеального генератора она равна i). Мэллори, пытаясь раскрыть ключ, может оптимизировать выполняемое вскрытие грубой силой, проверяя сначала наиболее вероятные ключи (000 . . . 0) и двигаясь к наименее вероятному ключу (iii . . . i). Из-за смещения Мэллори может ожидать, что ему удастся обнаружить ключ за 2i09 попыток. При отсутствии смещения Мэллори потребуется 2iii попыток. Полученный ключ менее безопасен, но это практически неощутимо .

Извлеченная случайность

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

-Копия каждого нажатия на клавиши

-Команды мыши

-Номер сектора, время дня и задержка поиска для каждой дисковой операции

-Действительное положение мыши

-Номер текущей строки развертки монитора

-Содержание действительно выводимого на экран изображения

-Содержание FAT-таблиц, таблиц ядра, и т.д.

-Времена доступа/изменения /dev/tty

-Загрузка процессора

-Времена поступления сетевых пакетов

-Выход микрофона

-/dev/audio без присоединенного микрофона

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

Так как случайность в этих событиях определяется синхронизацией осцилляторов, используйте часы с как можно меньшим квантом времени. В стандартном PC используется микросхема таймера Intel 8254 (или эквивалентная), работающая на тактовой частоте i.i93i8i8 МГц, поэтому непосредственное считывание регистра счетчика даст разрешение в 838 наносекунд. Чтобы избежать смещения результатов, не используйте в качестве источника событий прерывание таймера. Вот как выглядит этот процесс на языке C с MD5 (см. раздел i8.5) в качестве хэш-функции:

char Randpool[16];

/* Часто вызывается для широкого множества случайных или полуслучайных системных событий для to churn the randomness pool . Точный формат и длина randevent не имеет значения, пока его содержание


является в некоторой мере чем-то непредсказуемым. */

void churnrand(char *randevent,unsigned lnt randlen) { MD5 CTX md5; MD5Init(&md5);

MD5Update(&md5, Randpool , sizeof(Randpool)); MD5Update(&md5 , randevent , randlen ); MD5Final(Randpool,&md5);

После достаточных вызовов churnrand() накопления достаточной случайности в Randpool, можно генерировать из этого случайные биты. MD5 снова становится полезной, в этот раз в качестве генератора псевдослуча й-ного байтового потока, работающего в режиме счетчика.

long Randcnt;

void genrand(char *buf,unsigned int buflen) { MD5 CTX md5; char tmp[16]; unsigned int n; while(buflen != 0) {

/* Пул хэшируется счетчиком */

MD5Init(&md5);

MD5Update(&md5, Randpool, sizeof(Randpool)); MD5Update(&md5,(unsigned char *)&Randcnt,sizeof(Randcnt)); MD5Final(tmp,&md5);

Randcnt++; /* Инкрементируем счетчик */

/Копируем 16 или запрошенное число байтов, если оно меньше 16, в буфер пользователя*/

n = (buflen < 16) ? buflen : 16; memcpy(buf, tmp, n); buf += n ; buflen -= n;

По многим причинам хэш-функция имеет ключевое значение . Во первых она обеспечивает простой способ генерировать произвольное количество псевдослучайных данных , не вызывая всякий раз churnrand(). На деле, когда запас в накопителе подходит к концу, система постепенно переходит от совершенной случайности к пра к-тической. В этом случае становится теоретически возможным использовать результат вызова genrand() для определения предыдущего или последующего результата . Но для этого потребуется инвертировать MD5, что вычислительно невозможно.

Это важно, так как процедуре неизвестно, что делается потом со случайными данными, которые она возвр а-щает. Один вызов процедуры может генерировать случайное число для протокола, которое посылается в явном виде, возможно в ответ на прямой запрос взломщика . А следующий вызов может генерировать секретный ключ для совсем другого сеанса связи, в суть которого и хочет проникнуть взломщик . Очевидна важность того, чтобы взломщик не смог получить секретный ключ, используя подобную схему действий .

Но остается одна проблема. Прежде, чем в первый раз будет вызвана genrand() в массиве Randpool[] должно быть накоплено достаточно случайных данных . Если система какое-то время работала с локальным пользователем, что-то печатающим на клавиатуре, то проблем нет . Но как насчет независимой системы, которая перегр у-жается автоматически, не обращая внимания ни на какие данные клавиатуры или мыши ?

Но есть одна трудность. В качестве частичного решения можно потребовать, чтобы после самой первой з а-грузки оператор какое-то время поработал на клавиатуре и создал на диске стартовый файл перед выгрузкой операционной системы, чтобы в ходе перезагрузок использовались случайные данные, переданные в Randseed[]. Но не сохраняйте непосредственно сам Randseed[]. Взломщик, которому удастся заполучить этот файл, сможет определить все результаты genrand() после последнего обращения к churnrand() прежде, чем этот файл будет создан.

Решением этой проблемы является хэширование массива Randseed[] перед его сохранением, может даже вызовом genrandO. При перезагрузке системы вы считываете данные из стартового файла, передаете их


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



[стр.Начало] [стр.1] [стр.2] [стр.3] [стр.4] [стр.5] [стр.6] [стр.7] [стр.8] [стр.9] [стр.10] [стр.11] [стр.12] [стр.13] [стр.14] [стр.15] [стр.16] [стр.17] [стр.18] [стр.19] [стр.20] [стр.21] [стр.22] [стр.23] [стр.24] [стр.25] [стр.26] [стр.27] [стр.28] [стр.29] [стр.30] [стр.31] [стр.32] [стр.33] [стр.34] [стр.35] [стр.36] [стр.37] [стр.38] [стр.39] [стр.40] [стр.41] [стр.42] [стр.43] [стр.44] [стр.45] [стр.46] [стр.47] [стр.48] [стр.49] [стр.50] [стр.51] [стр.52] [стр.53] [стр.54] [стр.55] [стр.56] [стр.57] [стр.58] [стр.59] [стр.60] [стр.61] [стр.62] [стр.63] [стр.64] [стр.65] [стр.66] [стр.67] [стр.68] [стр.69] [стр.70] [стр.71] [стр.72] [стр.73] [стр.74] [стр.75] [стр.76] [стр.77] [стр.78] [стр.79] [стр.80] [стр.81] [стр.82] [стр.83] [стр.84] [стр.85] [стр.86] [стр.87] [стр.88] [стр.89] [стр.90] [стр.91] [стр.92] [стр.93] [стр.94] [стр.95] [стр.96] [стр.97] [стр.98] [стр.99] [стр.100] [стр.101] [стр.102] [стр.103] [стр.104] [стр.105] [стр.106] [стр.107] [стр.108] [стр.109] [стр.110] [стр.111] [стр.112] [стр.113] [стр.114] [стр.115] [стр.116] [стр.117] [стр.118] [стр.119] [стр.120] [стр.121] [стр.122] [стр.123] [стр.124] [стр.125] [стр.126] [стр.127] [стр.128] [стр.129] [стр.130] [стр.131] [стр.132] [стр.133] [стр.134] [стр.135] [стр.136] [стр.137] [стр.138] [стр.139] [стр.140] [стр.141] [стр.142] [стр.143] [стр.144] [стр.145] [стр.146] [стр.147] [стр.148] [стр.149] [стр.150] [стр.151] [стр.152] [стр.153] [стр.154] [стр.155] [стр.156] [стр.157] [стр.158] [стр.159] [стр.160] [стр.161] [стр.162] [стр.163] [стр.164] [стр.165] [стр.166] [стр.167] [стр.168] [стр.169] [стр.170] [стр.171] [стр.172] [стр.173] [стр.174] [стр.175] [стр.176] [стр.177] [стр.178] [стр.179] [стр.180] [стр.181] [стр.182] [стр.183] [стр.184] [стр.185] [стр.186] [стр.187] [стр.188] [стр.189] [стр.190] [стр.191] [стр.192] [стр.193] [стр.194] [стр.195] [стр.196] [стр.197] [стр.198] [стр.199] [стр.200] [стр.201] [стр.202] [стр.203]