Быстрая схема аутентификации и обмена ключами, устойчивая к DDoS-атаке

  • Вид работы:
    Дипломная (ВКР)
  • Предмет:
    Информационное обеспечение, программирование
  • Язык:
    Русский
    ,
    Формат файла:
    MS Word
    505,89 Кб
  • Опубликовано:
    2012-07-10
Вы можете узнать стоимость помощи в написании студенческой работы.
Помощь в написании работы, которую точно примут!

Быстрая схема аутентификации и обмена ключами, устойчивая к DDoS-атаке

ДИПЛОМ

Быстрая схема аутентификации и обмена ключами, устойчивая к DDoS-атаке

СОДЕРЖАНИЕ

Введение

1       Цель и задачи

2       Краткий обзор предметной области

2.1    Классификация криптографических протоколов

2.2    Классификация алгоритмов шифрования

2.3    Понятие аутентификации

3       Поиск и сравнение аналогов

3.1    Yahalom

3.2    Needham-Schroeder

3.3    Kerberos

3.4    DASS

3.5    Woo-Lam

3.6    Таблица сравнения аналогов

4       Описание реализуемой схемы

5       Формирование требований к ПО

5.1    Общие сведения

5.2    Требования к серверу

5.3    Требования к клиенту

6       Технологическая платформа

6.1    MSVS 2008

6.2    C\C++

6.3    Assembler

6.4    OpenSSL

6.5    Описание используемых алгоритмов

7       Реализация и Руководство программиста

7.1    Генерация и хранение ключей

7.2    Реализация сервера

7.3    Реализация клиента

8       Исследование протокола

Библиография

Приложение А

Приложение Б

ВВЕДЕНИЕ

криптографический протокол аутентификация ключ атака

Развитие коммерческих приложений в Интернет сталкивается с постоянно появляющимися новыми видами угроз и атак. Одной из наиболее эффективных атак является распределённая атака, направленная на отказ в обслуживании (DDoS, Distributed Denial of Service). Суть этой атаки сводится к тому, что большое количество компьютеров, предоставленных хакерами, или исполняющих вредоносный код, внедрённый на компьютер с вирусами и «троянскими конями», пытаются одновременно установить множество соединений с атакуемым сервером, вызывая исчерпание ресурсов атакуемого сервера, в первую очередь, вычислительной мощности процессора и пропускной способности канала связи с Интернет. В Интернет существуют уже довольно большое количество сетей компьютеров-«зомби», на которые был внедрён код, позволяющий выполнять любые действия по команде владельца сети таких компьютеров («ботнет»). В результате DDoS-атаки добропорядочные пользователи не могут воспользоваться услугами, предоставляемые атакуемым сервером.  С помощью такой сети, например, была реализована атака на «Живой Журнал» весной-летом 2011 года, что в результате вызвало политический и общественный резонанс в России, помимо этого участившиеся сбои в работе «ЖЖ» побудили часть блоггеров завести аккаунты на других конкурирующих сервисах, в частности, сервисе микроблогов Twitter[9].

Для борьбы с различными видами атак из Интернет применяются межсетевые экраны (фильтры, брандмауэры, файерволы), обеспечивающие некоторую защиту от таких атак[3,4,5]. Однако, несмотря на прогресс в этом направлении, надёжного решения против, например, SYN-атаки до сих пор нет. Более того, DDoS-атака может быть осуществлена просто большим количеством одновременно устанавливаемых соединений, имитирующих соединения легальных пользователей, не обладающих признаками типовых видов атак и, таким образом, беспрепятственно проникающих через межсетевой экран. Этот вид атаки является наиболее сложным с точки зрения оказания противодействия. Наиболее распространённые схемы аутентификации и обмена сеансовыми ключами на основе асимметричной криптографии (с публичным ключом) не были рассчитаны на применение в условиях такой DDoS-атаки. Для противодействия данному виду DDoS-атаки и была разработана реализованная в данном проекте схема. Разумеется, она не отменяет необходимости использования традиционных межсетевых экранов.

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

1. ЦЕЛЬ И ЗАДАЧИ

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

Для достижения поставленной цели были сформулированы следующие задачи:

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

2.      Анализ существующих аналогичных протоколов. Будут изучены существующие аналоги с целью выявления различных достоинств и недостатков.

3.   Формирование требований к программной реализации схемы и выбор платформы разработки. В результате будут детально прояснены требования к разрабатываемой схеме и выбраны подходящие средства разработки.

.     Проектирование общей архитектуры проекта. В ходе проектирования архитектуры будет установлен набор приложений, на основе которых будет выполнено исследование предложенной в данной работе схемы.

5.      Реализация спроектированных приложений. В ходе реализации будет разработан проект, удовлетворяющий сформулированным ранее требованиям и на основе спроектированной ранее архитектуры.

.        Тестирование и отладка. В ходе тестирования будет проведена проверка разработанных приложений на правильность работы и соответствие установленным ранее требованиям, а в процессе отладки исправлены выявленные недостатки.

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

Все эти задачи более подробно будут рассмотрены в следующих главах.

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

2. КРАТКИЙ ОБЗОР ПРЕДМЕТНОЙ ОБЛАСТИ

2.1 Классификация криптографических протоколов


Криптографический протокол - это абстрактный или конкретный протокол, включающий набор криптографических алгоритмов. В основе протокола лежит набор правил, регламентирующих использование криптографических преобразований и алгоритмов в информационных процессах.

По способу организации все протоколы можно разделить на 3 типа:

1.         Протоколы с посредником.

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

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

Компьютерная сеть должна обеспечить поддержку посредника.

Существует задержка, присущая всем протоколам с посредником.

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

Так как каждый в сети должен доверять посреднику, то посредник представляет собой слабое место сети при попытке ее взлома.

Несмотря на это посредничество все еще активно используется.

2.         Арбитражные протоколы.

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

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

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

3.         Самодостаточные протоколы.

Самодостаточный протокол является лучшим типом протокола. Он полностью обеспечивает честность сторон. Для выполнения протокола не нужен ни посредник, не решающий споры арбитр . Само построение протокола обеспечивает отсутствие споров. Если одна из сторон попытается смошенничать, мошенничество будет немедленно обнаружено другой стороной, и протокол прекратит выполняться. Чего бы не пыталась добиться мошенничающая сторона, этому не суждено случиться.

По целевому назначению криптографические протоколы можно классифицировать следующим образом:

1.         Протоколы шифрования / расшифрования.

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

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

2.         Протоколы электронной цифровой подписи (ЭЦП).

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

3.         Протоколы идентификации / аутентификации.

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

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

Если в протоколе идентификации используется ЭЦП, то роль секретной информации играет секретный ключ ЭЦП, а проверка ЭЦП осуществляется с помощью открытого ключа ЭЦП, знание которого не позволяет определить соответствующий секретный ключ, но позволяет убедиться в том, что он известен автору ЭЦП.

4.         Протоколы аутентифицированного распределения ключей.

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

В данной работе будет рассмотрен самодостаточный протокол аутентификации и обмена ключами.

2.2 Классификация алгоритмов шифрования


Шифрование - способ преобразования открытой информации в закрытую, и обратно. Применяется для хранения важной информации в ненадёжных источниках или передачи её по незащищённым каналам связи. Шифрование подразделяется на процесс зашифровывания и расшифровывания.

В зависимости от структуры используемых ключей алгоритмы шифрования подразделяются на:

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

ЕК(М)=С

DK(C)=M

Симметричные алгоритмы делятся на две категории . Одни алгоритмы обрабатывают открытый текст побитно (иногда побайтно), они называются потоковыми алгоритмами или потоковыми шифрами. Другие работаю с группами битов открытого текста. Группы битов называются блоками, а алгоритмы - блочными алгоритмами или блочными шифрами. Для алгоритмов, используемых в компьютерных модемах, типичный размер блока составляет 64 бита - достаточно большое значение, чтобы помешать анализу, и достаточно небольшое и удобное для работы.

Примерами симметричных алгоритмов могут служить такие алгоритмы как AES - в настоящее время он является стандартом шифрования в США, ГОСТ 28147-89 - Российский стандарт, SEED - являющийся Корейским стандартом шифрования, и многие другие.

Алгоритмы с открытым ключом (называемые асимметричными алгоритмами) разработаны таким образом, что ключ, используемый для шифрования, отличается от ключа дешифрирования. Более того, ключ дешифрирования не может быть (по крайней мере в течение разумного интервала времени) рассчитан по ключу шифрования. Алгоритмы называются "с открытым ключом", потому что ключ шифрования может быть открытым: кто угодно может использовать ключ шифрования для шифрования сообщения, но только конкретный человек с соответствующим ключом дешифрирования может расшифровать сообщение. В этих системах ключ шифрования часто называется открытым ключом, а ключ дешифрирования - закрытым. Закрытый ключ иногда называется секретным ключом, но чтобы не было путаницы с симметричными алгоритмами, этот термин не используется в данной книге. Шифрование с открытым ключом К обозначается как:

ЕК(М)=С

Хотя открытый и закрытый ключи различны, дешифрирование с соответствующим закрытым ключом обозначается как:

DK(C)=M

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

ЕК(М)=С

DK(C)=M

Наиболее известные и широко используемые в современном мире примеры асимметричных схем шифрования: RSA(Rivest-Shamir-Adleman), DSA(Digital Signature Algorithm) , Diffie-Hellman(Обмен ключами Диффи - Хелмана).

В данной работе будут использованы как симметричный так и асимметричный способ шифрования.

2.3 Понятие аутентификации


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

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

В любой системе аутентификации обычно можно выделить несколько элементов:

·          субъект, который будет проходить процедуру аутентификации

·        характеристика субъекта - отличительная черта

·        хозяин системы аутентификации, несущий ответственность и контролирующий её работу

·        механизм аутентификации, то есть принцип работы системы

·        механизм предоставления доступа, предоставляющий или лишающий субъекта определенных прав доступа

Таблица 1.1 Пример использования элементов аутентификации

Элемент аутентификации

пищера 40 разбойников

Регистрация в системе

банкомат

Субъект

Человек, знающий пароль

Авторизованный пользователь

Владелец банковской карты

Характеристика

Пароль "Сезам, откройся!"

Секретный пароль

Банковская карта и персональный идентификатор

Хозяин системы

40 разбойников

Предприятие, которому принадлежит система

Банк

механизм аутентификации

Волшебное устройство, реагирующее на слова

Программное обеспечение, проверяющее пароль

Программное обеспечение, проверяющее карту и идентификатор

механизм предоставления доступа

Механизм, отодвигающий камень от входа в пещеру

Процесс регистрации, управления доступом

Разрешение на выполнение банковских операций

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

Простая аутентификация имеет следующий общий алгоритм:

1.      Субъект запрашивает доступ в систему и вводит личный идентификатор и пароль

2.      Введенные уникальные данные поступают на сервер аутентификации, где сравниваются с эталонными

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

Введенный субъектом пароль может передаваться как в открытом виде,  на основе протокола парольной аутентификации (Password Authentication Protocol, PAP), так и с использованием шифрования или однонаправленных хэш-функций. В этом случае уникальные данные, введённые субъектом, передаются по сети защищено.

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

Технологии использования одноразовых паролей можно разделить на:

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

2.      Использование временных меток вместе с системой единого времени

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

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

Во втором методе используются временные метки. В качестве примера такой технологии можно привести SecurID. Она основана на использовании аппаратных ключей и синхронизации по времени. Аутентификация основана на генерации случайных чисел через определенные временные интервалы. Уникальный секретный ключ хранится только в базе системы и в аппаратном устройстве субъекта. Когда субъект запрашивает доступ в систему, ему предлагается ввести PIN-код, а также случайно генерируемое число, отображаемого в этот момент на аппаратном устройстве. Система сопоставляет введенный PIN-код и секретный ключ субъекта из своей базы и генерирует случайное число, основываясь на параметрах секретного ключа из базы и текущего времени. Далее проверяется идентичность сгенерированного числа и числа, введённого субъектом.

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

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

Кроме двух приведенных ранее способов в последнее время всё чаще применяется, так называемая, расширенная или многофакторная аутентификация. Она построена на совместном использовании нескольких факторов аутентификации. Это значительно повышает защищенность системы.

В качестве примера можно привести использование SIM-карт в мобильных телефонах. Субъект вставляет аппаратно свою карту (устройство аутентификации) в телефон и при включении вводит свой PIN-код (пароль).

Также, к примеру, в некоторых современных ноутбуках присутствует сканер отпечатка пальца. Таким образом, при входе в систему субъект должен пройти эту процедуру (биометрика), а потом ввести пароль.

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

3. ПОИСК И СРАВНЕНИЕ АНАЛОГОВ

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

3.1 Yahalom


Первый, взятый для сравнения, протокол Yahalom [1,10] использует симметричный алгоритм шифрования и доверенный сервер.

В этом протоколе Алиса и Боб делят с Трентом секретный ключ и реализован он следующим образом:

1    Алиса объединяет свое имя и случайное число, и отправляет созданное сообщение Бобу.

 

A, NA

2    Боб объединяет имя Алисы, ее случайное число, свое случайное число, шифрует созданное сообщение общим с Трентом ключом и посылает его Тренту, добавляя свое имя:

, KВS(А, NA, NB)

3    Трент создает два сообщения. Первое включает имя Боба, случайный сеансовый ключ, случайные числа Боба и Алисы и шифруется ключом, общим для Трента и Алисы. Второе состоит из имени Алисы, ел у-
чайного сеансового ключа и шифруется ключом, общим для Трента и Боба. Трент посылает оба сообщения Алисе:

KАS(В, KАB, NA, NB), KВS(А, KАB)

4    Алиса расшифровывает первое сообщение, извлекает KАB и убеждается, что NA совпадает со значением, отправленным на этапе (1). Алиса посылает Бобу два сообщения. Одним является сообщение Трента, зашифрованное ключом Боба. Второе - это NB, зашифрованное сеансовым ключом.

ВS(А, KАB), KАB (NB),

5    Боб расшифровывает первое сообщение, извлекает KАB и убеждается, что NB совпадает с отправленным на этапе (2).

В результате Алиса и Боб убеждены, что они общаются именно друг с другом, а не с третьей стороной.

Рисунок 3.1 Протокол Yahalom.

Отличительной чертой данного протокола является то что именно первым Боб обращается к Тренту, который генерирует общий ключ для Боба и Алисы и отправляет сообщение Алисе. Разделяемым секретом является NB .

3.2 Needham-Schroeder

Следующим рассмотрим протокол Needham-Schroeder [1,10]. Данный протокол был предложен Роджером Неедхэмом и Майклом Шредером в 1978 году он также как и Yahalom использует криптографию с открытым ключом и  доверенный сервер.

1    Алиса посылает Тренту сообщение, содержащее ее имя, имя Боба и случайное число.

 

А, В, NA

2    Трент генерирует случайный сеансовый ключ. Он шифрует сообщение, содержащее случайный сеансовый ключ и имя Алисы, секретным ключом, общим для него и Боба. Затем он шифрует случайное число Алисы, имя Боба, ключ, и шифрованное сообщение секретным ключом, общим для него и Алисы. Наконец, он отправляет шифрованное сообщение Алисе:

AS (NA, В, KAB, KВS(KAB, А))

3    Алиса расшифровывает сообщение и извлекает KAB. Она убеждается, что NA совпадает со значением, отправленным Тренту на этапе (1). Затем она посылает Бобу сообщение, зашифрованное Трентом ключом Боба.

KВS(KAB, А)

4    Боб расшифровывает сообщение и извлекает KAB. Затем он генерирует другое случайное число, NB. Он шифрует это число ключом KAB и отправляет его Алисе.

KAB (RB)

5    Алиса расшифровывает сообщение с помощью ключа KAB. Она создает число NB-1 и шифрует это число ключом KAB. Затем она посылает это сообщение обратно Бобу.

KAB (NB-1)

6    Боб расшифровывает сообщение с помощью ключа KAB и проверяет значение NB-1.

7      

Рисунок 3.2 Протокол Needham-Schroeder

Главной прорехой этого протокола является важность использованных сеансовых ключей . Если Мэллори получит доступ к старому KAB, он сможет предпринять успешное вскрытие. Ему нужно только записать сообщения Алисы Бобу на этапе (3). Тогда, имея KAB, он может выдать себя за Алису.

3.3 Kerberos


Протокол Kerberos был развит как часть Проекта Афина в MIT в 1987 году и в настоящее время широко используется разными организациями. Данный протокол основан на протоколе Needham-Schroeder, но с добавлением временных меток в качестве случайных данных благодаря которым удалось сократить количество сообщений и устранить проблему описанную выше[1,10].

В базовом протоколе Kerberos Version 5 у Алисы и Боба общие ключи с Трентом. Алиса хочет генерировать сеансовый ключ для сеанса связи с Бобом.

1    Алиса посылает Тренту сообщение со своим именем и именем Боба:

 

А, В

2    Трент создает сообщение, состоящее из метки времени, время жизни, L, случайного сеансового ключа и имени Алисы. Он шифрует сообщение ключом, общим для него и Боба. Затем он объединяет метку времени, время жизни, сеансовый ключ, имя Боба, и шифрует полученное сообщение ключом, общим для него и Алисы. Оба шифрованных сообщения он отправляет Алисе.

А S ((TS, L, KА B, В), KВ S (TS , L, KА B , А))

3    Алиса создает сообщение, состоящее из ее имени и метки времени, шифрует его ключом KАB и отправляет Бобу. Алиса также посылает Бобу сообщение от Трента, шифрованное ключом Боба:

 

KА B (А, TA), K B S (TS, L, KА B, А)

4    Боб создает сообщение, состоящее из метки времени плюс единица, шифрует его ключом KА B и отправляет Алисе:

KА B (TA +1)

Рисунок 3.3 Протокол Kerberos

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

3.4 DASS


Протокол Распределенной службы безопасности и проверки подлинности (Distributed Authentication Security Service, DASS), созданный в Digital Equipment Corporation, также обеспечивает обоюдную проверку подлинности и обмен ключами[1]. В отличие от рассмотренных нами ранее протоколов DASS использует как криптографию с открытыми ключами, так и симметричную криптографию. И у Алисы, и у Боба есть свой закрытый ключ. Трент подписывает копии их открытых ключей.

1    Алиса посылает Тренту сообщение, состоящее из имени Боба.

 

В

2    Трент посылает Алисе открытый ключ Боба, Кв, подписанный закрытым ключом Трента, Т. Подписанное сообщение содержит имя Боба.

 

ST(B, Кв)

3    Алиса проверяет подпись Трента, убеждаясь, что она действительно получила открытый ключ Боба. Она генерирует случайный сеансовый ключ, К, и случайную пару ключей открытый/закрытый, Кр. Она шифрует метку времени ключом К, а затем подписывает время жизни, L, свое имя и своим закрытым ключом, КА. Наконец, она зашифровывает К открытым ключом Боба и подписывает его с помощью Кр. Все это она отправляет Бобу.

ЕКА), S Ka (L, а, кр), S KКв (К))

4    Боб посылает Тренту (это может быть другой Трент) сообщение, состоящее из имени Алисы.

А

5    Трент посылает Бобу открытый ключ Алисы, КА, подписанный закрытым ключом Трента. Подписанное сообщение содержит имя Алисы.

T(A, Ка)

6    Боб проверяет подпись Трента, убеждаясь, что он действительно получил открытый ключ Алисы. Затем он проверяет подпись Алисы и извлекает Кр. Боб использует свой закрытый ключ, извлекая К. Затем он расшифровывает ТА, проверяя, что это сообщение - текущее.

7       Если требуется обоюдная проверка подлинности, Боб шифрует новую метку времени ключом К и посылает ее Алисе.

Ек(Тв)

8    Алиса расшифровывает Тв ключом К, проверяя, что это сообщение - текущее.

Рисунок 3.4 протокол DASS

3.5 Woo-Lam


Последним рассмотренным протоколом будет Woo-Lam в этом протоколе используется криптография с открытыми ключами [1]:

1 Алиса посылает Тренту сообщение, состоящее из ее имени и имени Боба.

 

А, В

2 Трент посылает Алисе открытый ключ Боба, Кв, подписанный закрытым ключом Трента, Т.

 

ST(KB)

3 Алиса проверяет подпись Трента. Затем она посылает Бобу свое имя и случайное число, шифрованное открытым ключом Боба.

A, EB(RB)

4 Боб посылает Тренту свое имя, имя Алисы и случайное число Алисы, шифрованное открытым ключом Трента, Кт.

 

А, В, ЕКт (Ra)

5 Трент посылает Бобу открытый ключ Алисы, КА, подписанный закрытым ключом Трента. Он также посылает Бобу случайное число Алисы, случайный сеансовый ключ, имена Алисы и Боба, подписав все это закрытым ключом Трента и зашифровав открытым ключом Боба.

 

ST(KA), Ек  (St (Ra, К А, В))

6 Боб проверяет подписи Трента. Затем он посылает Алисе вторую часть сообщения Трента, полученного на этапе (5), и новое случайное число, зашифровав все открытым ключом Алисы.

 

EK  (ST(RA,K,A,B), RB)

7 Алиса проверяет подпись Трента и свое случайное число. Затем она посылает Бобу второе случайное число, шифрованное сеансовым ключом.

 

Ek(Rb)

8 Боб расшифровывает свое случайное число и проверяет, что оно не изменилось.

Рисунок 3.5 Woo-Lam

.6 Таблица сравнения аналогов

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

Таблица 3.1 - Сравнение характеристик протоколов аутентификации и обмена ключами

Характеристики для сравнения

Yahalom

Needham-Schroeder

Kerberos

DASS

Woo-Lam

Симметричная криптография

+

+

+

+

-

Ассиметричная криптография

-

-

-

+

+

Использование доверенного сервера

+

+

+

+

+

Использование временных меток

-

-

+

+

-

Использование случайных данных

+

+

-

-

+

Разделяемый секрет

+

-

-

-

-

Доказывает присутствие сторон

A&B

A&B

A&B

A&B

A&B

4. ОПИСАНИЕ РЕАЛИЗУЕМОЙ СХЕМЫ

Вся процедура аутентификации и обмена сеансовыми ключами в предлагаемой схеме состоит из отправки клиентом (C) серверу (S) одного-единственного пакета, составленного из четырех полей P1, P2, P3 и P4. После анализа этого пакета сервер либо принимает решение об установлении связи с клиентом, в случае положительной аутентификации, либо просто игнорирует данное соединение, не загружая свой канал связи лишним исходящим трафиком. Это делается возможным благодаря использованию возможности многозадачных операционных систем, применяемых на серверах, устанавливать различные приоритеты процессам, порождаемым для обслуживания запросов на установление соединений. При этом авторизованные соединения получают высокий уровень приоритета, а неавторизованные соединения имеют настолько низкий приоритет, что даже большое количество одновременно рассматриваемых запросов не может замедлить скорость обслуживания высокоприоритетных соединений. Большое количество ожидающих соединений вызывает только расход оперативной памяти, но с удешевлением микросхем оперативной памяти это не представляет проблемы.

C->S: P1=EPks(K1, K2, IDc); P2=EK1(E Skc(hash(P1))); =IDauthkey; P4=MACauthkey (P1, P2);>C: EK2(“Hello, client”, MAC K2 (“Hello, client”));

Поле P1 представляет собой два сеансовых ключа и идентификатор ключа клиента, зашифрованные на публичном ключе сервера Pks. Аутентификация сервера будет осуществлена тем фактом, что сервер смог расшифровать это поле на своём секретном ключе Sks, получить сеансовые ключи и ответить клиенту подтверждающим сообщением. Идентификатор ключа клиента IDc рекомендуется вычислять как хэш от соответствующего публичного ключа клиента, таким образом, совместить функции идентификатора клиента и «отпечатка» (fingerprint) публичного ключа с целью защиты от подмены идентификатора или открытого ключа. Поле P2 представляет собой цифровую подпись P1, вычисленную на секретном ключе клиента Skc. Аутентификация клиента осуществляется расшифровкой поля P2 на публичном ключе клиента Pkc, хранящемся на сервере в базе публичных ключей и их сертификатов, и сравнением полученного результата с вычисленным хэшем от поля P1. С целью защиты конфиденциальности клиента, это поле зашифровано на сеансовом ключе K1. Если бы это поле не было зашифровано, существовала бы возможность раскрыть инкогнито клиента, просто перебрав публичные ключи всех клиентов. Поля P3 и P4 предназначены для быстрой аутентификации сообщения, чтобы быстро различать пакеты, сформированные добропорядочными клиентами. Для этого клиенты в ходе своего предыдущего сеанса согласовывают с сервером ключ аутентификации сообщения authkey и соответствующий ему идентификатор IDauthkey. Они должны быть сформированы таким образом, чтобы используя IDaythkey, содержащийся в поле P3 в открытом виде, нельзя было определить authkey, идентификатор клиента, сеансовые ключи или какую-то другую информацию. Допустимо вычислять пару IDauthkey и authkey, например, как криптостойкий хэш от сеансовых ключей K1 и K2. Сервер и клиент запоминают пару (IDauthkey, authkey) с тем, чтобы использовать её при следующем сеансе связи. Если в поле P3 был указан правильный IDauthkey, сервер использует соответствующий ему authkey и вычисляет код аутентификации сообщения (Message Authentication Code, MAC). Если вычисленный код совпадает с указанным в поле P4, это означает, что данное сообщение было сформировано добропорядочным клиентом, следовательно, можно приступать к относительно трудоёмким вычислениям на секретном ключе с высоким приоритетом процесса. Поскольку код аутентификации сообщения не несет криптографической нагрузки, он не обязан вычисляться слишком стойким способом, важно, чтобы его вычисление осуществлялось быстрым алгоритмом, возможно, специально облегченным для этой цели. Стойкость MAC должна быть достаточна, чтобы атакующий, перехвативший пакет клиента, не мог вычислить authkey. Пара IDauthkey и authkey используется только один раз - при успешной проверке аутентификации сообщения эта пара удаляется и вместо неё генерируется новая пара, таким образом, предотвращая многократное использование каким-либо способом полученной от легального пользователя пары IDauthkey и authkey.

Атакующие не имеют ранее согласованной пары IDauthkey и authkey, следовательно, они не могут должным образом заполнить поля P3 и P4. Однако такой пары не имеют и клиенты, первый раз устанавливающие соединение с сервером, или по каким-либо причинам утратившие пару IDauthkey и authkey. Следовательно, им придётся устанавливать соединение с низким приоритетом, это может занять довольно много времени, в зависимости от наличия других соединений, осуществляемых с сервером в данный момент. Это очевидное неудобство предлагаемой схемы.

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

Предлагаемая схема позволяет создавать защиту от SYN-атаки, основанной на переполнении таблицы TCB (transmission control block)[6], возникающей при используемой атакующими тактики посылки многочисленных запросов на установление соединения с установленным флагом SYN[6]. Использование SYN-cookies также не является решением, поскольку, если алгоритм вычисления cookies либо является слабым, и его могут незамедлительно использовать атакующие, либо он является криптографически стойким, но тогда есть возможность перегрузить вычислениями сервер. Для борьбы против SYN-атаки можно применить технологию «обратного вызова» (callback). Эта технология использовалась, например, Интернет-провайдерами для дополнительной аутентификации клиентов.

Для защиты от SYN-атаки может использоваться следующая модификация предлагаемой схемы. Сервер вообще не имеет открытых портов TCP, запросы от клиентов он принимает по UDP. Клиент определяет номер порта, на котором он будет ожидать входящее соединения от сервера. Свой адрес и выбранный номер порта он сообщает серверу вместе со своим идентификатором и сеансовыми ключами в поле P1. Должным образом сформированное сообщение, содержащее поля P1, P2, P3 и P4, он посылает серверу по протоколу UDP. После проверки на основе (IDauthkey, authkey) сервер помещает пакет в очередь на обслуживание либо с высоким приоритетом, либо с низким, в зависимости от результата проверки. Сервер, расшифровав часть P1 сообщения, извлекает из нее IP-адрес клиента и номер порта, на котором клиент ожидает входящего соединения от сервера, и по которому сервер устанавливает соединение с клиентом по протоколу TCP, используя сеансовые ключи, переданные клиентом. Таким образом, сервер может просто игнорировать все входящие пакеты с флагом SYN [6], поскольку он таких пакетов вообще не ждёт. Практическому применению этой технологии несколько мешает широкое распространение «маскарада адресов», вызванного дефицитом адресного пространства IPv4, а также применение клиентами межсетевых экранов. Впрочем, в этом случае клиент должен использовать посредника (proxy), установленного на корпоративном межсетевом экране (firewall, брандмауэр), либо должным образом сконфигурированную политику безопасности на сетевом экране.

Для защиты от атаки с повтором трафика («replay-атака»), сервер может запоминает в своей базе данных все ранее использованные сеансовые ключи. Если при расшифровке поля P1 было обнаружено, что хотя бы один из ключей был ранее использован - такое сообщение отвергается и соединение не устанавливается. Либо это replay-атака, либо просто ключи были неудачно сформированы, впрочем, вероятность этого события при достаточной длине ключа пренебрежимо мала. Для защиты в случае возможной утечки информации из этой базы данных, сервер хранит не целые ключи K1 и K2, а только половину бит от них. Если бы сервер хранил у себя в базе данных все ранее использованные ключи целыми, то утечка информации из этой базы данных скомпрометировала бы все сеансы связи с данным сервером. Поскольку сервер хранит только половину ключа, то при соответствующем выборе длины ключа, утечка этих половинок никак не ослабила бы систему, но хранение только половины ключа делает маловероятным случайное совпадение двух половинок ключей. В настоящее время безопасной считается длина ключа 128 бит, следовательно, длину сеансовых ключей K1 и K2 следует выбрать по 256 бит, соответственно, вероятность случайного совпадения ключей составляет всего лишь 2-128.

Запоминание ключей в базе данных незначительно тормозит работу сервера, поскольку время поиска с включением в базу данных, построенную как АВЛ-дерево, растет всего лишь логарифмически с ростом размера базы данных [7]. Сам же размер базы данных тоже не является существенной трудностью, учитывая прогресс в увеличении ёмкости и производительности дисковых накопителей.

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

5. ФОРМИРОВАНИЕ ТРЕБОВАНИЙ К ПО

5.1 Общие сведения


Для решения основной задачи дипломного проекта которая заключалась в реализации и исследовании описанной в главе 4 схемы необходимо разработать клиент-серверное приложение с помощью которого можно было бы проверить как поведет себя протокол в реальных условиях. Для полноценного теста необходимо использовать вычисления с большими числами, симметричные и ассиметричные методы шифрования а также криптостойкую хеш функцию. В результате были разработаны клиент и сервер в полной мере реализующие данный протокол и взаимодействующие через стек протоколов TCP\IP. Как клиент так и сервер реализованы для операционной системы Windows XP. Далее в этой главе приведем основные задачи, которые должны реализовывать клиент и сервер. Подробное рассмотрение и реализация этих задач будет рассмотренная в следующих главах.

5.2 Требования к серверу


Серверная часть приложения должна реализовывать следующие задачи:

1    Принимать подключения от большого числа клиентов

2       Корректно осуществлять обработку любых принятых от клиента пакетов

3       Иметь набор криптографических функций необходимых для реализации протокола

4       Хранить свой секретных ключ, открытые ключи клиентов, ID и соответствующий ключ для предварительной аутентификации

5       Корректно измерять время работы протокола в различных условиях

6       Иметь механизм изменения приоритетов для различных нитей приложения

7       Обладать возможностью конфигурирования для создания различных условий работы в ходе тестирования протокола

8       Вести логирование различных событий, таких как возникновение исключительных ситуаций или результат работы протокола.

1.1     Требования к клиенту

Клиент должен выполнять следующие функции:

1    Устанавливать соединение с клиентом

2       Иметь набор криптографических функций необходимых для реализации протокола

3       Хранить свой секретных ключ, открытый ключ сервера, ID и соответствующий ключ для предварительной аутентификации

4       возможность конфигурирования для создания различных условий работы в ходе тестирования протокола

5       В зависимости от выбранной конфигурации реализовать общение с сервером как легальный или не легальный пользователь.

6. ТЕХНОЛОГИЧЕСКАЯ ПЛАТФОРМА

На основе предъявленных требований к приложению были выбраны следующие технологии реализации:

1    среда разработки MSVS (microsoft visual studio) 2008

2       языки программирования: С\С++, assembler(вставки)

3       криптографическая библиотека OpenSSL

6.1 MSVS 2008

Visual Studio - мощная интегрированная среда разработки, обеспечивающая высокое качество кода на протяжении всего цикла разработки ПО, от проектирования до внедрения[11]. Используемая в этой работе версия была выпущена в ноябре 2007 года и стала первой средой, включающей визуальный конструктор для Windows Presentation Foundation (WPF) с линиями привязки и вкладками событий, поддерживающими разработку в стиле RAD. ля многопрофильных рабочих групп система Visual Studio Team System обеспечивала повышенную масштабируемость, включая поддержку непрерывной интеграции.

Кроме того, она предоставила в распоряжение веб-разработчиков инструменты форматирования CSS, возможность программирования в среде ASP.NET AJAX, а также поддержку IntelliSense для JavaScript. Введение языка LINQ (Language Integrated Query) обеспечило новые расширенные методы работы с данными и их обработки в среде Visual Basic и C#. Для повышения производительности приложения Visual Studio 2008 предоставляла инструменты анализа программного кода, включая метрики кода, которые помогали выявлять неэффективные или другие проблемные участки кода. Интегрированная система сборки проекта включала поддержку многопоточности как для сборки, так и для отладки.

6.2 C\C++

Си - стандартизированный процедурный язык программирования, разработанный в начале 1970-х годов сотрудниками Bell Labs Кеном Томпсоном и Денисом Ритчи как развитие языка Би. Си был создан для использования в операционной системе UNIX. С тех пор он был портирован на многие другие операционные системы и стал одним из самых используемых языков программирования. Си ценят за его эффективность. Он является самым популярным языком для создания системного программного обеспечения. Его также часто используют для создания прикладных программ. Несмотря на то, что Си не разрабатывался для новичков, он активно используется для обучения программированию. В дальнейшем синтаксис языка Си стал основой для многих других языков[9].

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

В процессе своего развития язык Си лег в основу языка С++ но так как языки в последствии развивались независимо друг от друга в них стало появляться всё больше и больше несовместимостей.

C++ - компилируемый статически типизированный язык программирования общего назначения[9].

Данный язык поддерживает такие парадигмы программирования как процедурное программирование, модульность, раздельная компиляция, обработка исключений, абстракция данных, типы (объекты), виртуальные функции, объектно-ориентированное программирование, обобщенное программирование, контейнеры и алгоритмы, сочетает свойства как высокоуровневых, так и низкоуровневых языков. В сравнении с его предшественником - языком Cи, - наибольшее внимание уделено поддержке обобщённого и объектно-ориентированного программирования.++ является одним из самых популярных языков программирования и широко используется для разработки программного обеспечения. Область его применения включает создание операционных систем, разнообразных прикладных программ, драйверов устройств, приложений для встраиваемых систем, высокопроизводительных серверов, а также развлекательных приложений. Существует несколько реализаций языка C++ - как бесплатных, так и коммерческих.

6.3 Assembler


В данном проекте не будет использоваться непосредственно assembler, но будут использованы небольшие вставки. Приведем краткое описание этого языка для того что бы понять с чем имеем дело.

Assembler - машинно-ориентированный язык программирования низкого уровня с командами, обычно соответствующими командам машины [9]. Язык ассемблера позволяет программисту пользоваться алфавитными мнемоническими кодами операций, по своему усмотрению присваивать символические имена регистрам ЭВМ и памяти, а также задавать удобные для себя схемы адресации. Кроме того, он позволяет использовать различные системы счисления для представления числовых констант и даёт возможность помечать строки программы метками с символическими именами с тем, чтобы к ним можно было обращаться (по именам, а не по адресам) из других частей программы (например, для передачи управления).

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

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

6.4 OpenSSL

OpenSSL - криптографический пакет с открытым исходным кодом. Данное программное средство основано на библиотеке SSLeay, написанной Эриком Янгом (Eric A. Young) и Тимом Хадсоном (Tim Hudson)[9]. OpenSSL лицензируется по "двойной лицензии"  OpenSSL License и SSLeay License, и требует чтобы фраза "This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit. (<#"564522.files/image006.gif">, то дописывают только младшие биты. После этого длина потока станет кратной 512. Вычисления будут основываться на представлении этого потока данных в виде массива слов по 512 бит.

3       Для расчета цифровой подписи используется буфер на 4 слова (A,B,C,D). каждое из слов A, B, C, D представляет собой 32-битовый регистр. Этим регистрам задаются соответствующие начальные значения.

4       На данном этапе определяются 4 вспомогательные функции каждая из которых принимает три 32-битовых слова в качестве аргументов и возвращает одно 32-битовое слово.

F(X,Y,Z) = XY v not(X) Z(X,Y,Z) = XZ v Y not(Z)(X,Y,Z) = X xor Y xor Z(X,Y,Z) = Y xor (X v not(Z))

Определяется 64-элементная таблица T[1...64], построенная с использованием синусоидальной функции (sine function). Выровненные данные разбиваются на блоки (слова) по 32 бита, и каждый блок проходит 4 раунда из 16 операторов. Все операторы однотипны и имеют вид: [abcd k s i], определяемый как


где X - блок данных. X[k] = M [n * 16 + k], где k - номер 32-битного слова из n-го 512-битного блока сообщения, и  - циклический сдвиг влево на бит полученного 32-битного аргумента.

5    Сигнатура сообщения выводится как A, B, C, D (т. е., мы начинаем вывод с младшего байта A и закачиваем старшим байтом D).

Рисунок 6.1 Схема работы алгоритма MD5


6.5.2 AES

Advanced Encryption Standard (AES), также известный как Rijndael - симметричный алгоритм блочного шифрования с размером блока 128 бит, ключом 128/196/256 бит и количеством раундов 10, 12, или 14 в зависимости от длинны ключа. Оригинальный алгоритм Rijndael имеет возможность работать с более длинным блоком данных но эти модификации не вошли в стандарт AES. Данный алгоритм разработан бельгийскими криптографами В.Рейманом и Й. Даманом. В 2001 году AES был принят в качестве нового стандарта шифрования в США[9,14,15].

Блок входных и выходных данных состоит из 4 слов по 32 бита каждое, в свою очередь ключ состоит из 4, 6 или 8 слов.

Таблица 6.1 Стандартные комбинации длин ключа - блока - раундов


Длинна ключа (Nk слов)

Длинна блока (Nb слов)

Количество раундов

AES 128

4

4

10

AES 196

6

4

12

AES 256

8

4

14

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

Каждый раунд состоит из трех различных обратимых преобразований:

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

2       Нелинейный слой реализован с помощью S-блоков, имеющих оптимальную нелинейность, и предотвращает использование дифференциального, линейного и других методов криптоанализа.

3       Слой сложения с ключом на этом этапе выполняется непосредственно шифрование.

Ниже приведена реализация алгоритма на псевдокоде. В качестве входных параметров передается входной блок in и ключ w, на выходе мы получаем шифрованный блок out. В данном примере процедура AddRoundKey реализует слой сложения, SubBytes слой нелинейного преобразования, а ShiftRows и MixColumns реализуют смешивающий слой

Рисунок 6.2 Алгоритм шифрования AES на псевдокоде

.5.3 RSA

RSA - ассиметричный( с открытым ключом) алгоритм используемый для шифрования и для цифровой подписи сообщения был разработан Рональдом Ривестом, Ади Шамиром и Леонардом Адлеманом в в 1977 году. В настоящее время этот алгоритм широко распространен в различных криптографических приложениях[9].

В системе RSA используется два фактора[14]:

1    Задача проверки числа на простоту которая является относительно легкой

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

Для генерации ключей каждый абонент системы выбирает случайно два больших простых числа P и Q. Затем абонент вычисляет число

 

N=PQ

После этого вычисляется значение функции Эйлера от этого числа

 

f=(P-1)(Q-1)

и выбирается число d<f , взаимно простое с f, это число является открытой экспонентой. Далее вычисляется  число  c такое что

 

cd mod f = 1

Таким образом, пара чисел {d, N} является открытым ключом, а {с, N} секретным.

Протокол RSA можно описать следующим образом. Пусть Алиса хочет передать Бобу сообщение m такое что m<NB  для этого:

1    Алиса шифрует сообщение и передает его бобу

e=mDb mod NB

2    Боб получив сообщение вычисляет

’=eCb mod NB

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

 

y=h(m)

Далее Алиса вычисляет число s, сформированным подписанным сообщение будет являться пара чисел {m,s}

 

s=yCa mod NA

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

 

w=sDa mod NA

и проверить выполняется ли равенство w=h(m) . В том случае, если равенство верно, проверяющий может быть уверен, что подпись подлинная.

7. РЕАЛИЗАЦИЯ И РУКОВОДСТВО ПРОГРАММИСТА

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

 

7.1 Генерация и хранение ключей


В моем проекте за все криптографические функции отвечает библиотека OpenSSL разумеется и генерация ключей не исключение. Данная библиотека позволяет генерировать ключи, различной длинны, для системы RSA, а также имеет генератор псевдослучайных чисел, необходимый при генерации некоторых ключей.

7.1.1 Генерация ключей RSA

Из приведенного в главе 6 описания алгоритма RSA видно, что нет необходимости генерировать новые ключи при каждом его использовании, в связи с этим генерация ключей происходит отдельно от клиентской и серверной части проекта в специально созданной для этих целей программе регистраторе. Регистратор генерирует секретный и публичный ключи длиной 1024 бита и записывает их в файл, при этом секретный ключ дополнительно шифруется по алгоритму Blowfish в режиме 64 битной обратной связи по выходу(ofb) с кодовым словом “Hello”, а от открытого ключа берется хеш по алгоритму MD5. Ключи сохраняются в файлы privat.key, public.key, а так же в файл, именем которого является вычисленный хеш, записывается публичный ключ. Приведем примеры хранения открытого и секретного ключей в файлах

----BEGIN RSA PUBLIC KEY-----iXveg7xV3CR+TWkT/YQrftgxKkO3O0vIiKv59BZCoW0vvvmnUB7I1b+hSf4biUDKYacCRPuASh5s6I7M727sjpvuAqsAPYyExjRyBULVXm0GCZKpJsBmA2fDRBAHm/bAOXvR2hNkYWW7lLs1YcZJyQGPdrjNrAgMBAAE=

----END RSA PUBLIC KEY-----

-----BEGIN RSA PRIVATE KEY-----Type: 4,ENCRYPTEDInfo: BF-OFB,8ECB89E89B4AB034

pEeNkRcnJVBXFyWjRiwhfSLwzB/nFXHT0rP92u28N2gRkMqkT3D4PFAV3xqRH73f0jDRc481yEvQ/kmjgtX0La8z+7pAk4H1v3mkiuZHfWLq/1TjtQ3MAb8YQaOQJwJtmBz3+50mDWiEsaE3zVhHUDYWPDEU1SK5hYNjMHK3rFeGdW7iumjvoyHdNQVQWILyL8g4nyJoOp47D6rfrp+xEIYK7zOw9vBwdbaTUkqLnYEev7zBOVeuaDR/vWXJT89RN47VGU/5dHQc0ap0Q022ROBxn0U9jlZIBNFuG3wl

VZ2VO2OnmrZ0n/NWm3AP+CSEAclDod8K+DLFysKd/4ZPLGQiq+LKITNWTsEOr1bhQqNjExuROCTIGP1R/b5v2KeWKZ2r+q5mPUlOoOV8VqAGkuVvXIMkFBDe2A/xvjfxXkEYQFMb33wt2oYeBtVy8FIA/8Zf+p1oLrBB3t5SIQB/RMmK/lHwF+lrWu/r8hrw3bzUcCafb2+/xX4X9RLBLS9huY2sNjPJ3xk1Vqoq

Ul5osTDHr6NMAjJt7a82Z46CC9IpXJ5D/LdXSKzIK/7NXHbEbAeeb3p5oXWdEa8+fvUQ2fCmVDhT9f5GzDFRe6HyPdPS54kC432d/UKjkIDKqQsV87W7Mhl1QRJm

asNr8iJV2V3Bd4tZoXPAE0NOZc4Bel0a/ldAK75ZZ7mRS0lyBsqUDGkE3/eceOonFdWhpUJZVVAuhRk1r3g0y8L4sWj3a

----END RSA PRIVATE KEY-----

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

7.1.2 Генерация сессионных ключей

В отличии от ключей для системы RSA согласно условиям реализуемого протокола новые ключи должны формироваться при каждом подключении к серверу. Процесс формирования ключей реализован в клиентской части приложения. Для создания ключа с помощью библиотеки OpenSSL генерируется большое псевдослучайное число, а затем от этого числа вычисляется хеш MD5, в результате мы получаем 32 битный ключ после чего повторяем процедуру для получения второго ключа. Данные ключи хранятся как массив unsigned char в переменных session_key1 и session_key2.

7.1.3 Генерация ключей предварительной аутентификации

Согласно требованиям реализуемого протокола ключ предварительной аутентификации вычисляется, как  MD5 хеш от ключа сессии при этом хеш первого ключа сессии будет являться идентификатором ключа(IDauthkey), а хеш от второго ключа непосредственно самим ключом (authkey). На стороне клиента идентификатор и ключ хранятся в файлах auth.id и auth.key соответственно, а на стороне сервера ключ хранится в файле, названием которого является идентификатор ключа. На сервере данный ключ изначально отсутствует и генерируется аналогичным образом, но только в том случае если клиент успешно прошел полную аутентификацию, таким образом происходит согласование данных ключей между клиентом и сервером.

7.2 Реализация сервера


Сервер разработан для операционной системы Windows XP, с учётом требований рассматриваемого протокола. Все необходимые для работы приложения библиотеки включены в пакет установки приложения. Перед началом работы необходимо указать нужные параметры в файле конфигурации serv_ini, а также в случаи необходимости сгенерировать новые ключи

Основные функции сервера:

·          Настройка

·        Прием входящих подключений

·        Реализация протокола аутентификации

·        Измерение времени работы протокола

·        Общение с клиентом

·        Логирование

·        Подсчет обработанных подключений

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

Рисунок 7.1 Пример работы сервера

7.2.1 Настройка

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

Структура файла конфигурации serv_ini

·          Порт для приема входящих подключений

·          Задержка после приема подключения в миллисекундах

·        Задержка во время работы нити в миллисекундах.

·        Количество проходов алгоритма после которого будет высчитано среднее время работы

·        Время в миллисекундах превышение которого будет считаться не корректным

·        Количество сообщений которыми обменяется сервер и клиент перед разрывом соединения в случае успешной аутентификации.

·        Длина этих сообщений

·        Флаг использования задержки в нутрии нити (1 использовать)

·        Флаг определяющий будет ли в расчет включаться время генерации ключей предварительной аутентификации (1 включать)

·        Флаг отвечающий за общение с клиентом по мимо основного протокола, то есть за пересылку сообщений перед разрывом соединения в случае успешной аутентификации (1 разрешить)

·        Флаг определяющий будет ли использовать предварительная аутентификация (1 использовать)

7.2.2 Прием входящих подключений

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

7.2.3 Реализация протокола аутентификации

Реализации протокола происходит в нутрии нити. От клиента принимается некий пакет данных, затем этот пакет разбивается функцией split_pakage на 4 поля P1 P2 P3 P4, Эти поля представляют собой массив символов unsigned char. После разбиения пакета начинается процедура предварительной аутентификации. Функция get_authkey принимает на вход поле P3 и массив authkey, она извлекает ключ предварительной аутентификации и в случае успеха возвращает 0. Если ключ был успешно получен то в функцию pre_auth перадетются поля P1 P4 и ключ, эта функция шифрует поле P1 алгоритмом AES и сравнивает его с P4 если они равны возвращает 0, что означает об успешном прохождении предварительной аутентификации. В случае если неудалось извлеч ключ или предварительная аутентификация была не пройдена приоритет нити понижается в противном случае приоритет остается неизменным. Следующим шагом является расшифровка поля P1 алгоритмом RSA на SKS для этого оно передается в функцию do_decrypt также туда передается массив ptext в который будет записан расшифрованный текст. После расшифровки это поле разбивается на два сессионных ключа и id публичного ключа клиента функцией split_P1. Теперь когда нам известе id извлекаем ключ из файла функцией get_PKC на вход она принимает id а возвращет структуру RSA, в которой хранится публичный ключь клиента, либо NULL. В том случае если PKC не был получен сервер отказывает клиенту в аутентификации, вызывает функцию make_replay которая формирует соответсвующий ответ, а затем отправляет этот ответ клиенту и разрывает соединение. Если же PKC был получен корректно вычисляется MD5 хеш от поля P1, функцией do_DECRYPT_AES на первом ключе сессии расшифровывается поле P2, после чего хеш и расшифрованные данные передаются в функцию do_verify которая проверяет правильность подписи и в случае успеха возвращает 0. Если подпись оказалась подлинной то аутентификация считается успешной об этом функцией make_replay создается соответствующее сообщение, которое шифруется алгоритмом AES на втором ключе сессии, данное сообщение передается клиенту и функцией gen_authkey генерируются новый IDauthkey и authkey. После этого если небыл установлен флаг диалога соединение разрывается. Если же подпись оказалась фальшивой то опять же функцией make_replay формируется сообщение об этом и отправлется клиенту, после чего соединение разрывается.

7.2.4 Измерение времени работы протокола

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

unsigned __int64 rdtsc() {

         _asm{

                   rdtsc

         }

}

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

(t2-t1)/avgt*1000

где t2- значение счетчика в конце протокола t1 - в начале а avgt- среднее значение за секунду.

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

7.2.5 Общение с клиентом

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

7.2.6 Логирование

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

Система логирования разделена на две части. Первая часть отвечает за запись различных исключительных ситуаций, которые могут возникнуть в процессе работы сервера. Информация о них записывается в файл log_error.txt, запись содержит короткое пояснение и код ошибки.  Пример такой записи «WSAStart error 10048» данная запись говорит о том, что не удалось открыть заданный порт так как он уже используется, код ошибки сформирован функцией WSAGetLastError() библиотеки winsock полный список можно найти на официальном сайте[16].

Вторая часть отвечает за запись информации о времени работы протокола и расчет большой и малой средних. Малая средняя вычисляется как среднее время работы протокола за последние n раз, n указывается в файле конфигурации, большая средняя вычисляется из 10 малых. Данные о каждом проходе протокола записываются в файл log.txt в формате «результат аутентификации» «результат предварительной аутентификации» «количество подключенных клиентов на момент записи» «время работы протокола в миллисекундах». Данные о средних записываются в файл log_AVG.txt в формате «результат аутентификации» «результат предварительной аутентификации» «большая\малая средняя» «среднее значение времени в милисекундах». Примеры логов: «succeed 0 23 17.308069 ms»,  «failed SIGN 1 27 17.768198 ms» , «legal up client time avg=17.059146», «failed SIGN client time avg=17.355597».

7.3 Реализация клиента


Клиент также как и сервер реализован для операционной системы Windows XP и соответствует требованиям, предъявленным к протоколу. Все необходимые для работы приложения библиотеки включены в пакет установки приложения. Перед началом работы необходимо указать нужные параметры в файле конфигурации conin, а также в случаи необходимости сгенерировать новые ключи. Клиент реализует свою часть протокола и используется для моделирования действий легального пользователя, а так же для моделирования DDoS атаки.

Основные функции клиента:

·          Настройка

·        Подключение к серверу

·        Реализация протокола аутентификации

·        Общение с сервером

·        Имитация действий не легального пользователя

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

Рисунок 7.2 Пример работы клиента

7.3.1 Настройка

Как и серверная часть, клиент настраивается с помощью файла конфигурации conin. Функция client_ini() извлекает из него всю необходимую информацию.

Структура файла конфигурации:

·        Порт необходимый для подключения

·        IP-адрес сервера

·        Флаг, отвечающий за генерацию ключей предварительной аутентификации (0 генерировать)

·        Флаг, отвечающий за реализацию общения с сервером (0 разрешить общение)

·        Флаг DDoS клиента (1 переключает клиента в режим флуд атаки)

·        Задержка между сообщениями в процессе диалога в миллисекундах

·        Задержка перед повторением протокола в миллисекундах

7.3.2 Подключение к серверу

Новое подключение создается при каждом прохождении протокола с помощью функции Connect библиотеки winsock.h на основании параметров указанных в файле конфигурации, и разрывается после окончания работы протокола или в случае невозможности передать данные. В том случае, если по каким либо причинам не удалось подключиться к серверу, осуществляется еще 5 попыток подключения с задержкой в 2000 миллисекунд, если соединения установить так и не удалось, программа завершает свою работу.

7.3.3 Реализация протокола аутентификации

После успешного подключения начинается создание пакета для отправки серверу. Реализация протокола начинается с генерации двух ключей сессии функцией gen_session_key которая принимает на вход массив для храния ключа, сама процедура генерации была описана в разделе 7.1.2 ПЗ. Затем вычисляется MD5 хеш от публичного ключа клиента, который является идентификатором(IDc) клиента. Далее эти данные объединяются в массив ptext и передаются в функцию do_encrypt которая извлекает из файла публичный ключ сервера и шафрует на нем полученные данные с помощью алгоритма RSA после чего записывает зашифрованные данные в массив P1. После этого от поля P1 вычисляется хеш MD5 и передается в функцию do_sign которая подписывает его на секретном ключе клиента и записывает подпись в поле P2, затем это поле шифруется алгоритмом AES на первом ключе сессии функцией do_AES. Следующим шагом является извлечение из файлов ид и ключа предварительной аутентификации, а так же генерация нового ключа и идентификатора и замена их в файлах, за это отвечают функции get_IDauthkey, так же она заносить идентификатор в поле P3, и get_authkey. Затем поле P1 шифруется по алгоритму AES на ключе предварительной аутентификации с помощью функции do_AES, полученные данные заносятся в поле P4. Функция make_send_package объединяет все 4 поля и подготавливает их к отправке на сервер. После отправки данных клиент ожидает ответа от сервера если ответ не был получен то соединение разрывает и алгоритм повторяется заново, если ответ был получен то полученный пакет данных передается в функцию replay которая расшифровывает его и возвращает 1 если аутентификация прошла успешна.

На этом протокол аутентификации считается завершенным, соединение разрывается, и вся процедура вместе с установление нового подключения повторяется.

7.3.4 Общение с сервером

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

7.3.5 Имитация действий не легального пользователя

Для моделирования DDoS атаки нам необходимо реализовать протокол как со стороны легального, так и со стороны не легального пользователя.

Для реализации действий легального пользователя флаги DDoS клиента и генерации ключей предварительной аутентификации должны быть установлены на 0. Так же программе должны быть переданы легальные ключи системы RSA как клиента, так и сервера.

Действия «пхого» клиента реализуются двумя способами:

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

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

8. ИССЛЕДОВАНИЕ ПРОТОКОЛА

8.1 Тестирование протокола в различных условиях


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

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

Первый этап тестирования проводился на локальной машине с процессором DualCore AMD Athlon II X2 240, 2800 MHz (14 x 200) и памятью 3328 Мб (DDR2 SDRAM).

Тест № 1.

Целью данного теста является показать изменение времени работы протокола с увеличением числа подключаемых легальных пользователей. Тест начинается с подключения двух клиентов которые после прохождения процедуры аутентификации обмениваются с сервером сотней сообщений длинной 50 символов и подключаются заново после каждого сотого подключения добавлялось еще 2 клиента. Время потраченное на пересылку этих сообщений и на генерацию новых ключей предварительной аутентификации не учитывалось, для более наглядного сравнения со временем обработки нелегальных пользователей полученным в следующих тестах. На основании полученных логов сервера был составлен график изображенный на рисунке 8.1, использовались средние значения за 100 подключений. Всего в ходе теста было задействовано 26 клиентов и обработано 3000 подключений.

Рисунок 8.1 Тест №1 приоритет реального времени

Рисунок 8.2 Тест №1 повышенный приоритет

Библиография

1    Б.Шнаер. Прикладная криптография: Протоколы, алгоритмы, исходные тексты на языке Си. «Триумф», 2002.

2       A. Menezes, P. van Oorshort, S. Vanstone. Handbook of applied cryptography. CRCPress, 1996.

3       Дж. Скембрей, С. Мак-Клар, Дж. Курц. Секреты хакеров. Безопасность сетей - готовые решения. Второе издание. «Вильямс», 2001

         Дж. Вакка. Секреты безопасности в Internet. «Диалектика», 1997.

         В.М. Зима, А.А. Молдовян, Н.А. Молдовян. Безопасность глобальных сетевых технологий. БХВ-Петербург, 2000.

6       J.Postel. Transmission Control Protocol. RFC 793.

         Н.Вирт. Алгоритмы и структуры данных. "Мир", 1989

         Чмора А.Л. Современная прикладная криптография. 2-е изд., стер. - М.: Гелиос АРВ, 2002.

         Wikipedia, the free encyclopedia [Электронный ресурс]: Cвободная общедоступная многоязычная универсальная энциклопедия. - Режим доступа: http://ru.wikipedia.org/wiki/Main_Page.

10     M. Burrows, M. Abadi, R. Needham A Logic of Authentication // Research Report 39, Digital Equipment Corp. Systems Research Center - Feb. 1989

         Microsoft Visual Studio 2010 [Электронный ресурс]: Официальный сайт Visual Studio 2010. - Режимдоступа: http://microsoft.com/visualstudio/ru-ru.

         OpenSSL: The Open Source toolkit for SSL/TLS[Электронный ресурс]: Официальный сайт разработчиков библиотеки OpenSSL. - Режим доступа: http://openssl.org

         R. Rivest. The MD5 Message-Digest Algorithm. RFC 1321.

         Рябко Б. Я., Фионов А.Н. Основы современной криптографии для специалистов в информационных технологиях. - М.: Научный мир, 2004.

15     FIPS 197. The advanced encryption standart (AES)., 2001.

         MSDN Library [Электронный ресурс]: информация для разработчиков использующих продукты Microsoft - режим доступа : http://msdn.microsoft.com/en-us/library

ПРИЛОЖЕНИЕ А

Наиболее употребляемые текстовые сокращения

ВС - вычислительная система ПЗ - пояснительная записка АСУ - автоматизированная система управления ДП - дипломный проект ПЗ - пояснительная записка

СибГУТИ - Сибирский государственный университет телекоммуникаций и информатики

ПРИЛОЖЕНИЕ Б

Листинг исходного кода программного средства

// full_tcp_serv.cpp : Defines the entry point for the console application.

// server part

#include "stdafx.h"

#include <stdio.h>

#include <winsock.h>

#include <process.h>

#include <windows.h>

#include <openssl/rsa.h>

#include <openssl/pem.h>

#include <openssl/md5.h>

#include <openssl/rand.h>

#include <openssl/applink.c>

#include <stdlib.h>

#include <malloc.h>

#include <mbstring.h>

#include <iostream>

#pragma comment (lib,"libeay32")

#pragma comment (lib,"ssleay32")

#pragma comment (lib,"wsock32")

#define BUFSIZE 1024

#define BUFFSIZE (1025*16)

#define PRIVAT_SERVER_KEY "privat_server.key"

#define PUBLIC_SERVER_KEY "public_server.key"

#define PUBLIC_CLIENT_KEY "public_client.key"

#define password "hello"

#define KEYSIZE 32

#define RSA_key_size 128

#define _CRT_SECURE_NO_WARNINGS

_SECTION cs1;_SECTION cs2;_SECTION cs3;_SECTION cs4;

num_connect=0;_short PORT=3425;

*pub_serv;*priv_serv;*log,*log1,*log2;tik_per_second;config_param[10];config_flags[10];counter[8],savg[8];

__int64 rdtsc() {__rdtsc();

}

servini(){* pub_key_file = NULL;* priv_key_file = NULL;* ini;i=0;tmp[10];__int64 t1, t2;EVP_CIPHER *cipher = NULL;

_add_all_ciphers();= EVP_get_cipherbyname("bf-ofb");(GetCurrentProcess(), HIGH_PRIORITY_CLASS);_s(&ini,"serv_ini","r+");(ini,"%d",&PORT);(ini,"%d",&config_param[0]);(ini,"%d",&config_param[1]);(ini,"%d",&config_param[2]);(ini,"%d",&config_param[3]);(ini,"%d",&config_param[4]);(ini,"%d",&config_param[5]);(ini,"%d",&config_flags[0]);(ini,"%d",&config_flags[1]);(ini,"%d",&config_flags[2]);(ini,"%d",&config_flags[3]);(ini,"%d",&config_flags[4]);

(i<10){= rdtsc ();(1000);= rdtsc ();_per_second=t2-t1;(time>0){[i]=tik_per_second;++;

}

}_per_second=0;(int j=0;j<10;j++){_per_second+=tmp[j];

}_per_second/=10;("%f",tik_per_second);(int i=0; i<8; i++){[i]=0;[i]=0;

}((fopen_s(&log1,"log_error.txt", "w+"))!=0){(-1);

}((fopen_s(&log,"log.txt", "w+"))!=0){(log1,"error open log file");(-1);

}((fopen_s(&log2,"log_AVG.txt", "w+"))!=0){(log1,"error open AVG log file");(-1);

}((fopen_s(&pub_key_file,PUBLIC_SERVER_KEY, "rb"))!=0){(log1,"error open PUBLIC_SERVER_KEY");(-1);

}{_serv = PEM_read_RSAPublicKey(pub_key_file, NULL, NULL, NULL);

}((fopen_s(&priv_key_file,PRIVAT_SERVER_KEY, "rb"))!=0){(log1,"error open PRIVAT_SERVER_KEY");(-1);

}{_serv = PEM_read_RSAPrivateKey(priv_key_file, NULL, NULL, "hello");

}0;

}

md5(unsigned char *str, unsigned char *md_value, int strlen){_MD_CTX mdctx;EVP_MD * md;int md_len;_add_all_digests();= EVP_get_digestbyname("md5");_DigestInit(&mdctx, md);_DigestUpdate(&mdctx, str, strlen);_DigestFinal(&mdctx, md_value, &md_len);_MD_CTX_cleanup(&mdctx);1;

}

do_DECRYPT_AES(unsigned char *k, char *str, int strlen)

{outlen;char key[32]; /* 256- битный ключ */

unsigned char iv[8]; /* вектор инициализации */

unsigned char inbuf[BUFSIZE], outbuf[BUFSIZE];(int i=0; i<32; i++){[i]=k[i];

}(inbuf,str,strlen);_CIPHER_CTX ctx;EVP_CIPHER * cipher;_CIPHER_CTX_init(&ctx);= EVP_aes_256_cfb();_DecryptInit(&ctx, cipher, key, iv);_DecryptUpdate(&ctx, outbuf, &outlen,inbuf, strlen);(str,outbuf,strlen);_EncryptFinal(&ctx, outbuf, &outlen);_CIPHER_CTX_cleanup(&ctx);0;

}

do_AES(unsigned char *k, char *str, int strlen)

{outlen;char key[32]; /* 256- битный ключ */

unsigned char iv[8]; /* вектор инициализации */

unsigned char inbuf[BUFSIZE], outbuf[BUFSIZE];

(int i=0; i<32; i++){[i]=k[i];

}

(inbuf,str,strlen);_CIPHER_CTX ctx;EVP_CIPHER * cipher;_CIPHER_CTX_init(&ctx);= EVP_aes_256_cfb();_EncryptInit(&ctx, cipher, key, iv);_EncryptUpdate(&ctx, outbuf, &outlen, inbuf, strlen);(str,outbuf,strlen);_EncryptFinal(&ctx, outbuf, &outlen);_CIPHER_CTX_cleanup(&ctx);

1;

}

do_decrypt(unsigned char *ctext, unsigned char *ptext){outlen;key_size = RSA_size(priv_serv);= RSA_private_decrypt(key_size, ctext, ptext, priv_serv, RSA_PKCS1_PADDING);(outlen < 0){(log1,"error: do_decrypt failed;");

}0;

}

do_verify(unsigned char *m, unsigned int m_len, unsigned char *ctext, unsigned int key_size, RSA *pubKey){(RSA_verify(1,m,m_len,ctext,key_size,pubKey)==1){0;

}{1;

}

}

to_hex(unsigned char *str_dest, unsigned char *str_src, int sstr_len){tmp[4],buf1[RSA_key_size+1];

(int i=0; i<sstr_len; i+=2){(tmp,"%02x",str_src[i/2]);(&buf1[i],"%c",tmp[0]);(i+1<sstr_len)(&buf1[i+1],"%c",tmp[1]);

}(str_dest,buf1,sstr_len+1);0;

}

split_pakage(char *pakage, unsigned char *P1, unsigned char *P2, unsigned char *P3, unsigned char *P4){buf[RSA_key_size+1];buf2[KEYSIZE+1];count=0;(int i=0; i<RSA_key_size; i++){[i]=pakage[count];++;

}(P1,buf,RSA_key_size);(int i=0; i<RSA_key_size; i++){[i]=pakage[count];++;

}(P2,buf,RSA_key_size);(int i=0; i<KEYSIZE; i++){[i]=pakage[count];++;

}(P3,buf2,KEYSIZE);(int i=0; i<RSA_key_size; i++){[i]=pakage[count];++;

}(P4,buf,RSA_key_size);0;

}

make_replay(char *buff, int mode,unsigned char *k2){tmp[]="Hello,clien";tmp1[]="dialogstart";(mode==1){(buff,tmp,11);_AES(k2,tmp,11);(int i=0;i<11;i++){[i+11]=tmp[i];

}[23]='\0';1;

}(mode==0){="authentication failed";1;

}(mode==2){(buff,tmp1,11);_AES(k2,tmp1,11);(int i=0;i<11;i++){[i+11]=tmp1[i];

}[23]='\0';1;

}0;

}

split_P1(unsigned char *K1, unsigned char *K2, unsigned char *IDc, unsigned char *ptext){

(int i=0; i<KEYSIZE; i++){[i]=ptext[i];[i]=ptext[KEYSIZE+i];[i]=ptext[(KEYSIZE*2)+i];

}[KEYSIZE]=K2[KEYSIZE]=IDc[KEYSIZE]='\0';0;

}

get_authkey(unsigned char *IDauthkey, unsigned char *authkey){*f;buf[KEYSIZE+3]="1\\",tmp[33];(tmp,IDauthkey,32);[32]='\0';(int i=0; i<KEYSIZE;i++){[i+2]=tmp[i];

}((fopen_s(&f,buf,"r+"))==0){((fread(authkey,1,33,f))!=0){(f);::remove(buf);0;

}(f);1;

}1;

}

*get_PKC(unsigned char *IDc, RSA *pubKey){*pub_key_file;buf[33];(buf,IDc,32);[32]='\0';((fopen_s(&pub_key_file,buf, "rb"))==0){= PEM_read_RSAPublicKey(pub_key_file, NULL, NULL, NULL);(pub_key_file);pubKey;

}{(log1,"error: can not open PKC fail");

}

NULL;

}pre_auth(unsigned char *P1, unsigned char *P4, unsigned char *authkey){

buf[RSA_key_size+1];char tmp[RSA_key_size+1];(buf,P1,RSA_key_size);_AES(authkey,buf,RSA_key_size);(tmp,buf,RSA_key_size);[RSA_key_size]='\0';[RSA_key_size]='\0';((_mbscmp(P4,tmp))==0){0;

}1;

}

gen_authkey(unsigned char *k1, unsigned char *k2){

buf[KEYSIZE+1];tmp1[KEYSIZE+4]="1\\";char tmp[KEYSIZE+1];*f;(k1,tmp,KEYSIZE);_hex(tmp,tmp,KEYSIZE);(buf,tmp,KEYSIZE);[KEYSIZE]='\0';(int i=0; i<KEYSIZE;i++){[i+2]=buf[i];

}_s(&f,tmp1,"w+");(k2,tmp,KEYSIZE);_hex(tmp,tmp,KEYSIZE);(tmp,1,KEYSIZE+1,f);(f);0;

}

dialog(char *buf,int strlen, unsigned char *session_key){tmp[10];_DECRYPT_AES(session_key,buf,strlen);(int i=0; i<strlen; i++){

_itoa(i,tmp,10);[i]=tmp[0];

}_AES(session_key,buf,strlen);0;

}

__stdcall servprotocol( void* pArguments ){

*pubKey=NULL;buff[BUFSIZE],tmp1[10];char tmp[RSA_key_size+1];char authkey[KEYSIZE+1];char session_key1[KEYSIZE+1], session_key2[KEYSIZE+1], IDc[KEYSIZE+1], P1[RSA_key_size+1], P2[RSA_key_size+1], P3[KEYSIZE+1], P4[RSA_key_size+1];char ptext[RSA_key_size+1];byte_read, paflag=0,client_speak=0;;__int64 t1,t2;cur_tik,cur_time;

sock1=((SOCKET *) pArguments)[0];_PRIORITY_BELOW_NORMAL);((byte_read=recv(sock1, buff, 417,0))>0){(config_flags[0]==1)(config_param[1]);= rdtsc ();_pakage(buff,P1,P2,P3,P4);(config_flags[4]==1){(&cs3);((get_authkey(P3,authkey))==0){(&cs3);((pre_auth(P1,P4,authkey))==0){=0;

}

}{(&cs3);(GetCurrentThread(), THREAD_PRIORITY_LOWEST);=1;

}

}(config_flags[3]==1)(1);(&cs1);_decrypt(P1,ptext);(&cs1);_P1(session_key1, session_key2,IDc,ptext);(&cs2);=get_PKC(IDc,pubKey);(&cs2);(pubKey!=NULL){(P1,tmp,RSA_key_size);_hex(tmp,tmp,KEYSIZE);(buff,P2,RSA_key_size);_DECRYPT_AES(session_key1, buff, RSA_key_size);(P2, buff, RSA_key_size);[RSA_key_size+1]='\0';((do_verify(tmp,32,P2,RSA_key_size,pubKey))==0){(config_flags[1]==1 && config_flags[4]==1)_authkey(session_key1,session_key2);= rdtsc ();_tik=t2-t1;_time=cur_tik/tik_per_second*1000;(log,"\nsucceed %d %d %f ms\n",paflag,num_connect, cur_time);(config_flags[2]!=1){_replay(buff,1,session_key2);(sock1,buff,25,0);(config_flags[1]!=1 && config_flags[4]==1)_authkey(session_key1,session_key2);

}{_replay(buff,2,session_key2);(sock1,buff,25,0);(config_flags[1]!=1)_authkey(session_key1,session_key2);((byte_read=recv(sock1, buff, config_param[5],0))>0){(tmp1,buff,byte_read);(strcmp(tmp1,"ok")==0){(config_param[4],buff,10);_read=send(sock1,buff,config_param[4],0);_read=recv(sock1, buff, config_param[5],0);(config_param[5],buff,10);_read=send(sock1,buff,config_param[5],0);(client_speak<config_param[4]){((byte_read=recv(sock1, buff, config_param[5],0))>0){(buff,config_param[5],session_key2);(sock1,buff,config_param[5],0);_speak++;

}{_speak+=config_param[4];

}

}

}

}

}(closesocket(sock1)!=0){(log1,"close sock1 eror (succeed auth)");

}( &cs4 );(paflag==0){(cur_time<config_param[3])[0]+=cur_time;[0]++;(counter[0]>=config_param[2]){(log2,"\nlegal up client time avg=%f\n",savg[0]/counter[0]);[4]+=savg[0]/counter[0];[4]++;[0]=0;[0]=0;(counter[4]>10){(log2,"\n\nlegal up client time AVG= %f\n\n",savg[4]/counter[4]);[4]=0;[4]=0;

}

}

}(paflag==1){(cur_time<config_param[3])[1]+=cur_time;[1]++;(counter[1]>=config_param[2]){(log2,"\nlegal down client time avg=%f\n",savg[1]/counter[1]);[5]+=savg[1]/counter[1];[5]++;[1]=0;[1]=0;(counter[5]>10){(log2,"\n\nlegal down client time AVG= %f\n\n",savg[5]/counter[5]);[5]=0;[5]=0;

}

}

}_connect--;( &cs4 );

_endthreadex( 0 );0;

}{= rdtsc ();_tik=t2-t1;_time=cur_tik/tik_per_second*1000;(log,"\nfailed SIGN %d %d %f ms\n",paflag,num_connect, cur_time);_replay(buff,0,session_key2);(sock1,buff,22,0);(closesocket(sock1)!=0){(log1,"close sock1 eror (failed sign)");

}( &cs4 );(cur_time<config_param[3])[2]+=cur_time;[2]++;(counter[2]>=config_param[2]){(log2,"\nfailed SIGN client time avg=%f\n",savg[2]/counter[2]);[6]+=savg[2]/counter[2];[6]++;[2]=0;[2]=0;(counter[6]>10){(log2,"\n\nfailed SIGN client time AVG= %f\n\n",savg[6]/counter[6]);[6]=0;[6]=0;

}

}_connect--;( &cs4 );

_endthreadex( 0 );0;

}

}{= rdtsc ();_tik=t2-t1;_time=cur_tik/tik_per_second*1000;(log,"\nfailed PKC %d %d %f ms\n",paflag,num_connect, cur_time);_replay(buff,0,session_key2);(sock1,buff,22,0);(closesocket(sock1)!=0){(log1,"close sock1 eror (failed PKC)");

}( &cs4 );(cur_time<config_param[3])[3]+=cur_time;[3]++;(counter[3]>=config_param[3]){(log2,"\nfailed PKC client time avg=%f\n",savg[3]/counter[3]);[7]+=savg[3]/counter[3];[7]++;[3]=0;[3]=0;(counter[7]>10){(log2,"\n\nfailed PKC client time AVG=  %f\n\n",savg[7]/counter[7]);[7]=0;[7]=0;

}

}_connect--;( &cs4 );

_endthreadex( 0 );0;

}

}{(log1,"\nRECV from client failed\n sock1=%d\n",sock1);(closesocket(sock1)!=0){(log1,"\nclose sock1 eror (failed PKC)\n");

}( &cs4 );_connect--;( &cs4 );

_endthreadex( 0 );0;

}

}_tmain(void)

{client_sock, listener;sockaddr_in addr, client_addr;count=0;threadID;buf[1024];();( &cs1 );( &cs2 );( &cs3 );( &cs4 );( WSAStartup(0x202,(WSADATA*)&buf[0])){("WSAStart error %d\n", WSAGetLastError());(log,"WSAStart error %d\n", WSAGetLastError());-1;

}=socket(AF_INET, SOCK_STREAM, 0);(listener < 0){("WSAStart error %d\n", WSAGetLastError());(log1,"WSAStart error %d\n", WSAGetLastError());-1;

}.sin_family=AF_INET;.sin_port=htons(PORT);.sin_addr.s_addr=INADDR_ANY;(bind(listener, (struct sockaddr*)&addr, sizeof(addr))<0){("WSAStart error %d\n", WSAGetLastError());(log1,"WSAStart error %d\n", WSAGetLastError());-1;

}("bind OK\n");(listener, 0x100);

client_addr_size=sizeof(client_addr);

(client_sock=accept(listener, (sockaddr *)&client_addr, &client_addr_size)){++;("\nNEW CONNECTION %d\n",count);( &cs4 );_connect++;( &cs4 );

_beginthreadex( NULL, 0, &servprotocol, &client_sock, 0, &threadID );(config_param[0]);

}("\n\n\n\tSOCK ACCEPT ERROR!!!\n");(log1,"\n\n\n\tSOCK ACCEPT ERROR!!!\n");(30000);(client_sock);(listener);0;

}

// full_d_tcp_client.cpp : Defines the entry point for the console application.

// client part

#include "stdafx.h"

#include <stdio.h>

#include <winsock.h>

#include <openssl/rsa.h>

#include <openssl/pem.h>

#include <openssl/md5.h>

#include <openssl/rand.h>

#include <openssl/applink.c>

#include <stdlib.h>

#include<malloc.h>

#include <iostream>

#pragma comment (lib,"libeay32")

#pragma comment (lib,"ssleay32")

#pragma comment (lib,"wsock32");

#define BUFFSIZE (1025*16)

#define PRIVAT_CLIENT_KEY "privat_client.key"

#define PUBLIC_CLIENT_KEY "public_client.key"

#define PUBLIC_SERVER_KEY "public_server.key"

#define IDauthkey_file    "auth.id"

#define authkey_file      "auth.key"

#define password "hello"

#define KEYSIZE 32

#define RSA_key_size 128

PORT=3425;SERVERADDR[]="178.49.183.9";config_flags[10], config_param[10];

namespace std;

client_ini(){*ini=NULL;=fopen("conin","rb");(ini,"%d",&PORT);(ini,"%s",&SERVERADDR);(ini,"%d",&config_flags[0]);(ini,"%d",&config_flags[1]);(ini,"%d",&config_flags[2]);(ini,"%d",&config_param[0]);

0;

}md5(unsigned char *str, unsigned char *md_value, int strlen){_MD_CTX mdctx;EVP_MD * md;int md_len;

_add_all_digests();

= EVP_get_digestbyname("md5");_DigestInit(&mdctx, md);

_DigestUpdate(&mdctx, str, strlen);

_DigestFinal(&mdctx, md_value, &md_len);

_MD_CTX_cleanup(&mdctx);

1;

}

do_AES(unsigned char *k, char *str, int strlen)

{outlen;char key[32]; /* 256- битный ключ */

unsigned char iv[8]; /* вектор инициализации */

unsigned char inbuf[BUFSIZE], outbuf[BUFSIZE];

(int i=0; i<32; i++){[i]=k[i];

}

(inbuf,str,strlen);_CIPHER_CTX ctx;EVP_CIPHER * cipher;

_CIPHER_CTX_init(&ctx);

= EVP_aes_256_cfb();

_EncryptInit(&ctx, cipher, key, iv);

_EncryptUpdate(&ctx, outbuf, &outlen, inbuf, strlen);(str,outbuf,strlen);_EncryptFinal(&ctx, outbuf, &outlen);_CIPHER_CTX_cleanup(&ctx);

1;

}

md5_IDc(unsigned char *IDc){

EVP_MD_CTX mdctx; /* контекст для вычисления хэша */EVP_MD * md; /* структура с адресами функций алгоритма */

unsigned char md_value[EVP_MAX_MD_SIZE];

unsigned int md_len; /* размер вычисленного хэша */

int buf_len;*in;

=fopen(PUBLIC_CLIENT_KEY,"r");_add_all_digests();= EVP_get_digestbyname("md5");_DigestInit(&mdctx, md);

/* Вычисляем хэш */buf[BUFFSIZE];(;;) {long in_len = fread(buf,1,BUFFSIZE,in);(in_len <= 0) break;_len=in_len;_DigestUpdate(&mdctx, buf, (unsigned long)in_len);

}

_DigestFinal(&mdctx, md_value, &md_len);

_MD_CTX_cleanup(&mdctx);

tmp[4];tmp1[33];(int i = 0; i < md_len*2; i+=2){(tmp,"%02x",md_value[i/2]);(&tmp1[i],"%c",tmp[0]);(i+1<32)(&tmp1[i+1],"%c",tmp[1]);

}(IDc,tmp1,KEYSIZE+1);();1;

}to_hex(unsigned char *str_dest, unsigned char *str_src, int sstr_len){tmp[4],buf1[RSA_key_size+1];(int i=0; i<sstr_len; i+=2){(tmp,"%02x",str_src[i/2]);(&buf1[i],"%c",tmp[0]);(i+1<sstr_len)(&buf1[i+1],"%c",tmp[1]);

}

(str_dest,buf1,sstr_len+1);0;

}

gen_session_key(unsigned char *buff){

char buf[KEYSIZE+1],session_key[KEYSIZE+1];_bytes(buf,KEYSIZE);(buf,session_key,KEYSIZE+1);

_hex(buff,session_key, KEYSIZE);

1;

}

do_encrypt(unsigned char *ptext, unsigned char *ctext){* pubKey = NULL;outlen;* pub_key_file = NULL;

_key_file = fopen(PUBLIC_SERVER_KEY, "rb");= PEM_read_RSAPublicKey(pub_key_file, NULL, NULL, NULL);key_size = RSA_size(pubKey);

= RSA_public_encrypt(96, ptext, ctext, pubKey, RSA_PKCS1_PADDING);(outlen != RSA_size(pubKey)) exit(-1);

();0;

}

pre_rsa(unsigned char *k1, unsigned char *k2, unsigned char *IDc, unsigned char *ptext){

count=0;(int i=0; i<KEYSIZE; i++){[count]=k1[i];++;

}(int i=0; i<KEYSIZE; i++){[count]=k2[i];++;

}(int i=0; i<KEYSIZE; i++){[count]=IDc[i];++;

}0;

}

do_sign(unsigned char *m, unsigned int m_len, unsigned char *ctext, unsigned int key_size){*privKey = NULL;*priv_key_file;EVP_CIPHER *cipher = NULL;

_add_all_ciphers();= EVP_get_cipherbyname("bf-ofb");

_key_file = fopen(PRIVAT_CLIENT_KEY, "rb");= PEM_read_RSAPrivateKey(priv_key_file, NULL, NULL, "hello");

(RSA_sign(1,m,m_len,ctext,&key_size,privKey)==1){

}

0;

}

get_IDauthkey(unsigned char *IDauthkey, unsigned char *k1){*f;char buff[34];((f=fopen(IDauthkey_file,"r+"))!=NULL){(fread(IDauthkey,1,33,f)==0){(k1,IDauthkey,32);_hex(IDauthkey,IDauthkey,32);(IDauthkey,1,33,f);(f);1;

}{(f);(k1,buff,32);_hex(buff,buff,32);=fopen(IDauthkey_file,"w+");(buff,1,33,f);(f);0;

}

}{=fopen(IDauthkey_file,"w+");(k1,buff,32);_hex(buff,buff,32);(buff,1,32,f);(f);2;

}(-1);

}

get_authkey(unsigned char *authkey, unsigned char *k2){*f;char buff[34];((f=fopen(authkey_file,"r+"))!=NULL){(fread(authkey,1,33,f)==0){(k2,authkey,32);_hex(authkey,authkey,32);(authkey,1,33,f);(f);1;

}{(f);(k2,buff,32);_hex(buff,buff,32);=fopen(authkey_file,"w+");(buff,1,33,f);(f);0;

}

}{=fopen(authkey_file,"w+");(k2,buff,32);_hex(buff,buff,32);(buff,1,32,f);(f);2;

}(-1);

}

make_send_package(char *package,unsigned char *P1, unsigned char *P2, unsigned char *P3, unsigned char *P4){

buf[BUFSIZE];count=0;(buf,P1,128);(int i=0; i<RSA_key_size; i++){[count]=buf[i];++;

}(buf,P2,128);(int i=0; i<RSA_key_size; i++){[count]=buf[i];++;

}(buf,P3,32);(int i=0; i<KEYSIZE; i++){[count]=buf[i];++;

}(buf,P4,128);(int i=0; i<RSA_key_size; i++){[count]=buf[i];++;

}

0;

}

do_DECRYPT_AES(unsigned char *k, char *str, int strlen)

{outlen;char key[32];char iv[8];char inbuf[BUFSIZE], outbuf[BUFSIZE];(int i=0; i<32; i++){[i]=k[i];

}(inbuf,str,strlen);_CIPHER_CTX ctx;EVP_CIPHER * cipher;_CIPHER_CTX_init(&ctx);= EVP_aes_256_cfb();_DecryptInit(&ctx, cipher, key, iv);_DecryptUpdate(&ctx, outbuf, &outlen,inbuf, strlen);(str,outbuf,strlen);_EncryptFinal(&ctx, outbuf, &outlen);_CIPHER_CTX_cleanup(&ctx);0;

}

replay(char *str,char *buf, unsigned char *k2){tmp[BUFSIZE];(int i=0; i<11;i++){[i]=str[i+11];

}_DECRYPT_AES(k2,tmp,11);[11]='\0';(strcmp(tmp,buf)==0){1;

}0;

}

dialog(char *buf,int strlen, unsigned char *session_key){tmp[10];_DECRYPT_AES(session_key,buf,strlen);(int i=0; i<strlen; i++){

_itoa(i,tmp,10);[i]=tmp[0];

}_AES(session_key,buf,strlen);0;

}

_tmain(int argc, _TCHAR* argv[])

{sock;sockaddr_in addr;no_connect=0;buf[KEYSIZE+1],buff[BUFSIZE];char authkey[KEYSIZE+1];char session_key1[KEYSIZE+1], session_key2[KEYSIZE+1], IDc[KEYSIZE+1], P1[RSA_key_size+1], P2[RSA_key_size+1], P3[KEYSIZE+1], P4[RSA_key_size+1];char ptext[RSA_key_size+1];byte_read,wcount=0,wlen=0,countw=0;_ini();

( WSAStartup(0x202,(WSADATA*)&buff[0])){("WSAStart error %d\n", WSAGetLastError());-1;

}(1){=socket(AF_INET, SOCK_STREAM, 0);(sock < 0){("WSAStart error %d\n", WSAGetLastError());-1;

}

.sin_family=AF_INET;.sin_port=htons(PORT);(inet_addr(SERVERADDR)!=INADDR_NONE){.sin_addr.s_addr=inet_addr(SERVERADDR);

}{("\naddr err...\n");

}

(connect(sock, (struct sockaddr*)&addr, sizeof(addr))<0){("WSAStart error %d\n", WSAGetLastError());_connect++;("\nconnect error %d\n",no_connect);(2000);(no_connect>5){-1;

}

}

_session_key(session_key1);_session_key(session_key2);_IDc(IDc);_rsa(session_key1, session_key2, IDc, ptext);_encrypt(ptext,P1);char tmp[129];tmp2[129];(P1,tmp,128);_hex(tmp,tmp,KEYSIZE);_sign(tmp,32,P2,RSA_key_size);(tmp2,P2,128);_AES(session_key1,tmp2,128);(P2,tmp2,128);_IDauthkey(P3,session_key1);_authkey(authkey,session_key2);(tmp2,P1,128);(config_flags[0]==0)_AES(authkey,tmp2,128);(P4,tmp2,128);_send_package(buff,P1,P2,P3,P4);

((send(sock,buff,416,0))>0){("\n\n\nSEND OK!!!\n");(config_flags[2]!=1){((byte_read=recv(sock, buff, 25,0))>0){(buf,buff,12);[11]='\0';(replay(buff,buf,session_key2)==1){("\nauth OK\n");(strcmp(buf,"dialogstart")==0){(config_flags[1]==1){(sock,"no",3,0);

}{(sock,"ok",3,0);_read=recv(sock,buff,1000,0);=atoi(buff);_read=send(sock,buff,1,0);_read=recv(sock,buff,1000,0);=atoi(buff);(int i=0; i<wlen; i++){[i]='q';

}_AES(session_key2,buff,wlen);_read=send(sock,buff,wlen,0);(countw<wcount){((byte_read=recv(sock, buff, wlen,0))>0){(buff,wlen,session_key2);(sock,buff,wlen,0);++;("\nmessage %d of %d\n",countw,wcount);(config_param[0]);

}

}

}

}

}{("\nauth FAILED!\n");

}

}{

}

}

}{("\nSEND FAILED!!!\n");

}(sock);=0;(config_param[1]);

}

0;

}

Похожие работы на - Быстрая схема аутентификации и обмена ключами, устойчивая к DDoS-атаке

 

Не нашли материал для своей работы?
Поможем написать уникальную работу
Без плагиата!