Лабораторная работа №1.
Работа с криптопровайдерами Microsoft CryptoAPI.

Цель работы

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

Ход работы

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

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

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

Проанализировать работу полученной программы и сравнить результаты работы программы с примером результатов, приведенным в лабораторной работе.

Описание основных используемых в лабораторной работе функций Microsoft Crypto API

(функции определены в файле wincrypt. h, полное описание находится в MSDN, security. chm, .chi, в разделе Cryptography\CryptoAPI\Using CryptoAPI\CryptoAPI Reference\CryptoAPI Functions\Base CryptoAPI Functions\Service Provider Functions)

CryptEnumProviderTypes

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

BOOL WINAPI CryptEnumProviderTypes(

НЕ нашли? Не то? Что вы ищете?

DWORD dwIndex, // [вх] номер следующего перечисляемого типа.

DWORD *pdwReserved, //[вх] должен быть NULL. Оставлен для использования в будущем.

DWORD dwFlags, //[вх] должен быть 0. Оставлен для использования в будущем.

DWORD *pdwProvType, //[вых] адрес значения содержащего перечисляемый тип.

LPTSTR pszTypeName, //[вых] указатель на место, куда будет помещена строка с именем типа. Параметр может быть NULL для получения размера памяти необходимого для выделения.

DWORD *pcbTypeName //[вх/вых] размер строки, записанной в предыдущий параметр.

);

Возвращаемые значения: если все прошло нормально, ненулевое (TRUE), если произошла ошибка, то возвращается нуль (FALSE). Для анализа ошибки нужно вызвать GetLastError. Если она вернула значение ERROR_NO_MORE_ITEMS, то это не ошибка, а сигнал окончания списка типов криптопровайдеров. Таблица кодов остальных ошибок находится в MSDN.

CryptEnumProviders

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

BOOL WINAPI CryptEnumProviders(

DWORD dwIndex, // [вх] номер следующего перечисляемого провайдера.

DWORD *pdwReserved, //[вх] должен быть NULL. Оставлен для использования в будущем.

DWORD dwFlags, //[вх] должен быть 0. Оставлен для использования в будущем.

DWORD *pdwProvType, //[вых] адрес значения содержащего тип перечисляемого провайдера.

LPTSTR pszProvName, //[вых] указатель на место, куда будет помещена строка с именем провайдера. Параметр может быть NULL для получения размера памяти необходимого для выделения.

DWORD *pcbProvName //[вх/вых] размер строки, записанной в предыдущий параметр.

);

Возвращаемые значения: если все прошло нормально, ненулевое (TRUE), если произошла ошибка, то возвращается нуль (FALSE). Для анализа ошибки нужно вызвать GetLastError. Если она вернула значение ERROR_NO_MORE_ITEMS, то это не ошибка, а сигнал окончания списка типов криптопровайдеров. Если она вернула ERROR_MORE_DATA, то буфер pszProvName недостаточен для размещения в нем имени. Таблица кодов остальных ошибок находится в MSDN.

CryptGetDefaultProvider

получает криптопровайдер определенного типа, заданный в системе по умолчанию.

BOOL WINAPI CryptGetDefaultProvider(

DWORD dwProvType, //[вх] тип провайдера по умолчанию. Может быть одним из следующих: PROV_RSA_FULL, PROV_RSA_SIG, PROV_DSS, PROV_DSS_DH, PROV_DH_SCHANNEL, PROV_FORTEZZA, PROV_MS_EXCHANGE, PROV_RSA_SCHANNEL, PROV_SSL

DWORD *pdwReserved, //[вх] должен быть NULL. Оставлен для использования в будущем

DWORD dwFlags, //[вх] CRYPT_USER_DEFAULT ищет провайдер по умолчанию для данного пользователя. CRYPT_MACHINE_DEFAULT ищет провайдер по умолчанию системы.

LPTSTR pszProvName, //[вых] указатель на место, куда будет помещена строка с именем провайдера. Параметр может быть NULL для получения размера памяти необходимого для выделения

DWORD *pcbProvName //[вх/вых] размер строки, записанной в предыдущий параметр.

);

Возвращаемые значения: если все прошло нормально, ненулевое (TRUE), если произошла ошибка, то возвращается нуль (FALSE). Для анализа ошибки нужно вызвать GetLastError. Если она вернула ERROR_MORE_DATA, то буфер pszProvName недостаточен для размещения в нем имени. Если она вернула ERROR_INVALID_PARAMETER, значит один из параметров является неправильным. Таблица кодов остальных ошибок находится в MSDN.

CryptAcquireContext

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

Сначала функция пытается найти криптопровайдер с параметрами, описанными в dwProvType и pszProvider. Если криптопровайдер найден, функция пытается найти в нем контейнер ключей с именем, указанным в pszContainer.

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

BOOL WINAPI CryptAcquireContext(

HCRYPTPROV *phProv, //[вых] указатель на дескриптор криптопровайдера.

LPCTSTR pszContainer, //[вх] заканчивающаяся нулем строка с именем контейнера ключей. Если равен NULL, то используется контейнер по умолчанию. Когда dwFlags установлен в CRYPT_VERIFYCONTEXT, pszContainer должен быть NULL.

LPCTSTR pszProvider, //[вх] заканчивающаяся нулем строка с именем криптопровайдера. Если равен NULL, то используется криптопровайдер по умолчанию.

DWORD dwProvType, //[вх] задает тип получаемого криптопровайдера.

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

);

Значения параметра dwFlags:

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

CRYPT_NEWKEYSET создает новый контейнер ключей с именем заданным в pszContainer. Если последний равен NULL, то создается контейнер с именем по умолчанию.

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

После создания контейнера большинством криптопровайдеров ключи автоматически не создаются. Их необходимо создать отдельно вызовом CryptGenKey.

CRYPT_DELETEKEYSET уничтожает указанный в pszContainer контейнер ключей. Если pszContainer равен NULL, то удаляется контейнер ключей по умолчанию. Все ключевые пары в контейнере также уничтожаются. Если установлен этот флаг, то значение phProv не определено, и вызывать CryptReleaseContext не нужно.

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

Возвращаемые значения: если все прошло нормально, ненулевое (TRUE), если произошла ошибка, то возвращается нуль (FALSE). Для анализа ошибки нужно вызвать GetLastError. Некоторые из возможных значений ошибок (таблица кодов остальных ошибок находится в MSDN):

ERROR_BUSY: если установлен CRYPT_DELETEKEYSET а другой процесс использует этот контейнер.

ERROR_INVALID_PARAMETER: один из параметров является неправильным.

NTE_BAD_KEYSET: невозможно открыть контейнер. Скорее всего нет контейнера с таким именем.

NTE_SIGNATURE_FILE_BAD, NTE_BAD_SIGNATURE: не прошла проверка подписи DLL провайдера. Либо подпись, либо DLL были подменены.

NTE_EXISTS: если установлен CRYPT_NEWKEYSET, а контейнер с таким именем уже существует.

NTE_KEYSET_ENTRY_BAD: контейнер найден, но поврежден.

NTE_KEYSET_NOT_DEF: не найден провайдер или контейнер с заданным именем.

NTE_PROV_TYPE_NO_MATCH: тип провайдера не соответствует найденному криптопровайдеру. Эта ошибка возможна, если pszProvider задает имя конкретного криптопровайдера.

CryptGetProvParam

получает параметры, управляющие работой криптопровайдера.

BOOL WINAPI CryptGetProvParam(

HCRYPTPROV hProv, //[вх] дескриптор криптопровайдера, созданный вызовом CryptAcquireContext.

DWORD dwParam, //[вх] обозначает предмет запроса (см. ниже)

BYTE *pbData, //[вых] указатель на место, куда будет помещена строка с именем провайдера. Параметр может быть NULL для получения размера памяти необходимого для выделения.

DWORD *pdwDataLen, //[вх/вых] указатель на размер строки, записанной в предыдущий параметр. Если pdbData равен NULL и запрос PP_ENUMALGS или PP_ENUMALGS_EX, параметр содержит размер максимальной записи из списка.

DWORD dwFlags //[вх] флаги (см. ниже).

);

Возможные значения dwParam:

PP_CONTAINER, PP_UNIQUE_CONTAINER: имя текущего контейнера ключа.

PP_ENUMALGS: структура PROV_ENUMALGS, содержащая сокращенную информацию об одном алгоритме, поддерживаемом криптопровайдером. Значения должны запрашиваться последовательно чтобы получить все поддерживаемые алгоритмы. При первом вызове должен быть установлен флаг CRYPT_FIRST в dwFlags. При следующих вызовах dwFlags должен быть установлен в 0. Список окончился, если выдан код ошибки ERROR_NO_MORE_ITEMS.

Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4