Windows Crypto – время перемен
Aaloha, Guy! Думаешь, ты уже изучил Висту вдоль и поперек и
познакомился со всеми ее фишками? Не тут-то было. Пора копнуть глубже и
заглянуть ей под капот. Видишь во-о-он ту блестящую штуковину с
моторчиком? Нравится? А знаешь, что это такое? Нет? Ну тогда слушай и
запоминай.
Итак, на повестке дня - криптосистема Windows Vista.
Если тебе приходилось использовать криптографические возможности
более ранних версий Винды, ты должен знать, что доступ к этим
возможностям предоставляется системой CAPI (Crypto API).
Так вот Vista несет на своем борту новую, не столь убогую, как в
Windows XP, версию CAPI. Но как это дело не причесывай, конфетку из него
все равно не сделаешь. И в Microsoft это хорошо понимают. Нет, они не
переписали CAPI с нуля (на фига напрягаться), они просто засунули CAPI в дальний темный угол системы. Теперь за взаимодействие с CAPI отвечает красивая блестящая обертка под названием CNG. Но парни действительно старались, и обертка получилась не только красивой, но и весьма полезной. О том, какие
возможности перед тобой открывает система CNG, читай ниже.
Перечень изменений в криптографической системе выглядит следующим образом:
- Введен новый уровень абстракции, реализованный через CNG.
- CAPI сменил свою версию на 2.0 (при этом CAPI 1.0 никуда не исчез, поддержка его функций сохранена в полном объеме).
- .Net Framework теперь имеет в своем составе все необходимые интерфейсы, обеспечивающие взаимодействие CLR с криптографической подсистемой.
Согласись, перемены достаточно серьезные. И это я еще не упомянул о кардинальной перестройке архитектуры интерфейса PKI.
Следуя известной мудрости, гласящей о том, что «нельзя объять
необъятное», давай остановимся на центральной теме нововведений в
криптосистеме – на интерфейсе CNG, а все остальное пусть будет твоим домашним заданием :).
Итак, технология CNG (Cryptography Next Generation) пришла к нам всерьез и надолго, будучи призванной заменить устаревший CryptoAPI. Основной логической единицей как в CryptoAPI, так и в CNG является криптопримитив, то есть некоторая сущность, обеспечивающая выполнение одной специализированной операции. Если провести сравнение криптопримитивов, входящих в состав CryptoAPI и CNG, то можно сказать, что CNG в полном объеме включает в себя CryptoAPI плюс новые дополнительные возможности. Основу технологии составляют два элемента – NCrypt и BCrypt.
NCrypt отвечает за хранение ключей, используемых ассиметричными алгоритмами шифрования. Кроме того, NCrypt обеспечивает поддержку смарт-карт и прочего оборудования. А вот функции BCrypt гораздо шире и интереснее. Именно здесь находится все богатство криптографических примитивов, которыми располагает CNG. Эти примитивы могут быть использованы как в режиме ядра, так и в пользовательском режиме, в то время как хранилище ключей NCrypt доступно только из пользовательского режима.
CNG предоставляет специальный API для доступа к криптографическим возможностям Windows Vista.
Причем реализован этот доступ, в отличие от других аналогичных систем,
не в виде отдельных функций, а в виде набора интерфейсов криптоядра.
Набор логических криптоинтерфейсов представляет собой
криптомаршрутизатор. Посмотри на схему структуры CNG, чтобы получить представление о том, какие криптопримитивы в твоем распоряжении. Ну как, впечатляет?
Криптографические примитивы CNG
Допустим, ты решил написать супербезопасную программу,
предназначенную для работы под Windows Vista. Как при этом получить
доступ к криптографическим примитивам? Слушай сюда, и будет тебе
счастье.
Есть универсальный интерфейс CNG, который называется провайдером алгоритмов (Algorithm Provider). Для обращения к провайдеру алгоритмов существует дескриптор BCRYPT_HANDLE. Инициализация провайдера алгоритмов не представляет ничего сложного:
BCRYPT_HANDLE algorithmProvider = 0; NTSTATUS status = ::BCryptOpenAlgorithmProvider( &algorithmProvider, algorithmName, implementation, flags); if (NT_SUCCESS(status)) { // Используем CNG-примитивы
}
За управление инициализацией провайдера алгоритмов отвечает строка
«BCRYPT_HANDLE algorithmProvider = arg», где arg – это как раз и есть
параметр, управляющий процессом инициализации. В частности, если он
равен нулю, то по умолчанию будет использован криптоалгоритм,
определяемый параметром algorithmName.
Можно еще долго разглагольствовать на тему управления памятью. Но это
было бы уместно в «Мурзилке» или «Веселых картинках», но никак не в
журнале, который читают такие реальные перцы, как ты и наш редактор
Александр Лозовский (хе-хе, отлично я придумал, грубая лесть в адрес
читателей и редактора всегда благотворно сказывается на тиражах и
размере гонорара). Поэтому я просто ограничусь примером, иллюстрирующим
механизм завершения работы с провайдером:
status = ::BCryptCloseAlgorithmProvider( algorithmProvider, flags) ASSERT(NT_SUCCESS(status))
То есть мы передаем функции BCryptCloseAlgorithmProvider() ранее
созданный дескриптор провайдера алгоритмов и забываем о том, что у нас
вообще когда-то был такой объект.
Если ты будешь использовать CNG не в своих домашних
поделках или на уроках труда в средней школе, а в серьезном приложении,
тогда и в процесс создания, и в процесс уничтожения экземпляра
провайдера крайне необходимо добавить обработчик ошибок, реагирующий на
сигналы NT_SUCCESS.
CNG на практике
Прежде всего, если ты собрался использовать в своем проекте возможности CNG,
не забудь о заголовочном файле <bcrypt.h>, а также укажи линкеру,
что при сборке проекта понадобится библиотека bcrypt.dll. Большинство
функций, входящих в CNG, может генерировать различные
сообщения о текущем статусе. Для этого используется файл ntstatus.h,
следовательно, если тебе понадобится обработка этих сообщений, используй
вот такой макрос:
Шифруем данные:
BCryptOpenAlgorithmProvider(&hAlg,...) BCryptGetProperty(hAlg,BCRYPT_BLOCK_LENGTH,&dwBlockSize,...) BCryptGetProperty(hAlg,BCRYPT_OBJECT_LENGTH,&cbKeyObjectLen,...) BCryptGenerateSymmetricKey(hAlg,&hKey,...) BCryptEncrypt(hKey,...) BCryptDestroyKey(hKey) BcryptCloseAlgorithmProvider(hAlg,0)
Не все понятно? Ок. Давай разбираться, что тут написано. Первая
строка подключает и инициализирует провайдера криптоалгоритмов. Дальше с
помощью функции BCryptGetProperty() мы выделяем в буфере место под
размещение кодируемых данных и ключа, которым будет осуществляться
шифрование. После того как мы позаботимся о выделении памяти, можно
приступать непосредственно к шифрованию. Оно выполняется в два этапа:
сначала генерируем ключ симметричного шифрования –
BCryptGenerateSymmetricKey(), затем шифруем данные – BCryptEncrypt(). И
не забываем убирать за собой – BCryptDestroyKey(),
BCryptCloseAlgorithmProvider(). Наверняка, у кого-то из гиков, привыкших
к жесткому порно, точнее, к жесткой
оптимизации (вроде того нарисованного хрена, который считает себя другом
второго нарисованного хрена, более интеллигентного вида), возник вполне
резонный вопрос: почему мы пошли в обход, использовав
BCryptOpenAlgorithmProvider вместо обращения непосредственно к функциям
шифрования? Все дело в том, что обращение к кэшируемому объекту гораздо
эффективнее, чем непосредственный вызов функций шифрования. Кстати,
подобный подход использовался и раньше, например при обращении к
функциям
CAPI.
Так же просто с помощью CNG можно получить и хэш-функцию объекта:
BCryptOpenAlgorithmProvider(&hAlg,...) BCryptGetProperty(hAlg,BCRYPT_OBJECT_LENGTH,&cbHash,...) BCryptCreateHash(hAlg,&hHash,...) BCryptHashData(hHash,...) BCryptFinishHash(hHash,...) BCryptDestroyHash(hHash) BСryptCloseAlgorithmProvider(hAlg,0)
По аналогии с предыдущим примером перво-наперво необходимо
позаботиться о выделении адресного пространства для работы с объектами.
За работу с хэш-функциями отвечают методы BCryptCreateHash(),
BCryptHashData() и BCryptFinishHash(). Ну и, как обычно, завершаем все
уничтожением ненужных более объектов и ссылок: BСryptDestroyHash() и
BCryptCloseAlgorithmProvider().
Идем дальше. Если ты не знаешь, что такое MAC, – бегом учить матчасть. И не спеши возмущенно заявлять, что о
Media Access Control знают даже первоклассники. MAC - это еще и Message Authentification Code, то есть одна из реализаций технологии
цифровой подписи. Создание MAC
аналогично расчету хэш-функции, за исключением двух моментов. Во-первых,
при вызове BCryptOpenAlgorithmProvider последним из передаваемых
функции параметров должен быть BCRYTP_ALG_HANDLE_HMAC_FLAG. Во-вторых,
дополнительно нужно указать секретный
MAC-ключ и его размер. Таким образом, вызов функции будет похож на тот, что приведен ниже:
BCRYPT_ALG_HANDLE hAlg = NULL; NTSTATUS status = STATUS_UNSUCCESSFUL; status = BCryptOpenAlgorithmProvider(&hAlg, GetPreferredHmacAlg(), NULL, BCRYPT_ALG_HANDLE_HMAC_FLAG)))
Но известная фирма на букву М не была бы сама собой, если бы все было
прозрачно, ясно и понятно. Видишь функцию GetPreferredHmacAlg()? Так
вот эта функция не является частью библиотеки
CNG, как логично было бы предположить. Ее реализация
отдается на откуп программисту, который сам должен решить, в
соответствии с каким алгоритмом будет рассчитываться
MAC. А ты как хотел: понавызывал кучу API-функций и
айда на печку сметану есть? Нет, иногда еще и думать приходится. Такие
вот дела, брат.
Ну и, наконец, такая полезная возможность, предоставляемая CNG, как генерация случайных чисел. С этой задачей справится даже стая леммингов, добравшаяся до клавиатуры:
BCRYPT_ALG_HANDLE hRngAlg = NULL; if (BCryptOpenAlgorithmProvider(&hRngAlg, BCRYPT_RNG_ALGORITHM, NULL, 0) == STATUS_SUCCESS) { BYTE buf[32]; if (BCryptGenRandom(hRngAlg, buf, sizeof buf, 0) == STATUS_SUCCESS) { } BCryptCloseAlgorithmProvider(hRngAlg,0); hRngAlg = NULL; }
Полный список функций CNG API ты можешь найти в документации, которой комплектуется
CNG SDK, или же на сайте MSDN. Кроме того, на диске, идущем в комплекте с журналом, мы выложили подборку примеров использования
CNG. Так что, если какие-то моменты тебе не особо понятны, смотри исходники.
И несколько слов о собственно использовании CNG.
Прежде всего, это технология, тесно завязанная на криптофункциях Висты.
Следовательно, не рассчитывай на то, что тебе удастся поюзать
CNG, к примеру, в Windows XP. Для разработки приложений, использующих новые криптографические возможности, понадобится
Visual Studio 2005 с первым сервис-паком (естественно,
бета-версия VS 2008, которая выкладывалась на диске к августовскому
номеру журнала, тоже подойдет). Я тут уже упоминал, что
CNG совместима только с WV. А это значит, что помимо IDE нам понадобится еще и
Windows Vista SDK, позволяющий разрабатывать приложения для этой операционной системы. И, наконец, самое главное, без чего тебе не
обойтись, - это CNG SDK, содержащий все необходимые
заголовочные файлы, библиотеки и криптоинструменты. Где его взять? Ну,
во-первых, на сайте производителя (хм... почему-то это слово у меня
ассоциируется исключительно с мужской особью крупного рогатого скота). А
во-вторых, на нашем диске - такие вот мы добрые и щедрые.
И последнее замечание. Если ты фанат Visual Basic'a или крутой перец,
не признающий ничего, кроме жутко модного C#, спешу тебя огорчить:
CNG SDK совместим только с проектами, написанными на приплюснутом Си.
Теперь детали...
Для того чтобы начать работать с CNG, нужно в
свойствах проекта в группе параметров C/C++ (строка Additional Include
Directories) прописать путь к файлам CNG SDK. Если ты не менял
предложенный по умолчанию каталог установки SDK, тогда это будет
C:\Program Files\Microsoft CNG Development Kit\Include.
Кроме того, в свойствах линкера необходимо указать, где он сможет
найти необходимые DLL-файлы (C:\Program Files\Microsoft CNG Development
Kit\Lib\X86).
Криптография нового поколения
Как видишь, парни из Microsoft действительно приложили немало усилий к тому, чтобы заменить малопопулярный у разработчиков
CAPI более надежным и более функциональным набором
инструментов. И это у них, безусловно, получилось. Хотя, возможно, они
немного погорячились, назвав это криптографией нового поколения,
поскольку ничего принципиально нового придумано не было. Просто широко
известные и проверенные временем алгоритмы были объединены в
криптоядро со своим API, доступным как из
пользовательского режима, так и из режима ядра. Простая идея. Но,
несмотря на свою простоту, она позволяет вывести криптографические
возможности операционной системы на новый уровень. Считать ли это
криптографией
нового поколения, решать тебе. Adios!
WWW
http://msdn2.microsoft.com/en-us/library/aa376214.aspx - подробное описание CNG на сайте MSDN.
www.microsoft.com/security/glossary.mspx - словарь терминов по IT-безопасности, используемых в технологиях компании Microsoft.
|