Общие сведения об исходном коде (пример CNG)
В этих общих сведениях приведено высокоуровневое описание взаимодействия различных фрагментов кода в примере безопасного обмена данными с шифрованием CNG.
В разделе описаны следующие элементы примера.
Приложения
Файлы
Классы
Версии системы безопасности
Общие сведения о сеансах
Ключи шифрования (версии 2–5)
Обмен цифровыми подписями по открытому каналу (версия 3)
Обмен цифровыми подписями по закрытому каналу (версия 4)
Завершение сеанса (версия 5)
Дополнительные примечания
Ограничения примера CNG
Приложения
Пример состоит из трех отдельных консольных приложений: Alice, Bob и Mallory.Каждое приложение реализовано в виде отдельного проекта Visual Studio и состоит из главного файла и трех общих файлов.В следующей таблице перечислены приложения и относящиеся к ним файлы.
Имя приложения (проекта) |
Файлы |
---|---|
Alice |
|
Bob |
|
Mallory |
|
Файлы
В таблицах этого подраздела описаны классы и методы, которые используются каждым приложением, в порядке, определенном в исходном коде.
Alice.cs, Bob.cs и Mallory.cs
Класс, метод или имя глобальной переменной |
Использование |
---|---|
CNG_SecureCommunicationExample |
Разделяемый класс уровня всего проекта. |
MyColor OtherColor fDisplaySendMessage |
Глобальные переменные. |
Main |
Точка входа в программу для каждого из приложений.Этот метод выполняет следующие операции.
|
Run |
Метод, вызывающий метод InitializeOptions и создающий выбранный сценарий безопасности. |
Utilities.cs
Класс, метод или имя глобальной переменной |
Использование |
---|---|
CNG_SecureCommunicationExample |
Разделяемый класс уровня всего проекта. |
Version fVerbose fMallory |
Глобальные переменные. |
Autoloader |
Метод, который Алиса вызывает, чтобы загрузить приложения Bob.exe и Mallory.exe. |
InitConsole |
Метод, который отвечает за меню пользовательского интерфейса и сообщения уровня приложения. |
SplashScreen |
Метод, который создает заголовки окон консоли. |
ReadALine |
Служебный метод для чтения строки, которую пользователь вводит с консоли. |
ReadAChar |
Служебный метод для вывода на экран вопроса и приглашения ответить "Да" или "Нет". |
InitializeOptions |
Метод для отображения параметров и приглашения пользователю выбрать нужные значения.Этот метод также отвечает за установку глобальных флагов Version, fVerbose и fMallory. |
Display(string s) |
Первый из двух методов Display.Этот метод передает строку и переменную MyColor второму методу Display. |
Display(string DisplayString, int color) |
Второй из двух методов Display.Этот метод создает программу-оболочку для операторов Console.WriteLine и обеспечивает поддержку цвета выводимых строк. |
Дополнительные сведения об этих классах, методах и переменных см. в разделе Анализ кода классов Utility (пример CNG).
ChannelManager.cs
Класс, метод или имя глобальной переменной |
Описание |
---|---|
CNG_SecureCommunicationExample |
Разделяемый класс уровня всего проекта. |
AppControl |
Метод, отвечающий за управление внутренним приложением и синхронизацию трех консольных приложений. Алиса использует этот метод для отправки параметров программы (флагов Version и fVerbose) Бобу и Мэллори. Метод AppControl не служит для обмена сообщениями.Его содержимое не шифруется и не подписывается.Он не вызывает класс Communicator. |
SendChannelName ReceiveChannelName |
Методы, которые служат для переключения с именованного канала PublicChannel на именованные каналы AliceAndBobChannel и AliceAndBobChannel1.Именно благодаря этим методам в системе безопасности существует уязвимость, описанная в разделе Общие сведения о примере CNG. |
ChannelManager |
Класс, отвечающий за создание среды межпроцессного взаимодействия для приложения. |
Дополнительные сведения об этих классах и методах см. в разделе Анализ кода класса ChannelManager (пример CNG).
Communicator.cs
Класс, метод или имя глобальной переменной |
Описание |
---|---|
CNG_SecureCommunicationExample |
Разделяемый класс уровня всего проекта. |
Communicator |
Класс, инкапсулирующий все функции шифрования.Этот класс отвечает за обработку всех сообщений между Алисой, Бобом и Мэллори.Он не обрабатывает сообщения, отправляемые с помощью метода AppControl класса ChannelManager. |
m_DSKey m_ECDH_Cng m_ECDH_local_publicKey_XML m_ECDH_remote_publicKey ChMgr |
Переменные класса. |
Communicator |
Метод, создающий объект Communicator. |
Dispose |
Метод, высвобождающий занятые объектом ресурсы. |
StoreDSKey |
Метод для хранения ключа цифровой подписи. |
Send_or_Receive_PublicCryptoKey |
Метод, обеспечивающий поддержку обмена ключами. |
iv ciphertext signature |
Закрытые переменные класса, которые служат для шифрования сообщений с открытым текстом.Объявления этих переменных расположены рядом с методом ReceiveMessage(). |
ReceiveMessage |
Метод, получающий сообщения с открытым текстом или зашифрованные сообщения в зависимости от версии системы безопасности. |
SendMessage |
Метод, принимающий сообщение с открытым текстом и отправляющий его в формате открытого текста или в зашифрованном виде в зависимости от версии системы безопасности. |
Дополнительные сведения об этих классах, методах и переменных см. в разделе Анализ кода класса Communicator (пример CNG).
Классы
Каждый проект содержит три класса.
public partial class CNG_SecureCommunicationExample
Действие этого класса распространяется на все четыре проекта, входящих в приложения Алисы, Боба и Мэллори.После компиляции класс CNG_SecureCommunicationExample будет содержать все классы, переменные и методы файлов четырех проектов.Дополнительные сведения о разделяемых классах см. в разделе Разделяемые классы и методы (Руководство по программированию в C#).
internal sealed class ChannelManager
Этот класс обеспечивает работу именованных каналов.В каждом из проектов на различных этапах выполнения программы создается несколько экземпляров класса ChannelManager.Описание этого класса см. в разделе Анализ кода класса ChannelManager (пример CNG).
internal sealed class Communicator
Этот класс отвечает за функции шифрования и расшифровки.В каждом из проектов на различных этапах выполнения программы создается несколько экземпляров класса Communicator.Описание этого класса см. в разделе Анализ кода класса Communicator (пример CNG).
Версии системы безопасности
Исходный код поддерживает сценарий безопасности, описанный в разделе Общие сведения о примере CNG.В нем реализованы следующие пять версий, соответствующие пяти уровням безопасности средства обмена мгновенными сообщениями.
Версия 1. Использование сообщений с открытым текстом и именованных каналов.
Версия 2. Использование зашифрованных сообщений.
Версия 3. Использование зашифрованных сообщений и цифровых подписей.
Версия 4. Использование зашифрованных сообщений и закрытой цифровой подписи.
Версия 5. Завершение работы приложения при возникновении ошибок безопасности.
Примечание
Далее в этом разделе при упоминании различных версий указываются их номера.Кроме того, в зависимости от контекста имена Алиса (Alice), Боб (Bob) и Мэллори (Mallory) могут относиться к трем действующим лицам описываемого сценария или к трем приложениям Visual Studio.
Общие сведения о сеансах
В каждом из приложений Алисы, Боба и Мэллори имеются методы Main и Run.
Метод Main синхронизирует приложения и выполняет следующие функции.
Отображение экрана-заставки при запуске.
Вывод запроса пользователя с предложением выбрать параметры сеанса (только у Алисы).
Отправка параметров сеанса приложениям Боба и Мэллори (только у Алисы).
Получение параметров сеанса от Алисы (только у Боба и Мэллори).
Вызов метода Run для запуска запрашиваемого сеанса безопасности.
Метод Run выполняет сценарии безопасности.
Каждый сеанс соответствует одной из перечисленных в предыдущем подразделе версий.
Сеанс начинается, когда приложения Алисы, Боба и Мэллори запускают свои методы Run, и завершается, когда управление возвращается методам Main.
Во время сеанса приложения Алисы, Боба и Мэллори всегда выполняют одну и ту же версию сценария.
Алиса инициирует все происходящие во время сеанса транзакции.Мэллори отвечает Алисе и инициирует транзакции для Боба.Боб только отвечает.
Исходный код приложений Алисы и Боба очень похож.Основное различие состоит в том, что Алиса инициирует все сеансы и выступает в роли сервера канала, а Боб всегда выступает в роли клиента канала.Код Мэллори более сложный, поскольку он управляет двумя отдельными каналам: первый связывает его с Алисой, второй — с Бобом.
Метод Main
Приложение Алисы вызывает метод InitializeOptions в начале метода Main и получает у пользователя параметры сеанса (Version, fVerbose, fMallory).Затем с помощью метода AppControl эти параметры передаются Бобу и Мэллори, которые принимают их с помощью своих методов AppControl.Если пользователь принимает решение закрыть приложение, введя букву "x", вместо параметров сеанса метод AppControl Алисы отправляет Бобу и Мэллори строку "exit".
По получении параметров сеанса всеми тремя приложениями вызываются методы Run.
Метод Run
Чтобы запустить запрашиваемый сеанс, Алиса, Боб и Мэллори выполняют следующие действия.
Алиса вызывает метод SendChannelName, который использует канал с именем PublicChannel.Она отправляет Бобу имя нового канала (AliceAndBobChannel).
Если флаг fMallory имеет значение true, Мэллори прослушивает канал PublicChannel и перехватывает имя нового канала (AliceAndBobChannel), передаваемое Алисой.Затем он отправляет Бобу другое имя канала (AliceAndBobChannel1).
Алиса и Боб создают объекты Communicator, названные их именами.Эти объекты создаются внутри операторов using C# и удаляются по окончании работы метода Run.
Алиса инициализируется в качестве сервера канала:
using (Communicator Alice = new Communicator("server", NewChannelName))
Боб инициализируется в качестве клиента канала:
using (Communicator Bob = new Communicator("client", NewChannelName))
Мэллори создает два объекта Communicator: MalloryAlice и MalloryBob.Мэллори инициализируется в качестве клиента канала для Алисы:
using (Communicator MalloryAlice = new Communicator("client", AliceChannelName))
Мэллори инициализируется в качестве сервера канала для Боба:
using (Communicator MalloryBob = new Communicator("server", BobChannelName"))
Конструктор класса Communicator принимает имя канала и создает долгосрочный открытый объект ChannelManager с именем ChMgr:
ChMgr = new ChannelManager(mode, ChannelName);
Конструктор ChannelManager принимает имя канала и создает соответствующий именованный канал.
Примечание
На этом этапе Алиса и Мэллори взаимодействуют по каналу с именем AliceAndBobChannel, а Мэллори и Боб — по каналу с именем AliceAndBobChannel1.
AliceAndBobChannel и AliceAndBobChannel1 — это долгосрочные каналы, которые остаются открытыми до завершения сценария безопасности (т. е. до завершения метода Run).
Значения флага fVersion (который обозначает версию системы безопасности) и флага fMallory (который отвечает за участие Мэллори) определяют дальнейшее развитие событий.
В версии 3 Алиса по каналу PublicChannel отправляет Бобу ключ цифровой подписи.Они используют этот ключ цифровой подписи, чтобы подписывать ключи и сообщения.Если флаг fMallory имеет значение true, Мэллори перехватывает ключ цифровой подписи и использует его для подписывания ключей и сообщений, которые он отправляет Алисе и Бобу.
В версиях 4 и 5 Алиса отправляет Бобу два ключа цифровой подписи.Ключ цифровой подписи 1 — это тот же ключ, который Алиса отправляла в версии 3.Ключ цифровой подписи 2 — это секретный ключ цифровой подписи, о котором Мэллори не знает.
В версиях 2–5 Алиса и Боб обмениваются открытыми ключами шифрования.Если флаг fMallory имеет значение true, Мэллори перехватывает их открытые ключи и заменяет их своими ключами.
Алиса и Боб обмениваются сообщениями. Если флаг fMallory имеет значение true, Мэллори перехватывает, подменяет и заново отправляет сообщения Алисы и Боба.
Когда Алиса и Боб завершат обмен сообщениями, пользователь получит приглашение отправить собственное сообщение.Это позволит ему понять, как происходит шифрование сообщений и что делает Мэллори для их изменения.После этого нажмите клавишу ВВОД, чтобы вернуть управление Алисе.
Алиса завершает сеанс.Методы Run Алисы, Боба и Мэллори возвращают управление своим методам Main, и пример перезапускается.
Ключи шифрования (версии 2–5)
В версиях 2–5 сообщения шифруются с помощью алгоритма AES.Обмен ключами шифрования реализован в методах Run Алисы, Боба и Мэллори после следующего оператора:
if (2 <= Version)
Ключ шифрования отправляется долгосрочным открытым объектом ChannelManager (ChMgr), который создается конструктором класса Communicator.
В следующих двух операторах показано, как Алиса отправляет, а Боб принимает ключ шифрования:
Alice.Send_or_Receive_PublicCryptoKey("send", MyColor);
Bob.Send_or_Receive_PublicCryptoKey("receive", OtherColor);
Второй параметр определяет цвет, который должно использовать принимающее приложение при отображении содержимого ключа шифрования.
Считается, что реализации AES невозможно взломать математически.Однако они не обеспечивают защиты от атаки "злоумышленник в середине".Может показаться странным, что Мэллори может расшифровать сообщения Алисы и Боба, хотя алгоритм AES и обеспечивает такое надежное шифрование.Это становится возможным, потому что у Мэллори имеется общее секретное соглашение Алисы и Боба.Тот факт, что Мэллори может перехватывать и подменять сообщения, делает шифрование AES бессмысленным.
Использование ключей шифрования без проверки подлинности создает обманчивое впечатление защищенности.Алиса и Боб полагают, что при использовании версии 2 у них имеется безопасная система обмена сообщениями.Однако защита нарушается еще до того, как они отправят первое сообщение.
Компания Алисы и Боба не знает, где находится злоумышленник — внутри компании или за ее пределами.Она разрабатывает версию 3 средства обмена мгновенными сообщениями, чтобы обнаружить источник атак.
Обмен цифровыми подписями по открытому каналу (версия 3)
В версии 3 предпринимается попытка устранить уязвимость версии 2 за счет использования цифровой подписи для подписывания ключей и сообщений.Обмен ключами цифровых подписей реализован в методах Run Алисы, Боба и Мэллори после следующего оператора:
if (3 <= Version)
Ключ цифровой подписи передается по тому же долгосрочному открытому каналу, что и ключи шифрования.За передачу ключа цифровой подписи отвечает следующий код:
Alice.ChMgr.SendMessage(dsKeyBlob);
Примечание
Экземпляр ChannelManager (ChMgr), который отправляет ключ цифровой подписи, является членом объекта Communicator Алисы.
Алиса и Боб хранят ключ цифровой подписи в форме закрытого члена своих объектов Communicator:
Alice.StoreDSKey(DSKey);
Bob.StoreDSKey(DSKey);
К сожалению, Мэллори может легко скопировать цифровую подпись из канала PublicChannel и сохранить ее:
Mallory.StoreDSKey(DSKey);
Когда Алиса и Боб получают друг от друга подписанные сообщения, цифровые подписи в точности соответствуют сообщениям.Это связано с тем, что Мэллори подписывает их с помощью того же ключа цифровой подписи, что и Алиса с Бобом.
В версии 3 ключи шифрования и цифровая подпись передаются по открытому каналу в сети компании.Компания, в которой работают Алиса и Боб, подозревает, что злоумышленник находится внутри компании.Компания создает версию 4, чтобы проверить эту теорию.
Обмен цифровыми подписями по закрытому каналу (версия 4)
В версии 4 используется два ключа цифровой подписи: ключ, который использовался в версии 3, и второй, секретный ключ, который передается по закрытому каналу.Теперь первый ключ является поддельным цифровым ключом, который нужен, чтобы выследить вора.Второй ключ Алиса и Боб используют, чтобы подписывать свои ключи шифрования и сообщения.
Только Алиса и Боб имеют версию 4 программного обеспечения для обмена мгновенными сообщениями.Мэллори продолжает использовать версию 3.Поэтому Мэллори никогда не узнает, что цифровая подпись, которую он использует, недействительна.Однако средство обмена мгновенными сообщениями Алисы и Боба выводит предупреждение безопасности всякий раз при получении ключа или сообщения.
Версия 4 также демонстрирует, что перехватываются как ключи шифрования, так и сообщения.Это говорит о том, что имеет место атака "злоумышленник в середине" и что она началась еще до отправки ключа шифрования.Поэтому сотрудник компании, у которого есть доступ к каналу PublicChannel, должен входить в сеть до Боба.Правильное использование секретного ключа цифровой подписи позволяет выявить тайную деятельность Мэллори.
Передача секретного ключа цифровой подписи реализована в методах Run Алисы, Боба и Мэллори после следующего оператора:
if (4 <= Version)
Следующие операторы кода отвечают за создание закрытых экземпляров ChannelManager Алисы и Боба:
ChannelManager ChMgr2 = new ChannelManager("server", "PrivateChannel")
ChannelManager ChMgr2 = new ChannelManager("client", "PrivateChannel")
Закрытый канал, который используют Алиса и Боб (ChMgr2), не является членом их объектов Communicator.Это можно понять, сравнив следующие операторы:
Alice.ChMgr.SendMessage(dsKeyBlob); // Public channel - fake key
ChMgr2.SendMessage(dsKeyBlob); // Private channel - real key
В первом операторе используется долгосрочный экземпляр ChannelManager (ChMgr), который создается при запуске метода Run.Этот экземпляр хранится в виде открытого члена объектов Communicator Алисы, Боба и Мэллори (см. шаг 3 в разделе Общие сведения о сеансах) до конца сеанса.Во втором операторе используется временный объект, который существует только на время отправки и получения ключа.Этот объект удаляется сразу после использования.
После отправки секретного ключа цифровой подписи Алисой Боб получает его с помощью следующего оператора:
DSKey = ChMgr2.ReadMessage();
Алиса и Боб сохраняют ключ в виде закрытого члена своих объектов Communicator:
Alice.StoreDSKey(DSKey);
Bob.StoreDSKey(DSKey);
Кроме того, в результате выполнения этих операторов поддельный ключ цифровой подписи перезаписывается.
В версии 4 Алиса и Боб используют для подписывания ключей и сообщений секретный ключ цифровой подписи вместо поддельного ключа цифровой подписи.Кроме того, в версии 4 подписываются ключи шифрования и отображаются предупреждения безопасности, если цифровая подпись не соответствует сообщению.
Завершение сеанса (версия 5)
Версия 5 идентична версии 4, но в ней сеанс завершается при первой же ошибке.При получении от Боба открытого ключа шифрования Алиса обнаруживает недействительную цифровую подпись, и происходит первая ошибка.У Боба первая ошибка происходит, когда он получает от Алисы открытый ключ шифрования и также обнаруживает недействительную цифровую подпись.
Дополнительные примечания
Удаление объектов. Операторы using C# обеспечивают дополнительный уровень безопасности.В них заключаются все объекты ChannelManager и Communicator.Когда объекты оказываются за пределами области действия, сразу же вызываются их методы Dispose, и все занятые внутри этих объектов ресурсы, высвобождаются.
Методы кодирования. При передаче зашифрованных данных необходимо всегда использовать кодировку UTF8 или Unicode, но никогда не использовать кодировку ASCII.
Ограничения примера CNG
Пример безопасного обмена данными с шифрованием CNG предназначен для демонстрации возможностей CNG.Поэтому в примере не были реализованы некоторые функции, в том числе следующие.
Проверка параметров во всех методах.
Активное использование блоков try/catch.
Надежные методы выявления отключения каналов.
Вывод появляющейся на экране информации в файл журнала.
Динамическая настройка алгоритма шифрования.
Динамическая настройка алгоритма цифровой подписи.
Альтернативный способ передачи Бобу ключа цифровой подписи.Именованный канал PrivateChannel является простым решением, однако существует и другой, более изощренный метод.
Сохраняемость, хранение и извлечение ключей.
Использование ключей цифровой подписи, создаваемых операционной системой.
Использование ключей, полученных с помощью инфраструктуры открытого ключа (PKI).
Реализация этих функций потребовала бы усложнения кода и выходит за рамки данного примера.
См. также
Основные понятия
Пример защищенного обмена данными с шифрованием CNG
Пошаговое описание процесса обмена ключами и сообщениями (пример CNG)