Главная страница
Навигация по странице:

  • Почему это реализовано в ядре

  • Интерфейсы для ввода энтропии

  • Интерфейсы для вывода энтропии

  • Объединяем все вместе Опасность, связанная со сложностью алгоритмов

  • Таблица В.1.

  • Второе издание


    Скачать 3.09 Mb.
    НазваниеВторое издание
    Дата08.09.2019
    Размер3.09 Mb.
    Формат файлаpdf
    Имя файлаLav_Robert_Razrabotka_yadra_Linux_Litmir.net_264560_original_254.pdf
    ТипДокументы
    #86226
    страница51 из 53
    1   ...   45   46   47   48   49   50   51   52   53
    Принцип работы и реализация
    Компьютеры— это предсказуемые устройства. Действительно, трудно найти слу- чайное поведение в системе, поведение которой можно практически полностью программировать. Однако окружающая среда, где находится машина, полна различ- ных шумов, которые недетерминированы и которые можно измерить. Источники таких шумов включают моменты времени, в которые возникают события, связанные с аппаратными устройствами, а также события, связанные с взаимодействием поль- зователей и компьютера. Например, интервалы времени между нажатиями клавиш,
    перемещения мыши, интервалы времени между некоторыми типами прерываний и время выполнения запроса блочного ввода-вывода являются недетерминированны- ми, и, кроме того, их не может измерить внешний злоумышленник. Случайная ин- формация, которая получается из этих событий, записывается в пул энтропии. Пул растет и заполняется случайными и непредсказуемыми шумовыми данными. По мере добавления данных в пул вычисляется оценка энтропии, и итоговое значение запо- минается. Это позволяет всегда иметь информацию о значении энтропии в пуле. На рис. Б.1 показана диаграмма прохождения потока энтропии в пул и из пула.
    2
    Джон фон Нейман (28 декабря 1903-8 февраля 1957) работал в Институте специальных исследо- ваний в Принстоне (Institute for Advanced Study; Princeton). Он внес большой вклад в математиче- ские, экономические и компьютерные науки. Среди наиболее значительных его разработок- тео- рия игр, фон-неймановские алгебры и фон-неймановская проблема узких мест.
    424 Приложение Б

    Для доступа к пулу энтропии, как из пространства ядра, так и из пространства пользователя, ядро предоставляет набор интерфейсов. Когда выполняется обра- щение к этим интерфейсам, ядро вначале вычисляет хеш-значение SHA данных из пула. Алгоритм SHA (Secure Hash Algorithm, алгоритм вычисления безопасного хеш- значения) — это алгоритм вычисления дайджеста сообщения (профиля сообщения,
    message digest), который был разработан Агентством национальной безопасности
    (National Security Agency, NSA) и утвержден в качестве федерального стандарта США
    Национальным институтом стандартов и технологий (NIST) (федеральный стандарт по обработке информации, FIPS 186). Вычисление дайджеста сообщения выполняет- ся с помощью специального алгоритма, который принимает сообщение переменно- го размера (большое или маленькое) и выдает на выходе хеш-значение фиксирован- ного размера (обычно размером 128 или 160 байт). Это фиксированное значение и представляет собой дайджест. Входное сообщение не может быть реконструировано по его хеш-значению. Более того, простое изменение входного сообщения (напри- мер, изменение одного символа) приведет к радикальному изменению хеш-значения.
    Алгоритмы вычисления дайджестов сообщений могут использоваться по-разному,
    включая проверку подлинности данных и дактилоскопию. Другие алгоритмы вычис- ления дайджестов — это MD4 и MD5. Пользователю возвращается хеш-значение SHA
    пула, к содержимому пула энтропии непосредственно обращаться нельзя. Считается,
    что по хеш-значению невозможно получить никакую информацию о состоянии пула.
    Поэтому если известно несколько значений из пула, то это не дает никакой информа- ции о прошлых и будущих значениях. Ядро может использовать оценку энтропии и отказаться выполнить запрос на считывание данных из пула, если значение энтропии равно нулю. По мере того как из пула считываются данные, оценка энтропии умень- шается. Это реакция на то, что о пуле становится известно больше информации.
    <- Пространство ядра
    10110001-
    Ядро использует значения интервалов времени между успешными прерываниями для заполнения пула энтропии с помощью функции add_keyboard_random ness()
    1111010000->
    11100101100000110101 01111010101110100010 00100010110101011000
    Пул энтропии
    Пространство пользователя ->
    Приложения считывают информацию из пула через специальные файлы
    /dev/random и /dev/urandom
    Рис. Б.1. Прохождение энтропии через пул энтропии ядра
    Когда значение оценки энтропии достигает нуля, то ядро все равно может воз- вращать случайные числа. Однако в этом случае теоретически появляется возмож- ность того, что злоумышленник сможет предугадать результат вывода. Для этого тре- буются все результаты вывода из пула энтропии, а также чтобы злоумышленник смог
    Генератор случайных чисел ядра
    425
    При нажатии клавиш генерируются прерывания
    выполнить криптографический анализ алгоритма SHA. Так как алгоритм SHA счи- тается безопасным, то это невозможно. Для высоконадежной криптографии оценка энтропии позволяет гарантировать устойчивость случайных чисел. Для большинства пользователей такая дополнительная гарантия не нужна.
    Почему это реализовано в ядре?
    Критерием того, что какую-либо возможность необходимо реализовать в ядре, является слож- ность реализации этой возможности в пространстве пользователя. Недопустимо вводить что-либо в ядро только потому, что мы это можем сделать. Может показаться, что генерато- ру случайных чисел и пулу энтропии не место в ядре. Однако существует, по крайней мере,
    три причины, по которым они должны быть в ядре. Во первых, генератору необходим доступ к системным событиям, таким как прерывания и ввод данных пользователями. Для обеспечения доступа к информации об этих событиях из пространства пользователя необходимо экспорти- ровать специальные интерфейсы, чтобы информировать пространство пользователя о том, что эти события произошли. Даже если эти данные будут экспортироваться, то доступ к ним будет не простым и не быстрым. Во-вторых, генератор случайных чисел должен быть безопасным.
    Хотя такая система и может выполняться с правами пользователя root, тем не менее ядро явля- ется значительно более безопасным местом для пула энтропии. И наконец, самому ядру также необходимы случайные числа. Получать информацию о случайных числах, которая необходима ядру, из пространства пользователя — это не практично. В связи с этим генератор случайных чисел работает в ядре.
    Проблема с загрузкой системы
    Когда ядро загружается, оно выполняет последовательность действий, которые гарантированно можно предугадать. Следовательно, злоумышленник может предска- зать состояние пула энтропии на этапе загрузки. Еще хуже то, что каждая загрузка очень похожа на все остальные и пул инициализируется при каждой загрузке в очень близкие значения. Это уменьшает точность оценки энтропии, потому что нет ника- кого способа обеспечить, чтобы энтропия, которая добавляется на этапе загрузки,
    была менее предсказуема, чем энтропия, которая добавляется при такой же загрузке в другое время.
    Для решения проблемы большинство Linux-систем сохраняет на диске содер- жимое части пула энтропии между перегрузками системы. При старте системы со- храненные данные считываются и записываются в пул энтропии. Загрузка предыду- щего содержимого пула в текущий пул позволяет обойтись без увеличения оценки энтропии.
    Таким образом, злоумышленник не может предугадать состояние пула энтропии,
    не зная одновременно предыдущего и текущего состояний системы.
    Интерфейсы для ввода энтропии
    Ядро экспортирует следующее семейство интерфейсов, которые могут использо- ваться драйверами и системами для ввода данных в пул энтропии.
    void add_interrupt_randomness(int irq)
    void add_keyboard_randomness (unsigned char scancode)
    void add_mouse_randomness(__u32 mouse_data)
    426 Приложение Б

    Функция add_interrupt_randomness () вызывается системой обработки преры- ваний, когда приходит прерывание, обработчик которого зарегистрирован с флагом
    SA_SAMPLE_RANDOM. Параметр i r q — это номер прерывания. Генератор случайных чисел использует интервалы времени между прерываниями, как источник шума.
    Следует помнить, что не все устройства для этого подходят. Если устройства гене- рируют прерывания детерминированным образом (например, прерывания тайме- ра) или на них может воздействовать внешний злоумышленник (например, сетевые устройства), то такие устройства нельзя использовать для ввода информации в пул.
    Подходящее устройство — жесткий диск, который генерирует прерывания с непред- сказуемой частотой.
    Функция add_keyboard_randomness () использует скан-коды и интервалы вре- мени между нажатиями клавиш для ввода энтропии в пул. Интересно, что эта функ- ция достаточно интеллектуальна и игнорирует повторение символов при постоян- ном нажатии клавиши, потому что повторяющиеся скан-коды и интервалы времени вносят мало энтропии.
    Функция add_mouse_randoraness () использует позицию указателя мыши и интер- валы времени между прерываниями для заполнения пула. Параметр mouse_data —
    это позиция указателя, которая возвращается аппаратным обеспечением.
    Эти три функции добавляют передаваемые данные в пул энтропии, вычисляют оценку энтропии добавляемых данных и увеличивают оценку энтропии пула на вы- численное значение.
    Все эти экспортируемые интерфейсы используют внутреннюю функцию add_timer_randomness () для ввода данных в пул. Эта функция вычисляет интер- валы времени между успешными событиями одного типа и добавляет эти значения в пул. Например, интервалы времени между успешными прерываниями жесткого дис- ка достаточно случайны, особенно если измерять достаточно точно. Самые младшие биты — это обычно электрический шум. После того как эта функция вводит данные в пул, она вычисляет количественную характеристику того, насколько эти данные случайны. Это делается путем вычисления отклонения первого, второго и третье- го порядка от предыдущего момента времени и изменения этих отклонений перво- го, второго и третьего порядка. Наибольшее из этих отклонений, округленное до
    12 бит, используется в качестве оценки энтропии.
    Интерфейсы для вывода энтропии
    Для получения случайных чисел внутри ядра экспортируется один интерфейс.
    void get_random_bytes(void *buf, int nbytes)
    Эта функция сохраняет nbytes случайных байтов в буфере памяти, на который указывает параметр buf. Функция возвращает данные, даже если оценка энтропии равна нулю. Для ядра это не так критично, как для пользовательских криптографи- ческих программ. Случайные данные мало используются в ядре, в основном они нужны сетевой подсистеме для генерации стартового номера последовательности сегментов при соединении по протоколу TCP.
    Код ядра может выполнить следующий код для получения случайных данных раз- мером в одно машинное слово.
    Генератор случайных чисел ядра 427
    unsigned long rand;
    get_random_bytes(&rand, sizeof(rand));
    Для программ, которые выполняются в пространстве пользователя, предоставля- ется два символьных устройства: /dev/random и /dev/urandom. Первое устройство,
    /dev/random, используется, когда необходимы гарантированно случайные данные для криптографических приложений с высоким уровнем безопасности. Это устрой- ство выдает только то количество битов данных, которое соответствует оценке эн- тропии в ядре. Когда оценка энтропии становится равной нулю, операция чтения устройства /dev/random блокируется и не возвращает данные, пока значение эн- тропии не станет существенно положительным. Устройство /dev/urandom не имеет последней возможности, а в остальном работает аналогично. Оба устройства возвра- щают данные из одного и того же пула.
    Чтение из обоих файлов выполняется очень просто. Ниже показана функция пользовательской программы, которая служит для считывания одного машинного слова случайных данных.
    , i unsigned long get_random(void)
    (
    unsigned long seed = 0;
    int fd;
    fd = open("/dev/urandom", O_RDONLY);
    if (fd == -1) {
    perror("open");
    return 0;
    }
    if (read (fd, &seed, sizeof(seed)) < 0) {
    perror("read") ;
    seed = 0;
    }
    if (close(fd))
    perror("close");
    return seed;
    }
    Можно также считать $bytes байтов в файл $file, используя программу del.
    dd if=/dev/urandom of=$file count=l bs=$bytes
    428 Приложение Б

    в
    Сложность
    алгоритмов
    В
    компьютерных и связанных с ними дисциплинах полезно выражать сложность,
    или масштабируемость, алгоритмов с помощью количественных значащих ха- рактеристик (в отличие от менее наглядных характеристик, таких как быстрый или медленный). Существуют различные методы представления масштабируемости.
    Один из наиболее часто используемых подходов — это исследование асимптотиче- ского поведения алгоритмов. Асимптотическое поведение — это поведение алгоритма при достаточно больших значениях входных параметров или, другими словами, при
    стремлении входных параметров к бесконечности. Асимптотическое поведение пока- зывает, как масштабируется алгоритм, когда его входные параметры принимают все большие и большие значения. Исследование масштабируемости алгоритмов, т.е. из- учение свойств алгоритма при больших значениях входных параметров, позволяет смоделировать поведение алгоритма по отношению к тестовым задачам и лучше по- нять особенности этого поведения.
    Алгоритмы
    Алгоритм — это последовательность действий, возможно, с одним входом или более и, в конечном счете, с одним результатом или выходом. Например, подсчет количества людей в комнате представляет собой алгоритм, для которого люди, на- ходящиеся в комнате, являются входными данными, а количество людей в комнате —
    выходными данными. Операции замещения страниц в ядре Linux или планирование выполнения процессов — это тоже примеры алгоритмов. Математически алгоритм аналогичен функции (или, по крайней мере, может быть смоделирован с помощью функции). Например, если мы обозначим алгоритм подсчета людей в комнате бук- вой f, а количество людей, которых необходимо посчитать, буквой х, то функцию подсчета количества людей можно записать следующим образом.
    y=f(х)
    В этом выражении буквой у обозначено время подсчета количества людей в ком- нате.

    Множество О
    Это означает, что время вычисления функции f ( x ) всегда меньше времени вы- числения функции g (х), умноженного на некоторую константу, и это справедливо всегда, для всех значений х, больших некоторого начального значения х'.
    Другими словами, мы ищем функцию, которая ведет себя не лучше, чем наш алго- ритм в наихудшей ситуации. Можно посмотреть на результаты того, как ведет себя функция при очень больших значениях входных параметров, и понять, как ведет себя алгоритм.
    Множество большого-тета
    Когда говорят об обозначении большого-О, то чаще всего имеют в виду то, что
    Дональд Кнут (Donald Knulh) описывал с помощью обозначения "большого-тета".
    Обозначение "болыпого-О" соответствует верхней границе. Например, число 7 — это верхняя граница числа 6, кроме того, числа 9, 12 и 65— это тоже верхние границы числа 6. Когда рассматривают рост функции, то обычно наиболее интересна наимень-
    шая верхняя граница или функция, которая моделирует как верхнюю, так и нижнюю границу'. Профессор Кнут описывает это с помощью обозначения большого-тета следующим образом.
    Если f (х) принадлежит множеству большого-тета от g (x), то g(х) является одновременно и верхней и нижней границей f(х)
    Можно также сказать, что функция f (x) порядка функции g (х). Порядок, или множество "большого-тета" алгоритма, — один из наиболее важных математических инструментов изучения алгоритмов.
    Следовательно, когда говорят об обозначении большого-О, то чаще всего имеют в виду наименьший возможный вариант "большого-О" — "болыное-тета". Об этом не нужно особо волноваться, если, конечно, нет желания доставить удовольствие про- фессору Кнуту.
    1
    Если интересно, то нижняя граница описывается с помощью обозначения большого-омега.
    Определение аналогично определению множества большого-О, за исключением того, что значе- ния функции g ( s ) должны быть меньше значений функции f (х) или равны им.
    430 Приложение В
    Полезным обозначением асимптотического поведения функции является верхняя граница — функция, значения которой всегда больше значений изучаемой функции.
    Говорят, что верхняя граница некоторой функции растет быстрее, чем рассматрива- емая функция. Специальное обозначение "большого-О" используется для описания этого роста. Это записывается как f (х)
    О (g (х} ) и читается так: f принадлежит множеству "О-болыпого" от g. Формальное математическое определение имеет сле- дующий вид.
    Е с л и f ( x ) п р и н а д л е ж и т м н о ж е с т в у б о л ь ш о г о O ( g ( х ) ) , т о

    Объединяем все вместе
    Опасность, связанная
    со сложностью алгоритмов
    Очевидно, что будет разумным избегать алгоритмов, которые масштабируются,
    как О ( n ! ) или О(2
    n
    ) . Более того, замена алгоритма, который масштабируется, как
    О(n), алгоритмом, который масштабируется, как O(1), — это обычно серьезное улуч- шение. Тем не менее это не всегда так, и нельзя принимать решение вслепую, бази- руясь только на описании "болыпого-О". Вспомните, что в определении множества
    О ( g ( х ) ) фигурирует константа, на которую умножается значение функции g(х).
    Поэтому есть возможность, что алгоритм, который масштабируется, как O(1), будет выполняться в течение 3 часов. Следовательно, он будет выполняться всегда в те- чение 3 часов, независимо от количества входных данных, но это может оказаться дольше, по сравнению с алгоритмом, который масштабируется, как О ( n ) , при не- большом количестве входных данных. При сравнении алгоритмов необходимо всег- да принимать во внимание количество входных данных. Не стоит слепо оптимизи- ровать для некоторого случайно выбранного варианта.
    Сложность алгоритмов 431
    Вернемся снова к подсчету количества людей в комнате. Допустим, что можно считать по одному человеку за секунду. Следовательно, если в комнате находится 7
    человек, то подсчет займет 7 секунд. Очевидно, что если будет n человек, то подсчет всех займет n секунд. Поэтому можно сказать, что этот алгоритм масштабируется,
    как О(n). Что если задача будет состоять в том, чтобы станцевать перед всеми, кто находится в комнате? Поскольку, независимо от того, сколько человек будет в комна- те, это займет одно и то же время, значит, этот алгоритм масштабируется, как O(1).
    В табл. В.1 показаны другие часто встречающиеся характеристики сложности.
    Таблица В.1. Значения масштабируемости алгоритмов во времени
    O(g(x)) Название
    1
    log(n)
    n n
    2
    n
    3 2
    n n!
    Как масштабируется алгоритм представления всех людей в комнате друг другу?
    Какая функция может промоделировать этот алгоритм? Для представления одного человека необходимо 30 секунд, сколько времени займет представление 10 человек друг другу? Что будет в случае 100 человек?
    Постоянная (отличная масштабируемость)
    Логарифмическая
    Линейная
    Квадратичная
    Кубическая
    Показательная, или экспоненциальная (плохо)
    Факториал (очень плохо)

    1   ...   45   46   47   48   49   50   51   52   53


    написать администратору сайта