Cifratura la Vista Николай Байбородин (baiborodin@gmail.com) Хакер, номер #108, стр. 108-112-1 Используем криптоядро Windows VistaНу что же, разопьем по бутылочке темного пива и продолжим знакомиться с возможностями Windows Vista, доступными разработчикам программного обеспечения (или, как подсказывает Крыс Касперски из своей глубокой норы в недрах аргентинского болота, «точить»). На этот раз давай посмотрим, что же изменилось в операционной системе с точки зрения шифрования данных. А изменилось, надо сказать, немало: начиная с основательного обновления CryptoAPI и заканчивая созданием принципиально новой сущности – криптоядра CNG (Cryptography API Next Generation). Дело за малым – разобраться со всем этим богатством и научиться применять криптотехнологии WV на практике. Windows Crypto – время переменAaloha, Guy! Думаешь, ты уже изучил Висту вдоль и поперек и познакомился со всеми ее фишками? Не тут-то было. Пора копнуть глубже и заглянуть ей под капот. Видишь во-о-он ту блестящую штуковину с моторчиком? Нравится? А знаешь, что это такое? Нет? Ну тогда слушай и запоминай. Итак, на повестке дня - криптосистема Windows Vista
И в Microsoft это хорошо понимают. Нет, они не переписали CAPI с нуля (на фига напрягаться), они просто засунули CAPI в дальний темный угол системы. Теперь за взаимодействие с CAPI отвечает красивая блестящая обертка под названием CNG. Но парни действительно старались, и обертка получилась не только красивой, но и весьма полезной. О том, какие возможности перед тобой открывает система CNG, читай ниже. Перечень изменений в криптографической системе выглядит следующим образом:
Согласись, перемены достаточно серьезные. И это я еще не упомянул о кардинальной перестройке архитектуры интерфейса PKI. Следуя известной мудрости, гласящей о том, что «нельзя объять необъятное», давай остановимся на центральной теме нововведений в криптосистеме – на интерфейсе CNG, а все остальное пусть будет твоим домашним заданием :).
Итак, технология CNG (Cryptography Next Generation) пришла к нам всерьез и надолго, будучи призванной заменить устаревший CryptoAPI. Основной логической единицей как в CryptoAPI, так и в CNG является криптопримитив, то есть некоторая сущность, обеспечивающая выполнение одной специализированной операции. Если провести сравнение криптопримитивов, входящих в состав CryptoAPI и CNG, то можно сказать, что CNG в полном объеме включает в себя CryptoAPI плюс новые дополнительные возможности. На рисунке, иллюстрирующем структуру CNG, видно, что основу технологии составляют два элемента – NCrypt и BCrypt. NCrypt отвечает за хранение ключей, используемых ассиметричными алгоритмами шифрования. Кроме того, NCrypt обеспечивает поддержку смарт-карт и прочего оборудования. А вот функции BCrypt гораздо шире и интереснее. Именно здесь находится все богатство криптографических примитивов, которыми располагает CNG. Эти примитивы могут быть использованы как в режиме ядра, так и в пользовательском режиме, в то время как хранилище ключей NCrypt доступно только из пользовательского режима. CNG предоставляет специальный API для доступа к криптографическим возможностям Windows Vista. Причем реализован этот доступ, в отличие от других аналогичных систем, не в виде отдельных функций, а в виде набора интерфейсов криптоядра. Набор логических криптоинтерфейсов представляет собой криптомаршрутизатор. Посмотри на схему структуры 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, следовательно, если тебе понадобится обработка этих сообщений, используй вот такой макрос: #ifndef NT_SUCCESS # define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) #endif Шифруем данные: 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! Основные функции CNG, доступные разработчикам:
Криптографические алгоритмы, реализованные в CNGВ общем случае технология использования CNG включает в себя пять шагов:
Система безопасности Windows Vista основана на следующих элементах:
ДВДСпециально для тебя мы выложили на наш диск CNG SDK! Шифруйся на здоровье. Лучше один раз увидеть, чем бла-бла-бла... Забирай с диска архив с примерами, распаковывай и изучай. WWW
INFOПо некоторым сведениям, в SP1 для WV помимо всего прочего войдут и изменения CNG, в частности, будут добавлены такие алгоритмы, как алгоритм симметричного дополнительного шифрования и алгоритм двойной эллиптической генерации случайных чисел. |