КриптоПро CSP 2.0

127018, Москва, Улица Образцова, 38
Телефон: (095) 933 1168
Факс: (095) 933 1168
http://www.CryptoPro.ru
E-mail: info@CryptoPro.ru

Средство Криптографической Защиты Информации

КриптоПро CSP

Версия 2.0

Руководство программиста

Часть 1. Внешний интерфейс провайдера

ЖТЯИ.00005-01 90 03

© OOO "Крипто-Про", 2000-2002. Все права защищены.
Авторские права на средство криптографической защиты информации КриптоПро CSP и эксплуатационную документацию зарегистрированы в Российском агентстве по патентам и товарным знакам (Роспатент). Свидетельство об официальной регистрации программ для ЭВМ № 2001610275 от 14 марта 2001 года.
Документ входит в комплект поставки программного обеспечения КриптоПРО CSP, и на него распространяются все условия лицензионного соглашения. Без специального письменного разрешения OOO "Крипто-Про" документ или его часть в электронном или печатном виде не могут быть скопированы и переданы третьим лицам с коммерческой целью.


Введение

КриптоПро CSP 2.0

ЖТЯИ.00005-01 30 01

© OOO "Крипто-Про" 2000-2002

Средство
Криптографической
Защиты
Информации

КриптоПро CSP 2.0

КриптоПро CSP

КриптоПро CSP версия 2.0 является дальнейшим развитием средства криптографической защиты информации КриптоПро CSP, разработанного ООО "Крипто-Про".

СКЗИ КриптоПро CSP реализует российские криптографические алгоритмы и разработана в соответствии с криптографическим интерфейсом фирмы Microsoft - Cryptographic Service Provider (CSP).

Область применения

Интеграция КриптоПро CSP с операционной системой Windows позволила использовать технологии Microsoft с российскими криптографическими алгоритмами для реализации различных защищенных систем документооборота и электронной коммерции, на основе Инфраструктуры Открытых Ключей (Public Key Infrastructure), соответствующей международным рекомендациям X.509, RFC 2459 и Федеральному закону "Об электронной цифровой подписи".

Использование КриптоПро CSP позволяет решить сразу несколько задач:

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

К стандартным приложениям, которые теперь могут использовать российские алгоритмы электронной цифровой подписи и шифрования, относятся:

  • Центр Сертификации - Microsoft Certification Authority
  • Электронная почта - Microsoft Outlook
  • Электронная почта - Microsoft Outlook Express
  • Средства контроля целостности ПО - Microsoft Authenticode
  • Защита соединений в Интернете (протокол TLS/SSL)

Аннотация

Краткое описание КриптоПро CSP.

Архитектура

Архитектура криптографических функций операционной системы Windows.

Руководство программиста

Описание функций, структур, переменных КриптоПро CSP.

Обратная связь

Связь с разработчиком.
Поддержка.
Конференция.


СКЗИ Крипто-Про CSP

КриптоПро CSP

Средство криптографической защиты информации КриптоПро CSP версия 2.0

Основные функции КриптоПро CSP

Основные функции, реализуемые КриптоПро CSP:

  • генерация закрытых (256 бит), открытых (1024 бита для ГОСТ Р 34.10-94 и 512 бит для ГОСТ Р 34.10-2001 ) ключей ЭЦП и шифрования;
  • формирование закрытых ключей на следующие типы носителей:
    • дискета 3,5";
    • процессорные карты MPCOS-EMV и российские интеллектуальные карты (РИК) с использованием считывателей смарт-карт, поддерживающий протокол PS/SC (GemPlus GCR-410, Towitoko, Oberthur OCR126);
    • таблетки Touch-Memory DS1993 - DS1996 с использованием устройств Аккорд 4+, электронный замок "Соболь" или устройство чтения таблеток Touch-Memory DALLAS;
    • электронный ключ с интерфейсом USB;
    • сменный носитель с интерфейсом USB;
    • реестр Windows.
  • возможность хранения сертификатов открытых ключей в ключевом контейнере;
  • возможность генерации ключей с различными параметрами в соответствии с ГОСТ Р 34.10-94 ("Информационная технология. Криптографическая защита информации. Система электронной цифровой подписи на базе асимметричного криптографического алгоритма.");
  • возможность генерации ключей с различными параметрами в соответствии с ГОСТ Р 34.10-2001 ("Информационная технология. Криптографическая защита информации. Процессы формирования и проверки электронной цифровой подписи.");
  • хеширование данных в соответствии с ГОСТ Р 34.11-94 ("Информационная технология. Криптографическая защита информации. Функция хэширования.");
  • шифрование данных во всех режимах, определенных ГОСТ 28147-89 ("Системы обработки информации. Защита криптографическая.");
  • имитозащита данных в соответствии с ГОСТ 28147-89;
  • формирование электронной цифровой подписи в соответствии с ГОСТ Р 34.10-94, ГОСТ Р 34.10-2001;
  • опциональное использование пароля (пин-кода) для дополнительной защиты ключевой информации;
  • реализация мер защиты от НСД ключевой информации пользователя.

Операционные системы

КриптоПро CSP функционирует в следующих операционных системах (ОС):

  • Windows 98 с установленным ПО MS Internet Explorer версии 5.0 и выше;
  • Windows 98 SE с установленным ПО MS Internet Explorer версии 5.0 и выше;
  • Windows NT 4.0 SP5 и выше с установленным ПО MS Internet Explorer 5.0 и выше;
  • Windows ME;
  • Windows 2000;
  • Windows XP;
  • Solaris 8 на платформах Intel и SPARC (32 и 64 бита).

На платформах Microsoft Windows 98/98 SE/ME/NT/2000/XP, используемых с СКЗИ "КриптоПро CSP", должна быть произведена установка следующих двух пакетов обновлений:

  1. Microsoft Security Bulletin MS02-048. Flaw in Certificate Enrollment Control Could Allow Deletion of Digital Certificates (Q323172). August 28, 2002. Доступ по адресу: http://www.microsoft.com/technet/treeview/default.asp?url=/technet/ security/bulletin/MS02-048.asp

  2. Microsoft Security Bulletin MS02-050. Certificate Validation Flaw Could Enable Identity Spoofing (Q328145). September 09, 2002. Доступен по адресу: http://www.microsoft.com/technet/treeview/default.asp?url=/technet/ security/bulletin/MS02-050.asp

Примечание 1. Полный перечень операционных систем и дополнительные требования, необходимые для функционирования СКЗИ приведены в документе "КриптоПро CSP. Описание реализации", ЖТЯИ.00005-01 90 01.

Примечание 2. Порядок и сроки эксплуатации операционных систем, в среде которых функционирует СКЗИ КриптоПро CSP v. 2.0, определяются производителями операционных систем.

Примечание 3. При выборе ОС необходимо учитывать следующие сроки поддержки и окончания эксплуатации операционных систем (по данным фирмы Microsoft на 03.07.2002 г. http://www.microsoft.com/windows/lifecycle.mspx):

ОС | Поддержка | Окончание эксплуатации
Microsoft Windows 98 | 30 июня 2002 г. | 30 июня 2003 г.
Microsoft Windows 98 SE | 30 июня 2002 г. | 30 июня 2003 г
Microsoft Windows NT 4/xx | 30 июня 2002 г. | 30 июня 2003 г
Microsoft Windows 2000 | 31 марта 2003 г. |
Microsoft Windows ME | 31 декабря 2003 г. |

Интеграция с прикладным программным обеспечением

О способах использования КриптоПро CSP смотрите в разделе Архитектура криптографических функций операционной системы Windows.

Удостоверяющий центр

Используя средство криптографической защиты информации КриптоПро CSP и средство сетевой аутентификации КриптоПро TLS, компания Крипто-Про разработала программный комплекс Удостоверяющий центр (КриптоПро УЦ), реализующий Инфраструктуру Открытых Ключей.

Удостоверяющий центр КриптоПро УЦ - это комплекс программных средств, разработанных на основе служб сертификации операционной системы Windows 2000 Server.

Основные функции, выполняемые с помощью КриптоПро УЦ:

  • Регистрация пользователей

  • Изготовление сертификатов открытых ключей

  • Ведение реестра сертификатов открытых ключей

  • Управление сертификатами открытых ключей

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

Удостоверяющий центр КриптоПро УЦ обеспечивает:

  • Выполнение процедуры генерации личных закрытых и открытых ключей ЭЦП и шифрования на рабочем месте пользователя;

  • Формирование запроса на сертификат нового открытого ключа на рабочем месте пользователя;

  • Выполнение процедуры регистрации электронных запросов от пользователей на сертификаты открытых ключей в Центре регистрации УЦ;

  • Формирование электронных сертификатов открытых ключей пользователей в соответствии с рекомендациями Х.509 версии 3 и RFC 2459, позволяющими с помощью криптографических методов (ЭЦП) централизованно заверять соответствие открытого ключа и атрибутов определенному пользователю;

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


СКЗИ Крипто-Про CSP

Архитектура криптографических функций в Windows

Архитектура криптографических функций в Windows

При разработке СКЗИ КриптоПРО CSP учитывалась существующая в операционной системе Windows архитектура использования криптографических функций. В соответствии с этой архитектурой собственно криптографические функции реализуются через специфицированный Microsoft интерфейс - Cryptographic Service Providers (CSP). При этом возможно подключение дополнительных криптографических модулей, удовлетворяющих формату CSP и SSPI для использования как в составе стандартного программного обеспечения, так и для встраивания в прикладное программное обеспечение.

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

Использование в программном обеспечении Microsoft

  • Центр Сертификации - Microsoft Certification Authority, входящий в состав OS Windows 2000 Server, Advanced Server (http://www.microsoft.com/technet/win2000/2000cert.asp);
  • Электронная почта - Microsoft Outlook 98, 2000, XP (http://www.microsoft.com/technet/security/outlksec.asp);
  • Электронная почта - Microsoft Outlook Express, входящая в состав Internet Explorer версии 5.0 или выше (http://www.microsoft.com/TechNet/win2000/pubkeyox.asp);
  • Средства контроля целостности ПО, распространяемого по сети - Microsoft Authenticode (http://www.microsoft.com/TechNet/security/authtech.asp);
  • Защита TCP/IP соединений в сети Интернет - протокол TLS/SSL при взаимодействии Internet Explorer - Web сервер IIS 5.0(4.0).

Встраивание СКЗИ КриптоПро CSP

Иерархическая архитектура криптографических функций в операционной системе Windows позволяет использовать российские криптографические алгоритмы, реализованные в КриптоПро CSP на самых различных уровнях.

Подключение на уровне CSP

КриптоПро CSP может быть непосредственно подключено к прикладному программному обеспечению путем загрузки модуля с использованием функции LoadLibrary(). Для этих целей в комплект поставки включается "Руководство программиста", описывающее состав функций и тестовое ПО. При такой реализации прикладному ПО доступен лишь ограниченный набор низкоуровневых криптографических функций, соответствующий интерфейсу Microsoft CSP.

Подключение на уровне CryptoAPI 2.0

КриптоПро CSP может быть подключено к прикладному программному обеспечению (как и любой другой криптопровайдер, поставляемый с ОС Windows) через интерфейс CryptoAPI 2.0, подробное описание которого приведено в программной документацией MSDN (Microsoft Developer Network). В этом случае способ выбора криптографического алгоритма в прикладном ПО может определятся информацией, описывающий алгоритм открытого ключа отправителя/получателя, содержащийся в сертификатах открытых ключей Х.509.

Использование интерфейса CryptoAPI 2.0 в ОС Windows преследует две главные цели:

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

Функционально интерфейс CryptoAPI 2.0 делится на 5 групп.

Базовые криптографические функции

К базовым функциям относятся функции:

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

По своей функциональности базовые функции повторяют низкоуровневый интерфейс CSP.

Функции кодирования/декодирования

Данные функции предназначены для преобразования (кодирования) из внутреннего представления объектов, используемых в CryptoAPI, во внешнее представление и обратно. В качестве внешнего представления объектов используется формат ASN.1 (Abstracy Syntax Notation One), определенный серией рекомендаций X.680. К этой же группе функций можно отнести набор функций, позволяющих расширить функциональность CryptoAPI 2.0 путем реализации и регистрации собственных типов объектов.

Функции работы со справочниками сертификатов

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

Высокоуровневые функции обработки криптографических сообщений

Именно эта группа функций (Simplified Message Functions) в первую очередь предназначена для использования в прикладном ПО. С помощью этих функций можно:

  • Зашифровать/расшифровать сообщение от одного пользователя к другому.
  • Подписать данные.
  • Проверить подпись данных.

Эти функции (так же как и функции низкого уровня) оперируют сертификатами открытых ключей X.509 для адресации отправителя/получателя данных. В качестве формата данных, формируемых функциями, используется формат PKCS#7 (RFC2315) или CMS (RFC2630) в Windows 2000.

Низкоуровневые функции обработки криптографических сообщений

Данная группа функция (Low Level Message Functions) предназначена для аналогичных целей, что и группа высокоуровневых функций, но обладает большей функциональностью. Вместе с тем большая функциональность требует от прикладного программиста более детальных знаний в области прикладной криптографии.

Использование COM интерфейсов

КриптоПро CSP может быть использовано из COM интерфейсов, разработанных Microsoft.

  • CAPICOM 1.0 (CAPICOM 2.0);
  • Certificate Services;
  • Certificate Enrollment Control.

Certificate Enrollment Control

COM интерфейс Certificate Enrollment Control (реализованный в файле xenroll.dll) предназначен для использования ограниченного количества функций CryptoAPI 2.0, связанных с генерацией ключей, запросов на сертификаты и обработкой сертификатов, полученных от Центра Сертификации с использованием языков программирования Visual Basic, C++, JavaScript, VBScript и среды разработки Delphi.

Именно этот интерфейс используют различные публичные Центры Сертификации (Verisign, Thawte и т. д.) при формировании сертификатов пользователей на платформе Windows.

CAPICOM

CAPICOM (реализованный в файле capicom.dll) предоставляет COM интерфейс, использующий основные функции CryptoAPI 2.0. Этот компонент является добавлением к уже существующему COM интерфейсу Certificate Enrollment Control (xenroll.dll), который реализуют клиентские функции генерации ключей, запросов на сертификаты и обмена с центром сертификации.
С выпуском данного компонента стало возможным использование функций формирования и проверки электронной цифровой подписи, построения и проверки цепочек сертификатов, взаимодействия с различными справочниками сертификатов (включая Active Directory) с использованием Visual Basic, C++, JavaScript, VBScript и среды разработки Delphi. Использование CAPICOM позволяет реализовать функциональность "тонкого" клиента в интерфейсе броузера Internet Explorer.

Компонент CAPICOM является свободно распространяемым и поставляется в составе Redistributable инструментария разработчика Microsoft Platform SDK.

Certificate Services

Certificate Services включает в себя несколько COM интерфейсов, позволяющих изменить функциональность Центра Сертификации, входящего в состав ОС Windows 2000 Server. При помощи данных интерфейсов возможно изменить:

  • обработку поступающих от пользователей запросов на сертификаты
  • состав данных (в том числе дополнений X.509), записываемых в издаваемые центром сертификаты
  • способ публикации (хранения) изданных центром сертификатов.

Использование протокола TLS в прикладном ПО

Кроме использования протокола TLS в интерфейсе Internet Explorer, прикладное программное обеспечение может использовать протокол TLS с СКЗИ КриптоПро CSP для аутентификации и защиты данных, передаваемых по собственным протоколам на основе TCP/IP и HTTPS.

Для встраивания протокола TLS в комплект примеров, поставляемых с Platform SDK, входят примеры WebClient и WebServer.

Примеры использования средств криптографической защиты

СКЗИ КриптоПро CSP поставляется с тестовым программным обеспечением, содержащим примеры вызовов основных функций CryptoAPI 2.0. Большое количество примеров использования функций CryptoAPI 2.0, CAPICOM, Certificate Services входит в документацию MSDN и в инструментарий разработчика Platform SDK.

На сервере Крипто-Про (http://www.cryptopro.ru/CryptoPro/forum.asp) ведется конференция по вопросам использования криптографических функций и сертификатов открытых ключей. Соответствующие конференции по отдельным темам ведутся на сервере Microsoft:

  • http://discuss.microsoft.com/archives/cryptoapi.html - вопросы использования CryptoAPI;
  • http://discuss.microsoft.com/archives/capicom.html - вопросы использования технологии Authenticode;
  • http://discuss.microsoft.com/archives/authenticode.html - вопросы использования CAPICOM.

Заключение

СКЗИ КриптоПро CSP позволяет использовать стойкие сертифицированные средства криптографической защиты информации в составе обширного инструментария и программного обеспечения корпорации Microsoft, для реализации различных защищенных систем документооборота и электронной коммерции, на основе Инфраструктуры Открытых Ключей (Public Key Infrastructure), соответствующей международным рекомендациям X.509, RFC 2459.


Внешний интерфейс провайдера "КриптоПро CSP-ECC/TLS"

Функции КриптоПро CSP

Функции, структуры, параметры внешнего интерфейса провайдера КриптоПро CSP
Группы
Инициализация и параметры криптопровайдера
Функции генерации и работы с ключами
Функции шифрования/расшифрования данных
Функции хэширования и ЭЦП
Структуры данных, используемые КриптоПро CSP
Дополнительные параметры и определения, используемые КриптоПро CSP


Инициализация и параметры криптопровайдера

Функции инициализации и параметры. Предназначены для установления сессии прикладного ПО с криптопровайдером и получения (установки) параметров сессии.
Функции | Описание
BOOL WINAPI CPAcquireContext ( HCRYPTPROV *phProv, CHAR *pszContainer, DWORD dwFlags, PVTABLEPROVSTRUC pVTable) | Функция CPAcquireContext().
BOOL WINAPI CPReleaseContext ( HCRYPTPROV hProv, DWORD dwFlags) | Функция CPReleaseContext().
BOOL WINAPI CPGetProvParam ( HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData, DWORD *pdwDataLen, DWORD dwFlags) | Функция CPGetProvParam().
BOOL WINAPI CPSetProvParam ( HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData, DWORD dwFlags) | Функция CPSetProvParam().
Последние изменения: 25 окт 2002


CPAcquireContext

Функция CPAcquireContext().

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

BOOL WINAPI CPAcquireContext (
  HCRYPTPROV * phProv,
  CHAR * pszContainer,
  DWORD dwFlags,
  PVTABLEPROVSTRUC pVTable
);

Параметры:

phProv
[out] Адрес, по которому функция копирует дескриптор криптопровайдера.
pszContainer
[in] Имя ключевого контейнера. Это указатель на строку, длиной не больше, чем MAX_PATH знаков, включая признак конца строки. Если данный параметр - NULL, то криптопровайдер будет использовать в качестве имени контейнера имя пользователя, вошедшего в систему. Пользователь может получить имя используемого контейнера функцией CPGetProvParam(). Подробнее см. LPSZ_CONTAINER_NAME.
dwFlags
[in] Параметр имеет нулевое или одно из следующих значений:
Значение dwFlags | Описание
CRYPT_VERIFYCONTEXT | Приложение не имеет доступа к секретным ключам ключевого контейнера. Флаг предназначен для использования с приложениями, для которых требуется проверка цифровой подписи. Операции, обычно необходимые в этом случае, – получение дескрипторов открытых ключей, хэширование и проверка подписи. При вызове функции CryptAcquireContext() криптопровайдер не требует от пользователя ввода ключевой информации.
CRYPT_NEWKEYSET | Если флаг установлен, то будет создан новый ключевой контейнер с именем, соответствующим pszContainer. Если pszContainer - NULL, то в качестве имени контейнера используется имя пользователя, вошедшего в систему.
CRYPT_MACHINE_KEYSET | Флаг может использоваться при вызове функции CryptAcquireContext() c CRYPT_NEW_KEYSET или флагом CRYPT_DELETE_KEYSET. В этом случае ключи будут сохранены в ключе HKEY_LOCAL_MACHINE системного реестра. Флаг предназначен для использования криптопровайдера в составе системных приложений.
CRYPT_DELETEKEYSET | Ключевой контейнер, соответствующий pszContainer, удаляется. Если pszContainer - NULL, то удаляется ключевой контейнер с именем, заданным по умолчанию. Все ключевые пары в ключевом контейнере также уничтожаются. Когда флаг CRYPT_DELETEKEYSET установлен, значение, возвращенное в phProv, не определено и функция CPReleaseContext() не должна вызываться повторно.
CRYPT_SILENT | Приложение запрещает "КриптоПро CSP" использовать какой либо пользовательский интерфейс (UI) при выполнении операций с данным контекстом. Если для выполнения операции "КриптоПро CSP" необходимо использовать UI, то он будет возвращать ошибку NTE_SILENT_CONTEXT, как код LastError.
pVTable
[in] Указатель на структуру _VTABLEPROVSTRUC, которая содержит список callback функций, представляемых операционной системой для использования криптопровайдером.

Возвращает:

При успешном завершении функция возвращает TRUE, в противном случае возвращается FALSE. Если возвращается FALSE, соответствующий код ошибки (см. таблицу) может быть получен через функцию GetLastError().
Возвращаемые значения | Описание
ERROR_BUSY | Ключевой контейнер с данным именем был создан иным процессом и в настоящее время не может использоваться данным процессом. Если эта ошибка возникает при обработке контейнера в одном процессе, разрешить коллизию можно вызовом функции CPReleaseContext().
NTE_BAD_FLAGS | Параметр dwFlags имеет запрещенное значение.
NTE_BAD_KEYSET | Ключевой контейнер не был открыт, и, возможно, не существует.
NTE_BAD_KEYSET_PARAM | Параметр pszContainer установлен в запрещенное значение.
NTE_BAD_SIGNATURE | Не прошла проверка цифровой подписи DLL криптопровайдера. DLL или цифровая подпись искажены.
NTE_EXISTS | Параметр dwFlags установлен в CRYPT_NEWKEYSET, а ключевой контейнер уже существует.
NTE_KEYSET_ENTRY_BAD | Ключевой контейнер, соответствующий pszContainer найден, но искажен.
NTE_KEYSET_NOT_DEF | Ключевой контейнер, соответствующий pszContainer, не существует.
NTE_NO_MEMORY | Криптопровайдер во время операции исчерпал память.
SCARD_W_CANCELLED_BY_USER | Пользователь прервал операцию, нажатием клавиши Cancel
SCARD_W_WRONG_CHV | Пользователь ввел неправильный пароль или пароль, установленный функцией SetProvParam, неправильный
SCARD_E_INVALID_CHV | Пользователь ввел пароль с нарушением формата или пароль, установленный функцией SetProvParam, имеет неправильный формат. Например, пароль имеет недопустимую длину или содержит недопустимые символы.
SCARD_W_CHV_BLOCKED | Ввод Pin-кода был заблокирован смарт-картой, т.к. исчерпалось количество попыток, разрешенное картой для ввода.
NTE_TOKEN_KEYSET_STORAGE_FULL | Недостаточно места на носителе для сохранения информации.

Требования:

Windows NT/2000/XP: Необходимо Windows NT 4.0 SP5 или старше с Internet Explorer 5.0 или старше.
Windows 98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле Wincrypt.h.
Solaris: Прототип описан в файле CSP_Wincrypt.h.
Ядро ОС: При использовании в ядре ОС CPAcquireContext допустимо вызывать только с флагами CRYPT_VERIFYCONTEXT|CRYPT_SILENT.

См. также:

CPReleaseContext() , CPAcquireContext() в MS CSP , CryptAcquireContext() в MS CryptoAPI 2.0 , CryptSetProvParam() в MS CryptoAPI 2.0


CPGetProvParam

Функция CPGetProvParam().

Производит возвращение параметров криптопровайдера.

BOOL WINAPI CPGetProvParam (
  HCRYPTPROV hProv,
  DWORD dwParam,
  BYTE * pbData,
  DWORD * pdwDataLen,
  DWORD dwFlags
);

Параметры:

hProv
[in] Дескриптор криптопровайдера. Получается через запрос функции CPAcquireContext().
dwParam
[in] Значение аргумента определяет тип запроса. В настоящее время определены следующие значения dwParam:
Значение dwParam | Содержимое буфера pbData
PP_CONTAINER | Имя ключевого контейнера вида CONTAINER, если он имеет имя, в противном случае уникальное имя (см. PP_UNIQUE_CONTAINER). Строковая величина с признаком конца строки, содержащая имя текущего ключевого контейнера. Подробнее см. LPSZ_CONTAINER_NAME.
PP_UNIQUE_CONTAINER | Уникальное имя ключевого контейнера. Уникальное имя зависит от типа ключевого носителя и может иметь вид: MEDIA\FOLDER, MEDIA\UNIQUE\FOLDER или MEDIA\UNIQUE. Строковая величина с признаком конца строки, содержащая имя текущего ключевого контейнера. Подробнее см. LPSZ_CONTAINER_NAME.
PP_ENUMALGS | Поддерживаемые алгоритмы. Подробнее см. CryptGetProvParam().
PP_ENUMALGS_EX | Поддерживаемые алгоритмы. Подробнее см. CryptGetProvParam().
PP_ENUMCONTAINERS | Имена ключевых контейнеров. Строковая величина с признаком конца стороки, содержащая имя одного из ключевых контейнеров, поддерживаемых криптопровайдером. Прикладные программы читают указанный параметр неоднократно для перечисления всех ключевых контейнеров, поддерживаемых криптопровайдером.
PP_PROVTYPE | Тип криптопровайдера. Задается величиной DWORD.
PP_IMPTYPE Тип реализации криптопровайдера. Задается величиной DWORD. В настоящее время определены следующие типы реализации:
  • CRYPT_IMPL_HARDWARE
  • CRYPT_IMPL_SOFTWARE
  • CRYPT_IMPL_MIXED
  • CRYPT_IMPL_UNKNOWN
PP_NAME | Строковая величина с признаком конца строки, содержащая имя криптопровайдера. Соответствует вхождениям "CSP Name", которые программа setup установила в Windows® Registry.
PP_VERSION | Версия криптопровайдера. Задается величиной DWORD. Например, версия 1.0 представляется как 0x00000100.
PP_KEYSPEC | Тип ключа. Задается величиной DWORD.
PP_KEYX_KEYSIZE_INC | Модуль открытого ключа обмена. Задается величиной DWORD.
PP_SIG_KEYSIZE_INC | Модуль открытого ключа ЭЦП. Задается величиной DWORD.
PP_KEYSET_SEC_DESCR | Возвращает дескриптор безопасности раздела реестра Windows, где хранятся ключи пользователя.
PP_ENUMOIDS_EX | Поддерживаемые параметры алгоритмов. Перечисляются строковые величины - OID поддерживаемых наборов параметров алгоритмов.
PP_HASHOID | OID текущих параметров алгоритма функции хеширования.
PP_SIGNATUREOID | OID текущих параметров алгоритма подписи.
PP_DHOID | OID текущих параметров алгоритма Диффи-Хеллмана.
PP_CIPHEROID | OID текущих параметров алгоритма шифрования.
PP_CHECKPUBLIC | Передаёт в pbData значение флага проверки открытого ключа.
PP_RANDOM | Выдаёт в pbData ключевой блоб типа SIMPLEBLOB (см. CRYPT_SIMPLEBLOB) для установки программного ДСЧ провайдера уровня ядра ОС. Если контекст криптопровайдера hProv открыт в режиме CRYPT_VERIFYCONTEXT, то предварительно будут получены случайные числа с физического или клавиатурного ДСЧ. См. описание параметра PP_USE_HARDWARE_RNG CPSetProvParam().
PP_LAST_ERROR | Код последней ошибки криптопровайдера. В pbData буфер будет помещена величина DWORD - код последней ошибки, возвращённой одной из функций криптопровайдера. Коды ошибок даны в файле WinCryptEx.h.
PP_MUTEX_ARG | Для использования в ядре ОС. Возвращает значение последнего аргумента функции mutex_init (указатель на обработчик прерывания) для всех mutex, используемых при работе CSP.
pbData
[out] Буфер данных параметра. Функция копирует соответствующие параметру данные в буфер. Формат этих данных зависит от значения dwParam. Если аргумент функции - NULL, то данные не копируются. Требуемый размер буфера в байтах возвращается в pdwDataLen. Подробнее см. Возвращение данных неопределенной длины. Как отмечено в CryptGetProvParam(), когда читается один из параметров перечисления, возвращенное в pdwDataLen значение будет равно размеру самого большого элемента в списке перечисления.
pdwDataLen
[in/out] Адрес длины данных параметра. При вызове функции указанный аргумент содержит размер передаваемого буфера pbData в байтах. После возврата из неё аргумент установливается числом байтов данных параметра, скопированных в буфер pbData. Если буфер, соответствующий pbData, недостаточно велик, чтобы в него копировать запрошенные данные, через функцию GetLastError будет возвращен код ошибки ERROR_MORE_DATA. В этом случае требуемый размер буфера возвращается в pdwDataLen. Если эта функция завершается с кодом ошибки, отличным от ERROR_MORE_DATA, в этом аргументе возвращается ноль.
dwFlags
[in] Значения флагов. В настоящее время определены следующие значения флагов:
Значение dwFlags | Описание
CRYPT_FIRST | Когда читается параметр перечисления (например, PP_ENUMALGS, PP_ENUMALGS_EX или PP_ENUMCONTAINERS) и установлен этот флаг, должен быть возвращен первый элемент в списке перечисления. Иначе - возвращается следующий элемент в списке. Если флажок установлен, и читается параметр неперечисления, возвращается код ошибки NTE_BAD_FLAGS.
CRYPT_MACHINE_KEYSET | Когда читается параметр перечисления PP_ENUMCONTAINERS, может быть определен флаг CRYPT_MACHINE_KEYSET. Этот флаг должен быть установлен, если нужно, чтобы перечисление проходило в разделе HKEY_LOCAL_MACHINE, а не в разделе HKEY_CURRENT_USER (значение по умолчанию) системного реестра.
SECURITY_INFORMATION Если dwParam установлен в PP_KEYSET_SEC_DESCR, будет возвращен дескриптор безопасности раздела реестра, содержащего ключевой контейнер. В этом случе dwFlags используется, чтобы передать битовые флаги, объединяемые поразрядной операцией OR. Указатель на дескриптор безопасности возвращается в аргументе pbData, длина дескриптора безопасности возвращается в аргументе pcbData. Для получения дополнительной информации, см. RegGetKeySecurity и RegSetKeySecurity. Следующий список содержит имена битов, определяющих затребованную информацию о безопасности.
  • OWNER_SECURITY_INFORMATION - Указывает идентификатор владельца упомянутого объекта.
  • GROUP_SECURITY_INFORMATION - Указывает идентификатор первичный группы упомянутого объекта.
  • DACL_SECURITY_INFORMATION - Указывает идентификатор дискреционного ACL упомянутого объекта.
  • SACL_SECURITY_INFORMATION - Указывает идентификатор системного ACL упомянутого объекта.

Возвращает:

При успешном завершении функция возвращает TRUE, в противном случае возвращается FALSE. Если возвращается FALSE, соответствующий код ошибки (см. таблицу) может быть получен через функцию GetLastError().
Возвращаемые значения | Описание
ERROR_MORE_DATA | Размер буфера pbData не достаточен для копирования затребованных данных.
NTE_BAD_FLAGS | Параметр dwFlags имеет запрещенное значение.
NTE_BAD_TYPE | dwParam определяет неизвестный параметр.
SCARD_W_CANCELLED_BY_USER | Пользователь прервал операцию нажатием клавиши Cancel
SCARD_W_WRONG_CHV | Пользователь ввел неправильный пароль или пароль, установленный функцией SetProvParam, неправильный
SCARD_E_INVALID_CHV | Пользователь ввел пароль с нарушением формата или пароль, установленный функцией SetProvParam, имеет неправильный формат. Например, пароль имеет недопустимую длину или содержит недопустимые символы.
SCARD_W_CHV_BLOCKED | Ввод Pin-кода был заблокирован смарт-картой, т.к. исчерпалось количество попыток, разрешенное картой для ввода.

Требования:

Windows NT/2000/XP: Необходимо Windows NT 4.0 SP5 или старше с Internet Explorer 5.0 или старше.
Windows 98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле Wincrypt.h.
Solaris: Прототип описан в файле CSP_Wincrypt.h.

См. также:

CPAcquireContext() , CPSetProvParam() , CPGetProvParam() в MS CSP , CryptGetProvParam() в MS CryptoAPI 2.0


CPReleaseContext

Функция CPReleaseContext().

Используется для удаления дескриптора криптопровайдера, созданного функцией CPAcquireContext().

BOOL WINAPI CPReleaseContext (
  HCRYPTPROV hProv,
  DWORD dwFlags
);

Параметры:

hProv
[in] Дескриптор криптопровайдера. Получается через запрос функции CPAcquireContext().
dwFlags
[in] Значения флагов. Параметр зарезервирован для будущего использования и должен быть 0.

Возвращает:

При успешном завершении функция возвращает TRUE, в противном случае возвращается FALSE. Если возвращается FALSE, соответствующий код ошибки (см. таблицу) может быть получен через функцию GetLastError().
Возвращаемые значения | Описание
NTE_BAD_FLAGS | Параметр dwFlags имеет ненулевое значение.

Примечание:

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

Требования:

Windows NT/2000/XP: Необходимо Windows NT 4.0 SP5 или старше с Internet Explorer 5.0 или старше.
Windows 98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле Wincrypt.h.
Solaris: Прототип описан в файле CSP_Wincrypt.h.

См. также:

CPAcquireContext() , CPReleaseContext() в MS CSP , CryptReleaseContext() в MS CryptoAPI 2.0


CPSetProvParam

Функция CPSetProvParam().

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

BOOL WINAPI CPSetProvParam (
  HCRYPTPROV hProv,
  DWORD dwParam,
  BYTE * pbData,
  DWORD dwFlags
);

Параметры:

hProv
[in] Дескриптор криптопровайдера. Получается через запрос функции CPAcquireContext().
dwParam
[in] Аргумент, принимающий следующие значения:
Значение dwParam | Содержимое буфера pbData
PP_KEYSET_SEC_DESCR | Устанавливает дескриптор безопасности раздела реестра Windows, где хранятся ключи пользователя. Значение дескриптора передаётся в pbData.
PP_HASHOID | Устанавливает идентификатор алгоритма функции хеширования.
PP_CIPHEROID | Устанавливает идентификатор алгоритма шифрования.
PP_SIGNATUREOID | Устанавливает идентификатор алгоритма подписи.
PP_DHOID | Устанавливает идентификатор алгоритма Диффи-Хеллмана.
PP_KEYEXCHANGE_PIN | Задаёт пароль (PIN) для доступа к ключу AT_KEYEXCHANGE, в противном случае он запрашивается у пользователя посредством UI (если не был установлен флаг CRYPT_SILENT, см. CPAcquireContext()). Если pbData - NULL, то ранее запомненный пароль забывается (для доступа к ключу потребуется повторный ввод пароля).
PP_SIGNATURE_PIN | Задаёт пароль (PIN) для доступа к ключу AT_SIGNATURE, в противном случае он запрашивается у пользователя посредством UI (если не был установлен флаг CRYPT_SILENT, см. CPAcquireContext()). Если pbData - NULL, то ранее запомненный пароль забывается (для доступа к ключу потребуется повторный ввод пароля).
PP_CHANGE_PASSWORD | Задаёт новый пароль для контейнера hProv. В противном случае он запрашивается у пользователя посредством UI (если не был установлен флаг CRYPT_SILENT, см. CPAcquireContext()). pbData - указатель на структуру типа CRYPT_CHANGE_PIN_PARAM.
PP_ENCRYPTION_CONTAINER | Задаёт описание контейнера (имя, HANDLE, пароль), на ключе которого зашифровано содержимое контейнера hProv. В противном случае он запрашивается у пользователя посредством UI (если не был установлен флаг CRYPT_SILENT, см. CPAcquireContext()). pbData - указатель на структуру типа CRYPT_CHANGE_PIN_PARAM.
PP_USE_HARDWARE_RNG Иницирует добавление к ДСЧ контекста криптопровайдера hProv значения с физического или клавиатурного ДСЧ. В случае, если в данной системе поддерживается только биологический ДСЧ, то выдаётся UI для ввода событий мыши и/или клавиатуры (если не был установлен флаг CRYPT_SILENT, см. CPAcquireContext()).

Обычно, при отсуствии в системе физического ДСЧ, данные с клавиатурного (клавиатура, мышь) ДСЧ добавляются в обязательном порядке к контексту криптопровайдера (в контейнер ключевой информации) только при создании постоянных ключей AT_KEYEXCHANGE или AT_SIGNAUTURE функцией CPGenKey().
PP_RANDOM | Получает из pbData ключевой блоб типа CRYPT_SIMPLEBLOB для установки программного ДСЧ уровня ядра ОС. Данные передаются в форме BLOB структуры, где член структуры pbData указавает на данные, а cbData передаёт длину данных. См. описание параметра PP_RANDOM функции CPGetProvParam().
PP_CHECKPUBLIC | Получает из pbData значение флага проверки открытого ключа. Если значение pbData равно 1, при импорте публичного ключа проверяется его корректность, если 0, проверка производится, если флаг установлен по параметру PP_ADMIN_CHECKPUBLIC. Публичный ключ, соответствующий ГОСТ 34.10-2001, проверяется всегда.
PP_ADMIN_CHECKPUBLIC | Получает из pbData значение флага проверки открытого ключа и устанавливает его в реестр (раздел HKLM\SOFTWARE\Crypto Pro\Settings\Provider, значение CheckPublic типа REG_DWORD). Если значение флага, установленного в реестре равно 1, при импорте публичного ключа проверяется его корректность независимо от установки пользователя по параметру PP_CHECKPUBLIC, если 0, проверка производится в зависимости от установки по параметру PP_CHECKPUBLIC. Публичный ключ, соответствующий ГОСТ 34.10-2001, проверяется всегда.
PP_MUTEX_ARG | Для использования в ядре ОС. Устанавливает значение последнего аргумента функции mutex_init (указатель на обработчик прерывания) для всех mutex, используемых при работе CSP. Этот параметр должен быть установлен до первого вызова CPAcquireContext().
pbData
[in] Буфер данных параметра. Этот буфер при обращении к функции должен содержать данные, которые соответствуют типу параметра, помещённому в dwParam. Формат данных зависит от типа параметра.
dwFlags
[in] Значения флагов. Используются следующие значения флагов:
Значение dwFlags Описание
SECURITY_INFORMATION Флаг устанавливается,если dwParam установлен в дескриптор безопасности раздела реестра PP_KEYSET_SEC_DESCR,содержащего ключевой контейнер. Указатель на дескриптор безопасности передаётся в аргументе pbData, его длина передаётся в аргументе pcbData. Используются следующие битовые флаги:
  • OWNER_SECURITY_INFORMATION - Указывает идентификатор владельца объекта.
  • GROUP_SECURITY_INFORMATION - Указывает идентификатор первичный группы объекта.
  • DACL_SECURITY_INFORMATION - Указывает идентификатор дискреционного ACL объекта.
  • SACL_SECURITY_INFORMATION - Указывает идентификатор системного ACL объекта.

Возвращает:

При успешном завершении функция возвращает TRUE, в противном случае возвращается FALSE. Если возвращается FALSE, соответствующий код ошибки (см. таблицу) может быть получен через функцию GetLastError.
Возвращаемые значения | Описание
NTE_BAD_DATA | Длина идентификатора главного ключа пользователя превышает максимально допустимую.
NTE_BAD_FLAGS | Величина dwFlags имеет ненулевое значение.
NTE_BAD_TYPE | dwParam определяет неизвестный параметр.
NTE_KEYSET_ENTRY_BAD | Нарушение целостности ключей в ОЗУ.
NTE_FAIL | Ошибка при считывании данных из системного реестра.
SCARD_W_CANCELLED_BY_USER | Пользователь прервал операцию нажатием клавиши Cancel
SCARD_W_WRONG_CHV | Пользователь ввел неправильный пароль или пароль, установленный функцией SetProvParam, неправильный
SCARD_E_INVALID_CHV | Пользователь ввел пароль с нарушением формата или пароль, установленный функцией SetProvParam(), имеет неправильный формат. Например, пароль имеет недопустимую длину или содержит недопустимые символы.
SCARD_W_CHV_BLOCKED | Ввод Pin-кода был заблокирован смарт-картой, т.к. исчерпалось количество попыток разрешенное картой для ввода.
NTE_TOKEN_KEYSET_STORAGE_FULL | Недостаточно места на носителе для сохранения информации.

Требования:

Windows NT/2000/XP: Необходимо Windows NT 4.0 SP5 или старше с Internet Explorer 5.0 или старше.
Windows 98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле Wincrypt.h.
Solaris: Прототип описан в файле CSP_Wincrypt.h.

См. также:

CPAcquireContext() , CPGetProvParam() , CPSetProvParam() в MS CSP , CryptSetProvParam() в MS CryptoAPI 2.0


Функции генерации и работы с ключами

Функции генерации и работы с ключами предназначены для генерации парных и обработки различных типов ключей, используемых в криптопровайдере.
Функции | Описание
BOOL WINAPI CPGenKey ( HCRYPTPROV hProv, ALG_ID AlgId, DWORD dwFlags, HCRYPTKEY *phKey) | Функция CPGenKey().
BOOL WINAPI CPDestroyKey ( HCRYPTPROV hProv, HCRYPTKEY hKey) | Функция CPDestroyKey().
BOOL WINAPI CPDeriveKey ( HCRYPTPROV hProv, ALG_ID AlgId, HCRYPTHASH hBaseData, DWORD dwFlags, HCRYPTKEY *phKey) | Функция CPDeriveKey().
BOOL WINAPI CPDuplicateKey ( HCRYPTPROV hProv, HCRYPTKEY hKey, DWORD *pdwReserved, DWORD dwFlags, HCRYPTKEY *phKey) | Функция CPDuplicateKey().
BOOL WINAPI CPExportKey ( HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTKEY hExpKey, DWORD dwBlobType, DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen) | Функция CPExportKey().
BOOL WINAPI CPGenRandom ( HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer) | Функция CPGenRandom().
BOOL WINAPI CPGetKeyParam ( HCRYPTPROV hProv, HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData, DWORD *pdwDataLen, DWORD dwFlags) | Функция CPGetKeyParam().
BOOL WINAPI CPGetUserKey ( HCRYPTPROV hProv, DWORD dwKeySpec, HCRYPTKEY *phUserKey) | Функция CPGetUserKey().
BOOL WINAPI CPImportKey ( HCRYPTPROV hProv, BYTE *pbData, DWORD dwDataLen, HCRYPTKEY hImpKey, DWORD dwFlags, HCRYPTKEY *phKey) | Функция CPImportKey().
BOOL WINAPI CPSetKeyParam ( HCRYPTPROV hProv, HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData, DWORD dwFlags) | Функция CPSetKeyParam().


CPDeriveKey

Функция CPDeriveKey().

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

BOOL WINAPI CPDeriveKey (
  HCRYPTPROV hProv,
  ALG_ID AlgId,
  HCRYPTHASH hBaseData,
  DWORD dwFlags,
  HCRYPTKEY * phKey
);

Параметры:

hProv
[in] Дескриптор криптопровайдера. Получается через запрос функции CPAcquireContext().
AlgId
[in] Идентификатор алгоритма шифрования, для которого должен быть произведен ключ.
Значение AlgId | Описание
CALG_G28147 | Ключ шифрования и/или имтозащиты данных по ГОСТ 28147-89. Впоследствии этот ключ можно пометить как ключ для импорта/экспорта с помощью функции CPSetKeyParam().
CALG_TLS1_ENC_KEY | Ключ шифрования на основе объекта TLS1_MASTER_HASH.
CALG_TLS1_MAC_KEY | Ключ имитозащиты на основе объекта TLS1_MASTER_HASH.
hBaseData
[in] Дескриптор объекта функции хэширования, используемый для обработки входных данных.
dwFlags
[in] Флаги определяют признаки производимого ключа сессии. В настоящее время определены следующие значения флагов:
Значение dwFlags | Описание
CRYPT_EXPORTABLE | Если флаг установлен, то произведённый ключ может быть передан из криптопровайдера в ключевой блоб через функцию CPExportKey(). Если флаг не установлен, ключ не будет экспортируемым и будет доступен только в пределах текущей сессии приложению, которое создало этот ключ. Действие этого флага не распространяются на открытый ключ ключевых пары.
CRYPT_SERVER | Если при работе с TLS флаг установлен, то создается ключ шифрования сервера, если не установлен - создается ключ шифрования клиента.
phKey
[out] Адрес, по которому функция копирует дескриптор произведённого ключа.

Возвращает:

При успешном завершении функция возвращает TRUE, в противном случае возвращается FALSE. Если возвращается FALSE, соответствующий код ошибки (см. таблицу) может быть получен через функцию GetLastError.
Возвращаемые значения | Описание
NTE_BAD_ALGID | Параметр AlgId определяет алгоритм, который не поддерживается криптопровайдером.
NTE_BAD_FLAGS | Величина dwFlags имеет ошибочное значение.
NTE_NO_MEMORY | Криптопровайдер во время операции исчерпал память.
NTE_FAIL | Ошибка при считывании данных из системного реестра.
GPE_CORRUPT_KEYCONTEXT | Нарушение целостности ключей.

Примечание:

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

Требования:

Windows NT/2000/XP: Необходимо Windows NT 4.0 SP5 или старше с Internet Explorer 5.0 или старше.
Windows 98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле Wincrypt.h.
Solaris: Прототип описан в файле CSP_Wincrypt.h.

См. также:

CPDestroyKey() , CPGenKey() , CPDeriveKey() в MS CSP , CryptDeriveKey() в MS CryptoAPI 2.0


CPDestroyKey

Функция CPDestroyKey().

Удаляет ключ, передаваемый через параметр hKey. После удаления ключ (дескриптор ключа) не может использоваться.

BOOL WINAPI CPDestroyKey (
  HCRYPTPROV hProv,
  HCRYPTKEY hKey
);

Параметры:

hProv
[in] Дескриптор криптопровайдера. Получается через запрос функции CPAcquireContext().
hKey
[in] Дескриптор удаляемого ключа.

Возвращает:

При успешном завершении функция возвращает TRUE, в противном случае возвращается FALSE. Если возвращается FALSE, соответствующий код ошибки (см. таблицу) может быть получен через функцию GetLastError().
Возвращаемые значения | Описание
NTE_BAD_TYPE | Тип алгоритма hKey ошибочен.

Требования:

Windows NT/2000/XP: Необходимо Windows NT 4.0 SP5 или старше с Internet Explorer 5.0 или старше.
Windows 98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле Wincrypt.h.
Solaris: Прототип описан в файле CSP_Wincrypt.h.

См. также:

CPDeriveKey() , CPGenKey() , CPGetUserKey() , CPDestroyKey() в MS CSP , CryptDestroyKey() в MS CryptoAPI 2.0


CPDuplicateKey

Функция CPDuplicateKey().

Создает копию заданного ключа, включая все его переменные, определяющие внутреннее состояние ключа (например, вектор IV).

BOOL WINAPI CPDuplicateKey (
  HCRYPTPROV hProv,
  HCRYPTKEY hKey,
  DWORD * pdwReserved,
  DWORD dwFlags,
  HCRYPTKEY * phKey
);

Параметры:

hProv
[in] Дескриптор криптопровайдера. Получается через запрос функции CPAcquireContext().
hKey
[in] Дескриптор исходного (копируемого) ключа. Возможно дублирование только ключей класса ALG_CLASS_DATA_ENCRYPT.
pdwReserved
[in] Параметр зарезервирован для будущего использования и должен быть NULL.
dwFlags
[in] Параметр зарезервирован для будущего использования и должен быть 0.
phKey
[out] Адрес, по которому функция возвращает дескриптор скопированного ключа.

Возвращает:

При успешном завершении функция возвращает TRUE, в противном случае возвращается FALSE. Если возвращается FALSE, соответствующий код ошибки (см. таблицу) может быть получен через функцию GetLastError().
Возвращаемые значения | Описание
NTE_BAD_KEY | Ключевой контейнер не был открыт и, возможно, не существует.

Требования:

Windows NT/2000/XP: Необходимо Windows NT 4.0 SP5 или старше с Internet Explorer 5.0 или старше.
Windows 98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле Wincrypt.h.
Solaris: Прототип описан в файле CSP_Wincrypt.h.

См. также:

CPDestroyKey() , CPDuplicateKey() в MS CSP , CryptDuplicateKey() в MS CryptoAPI 2.0


CPExportKey

Функция CPExportKey().

Используется для экспорта криптографических ключей из ключевого контейнера криптопровайдера, сохраняя их в защищённом виде.

BOOL WINAPI CPExportKey (
  HCRYPTPROV hProv,
  HCRYPTKEY hKey,
  HCRYPTKEY hExpKey,
  DWORD dwBlobType,
  DWORD dwFlags,
  BYTE * pbData,
  DWORD * pdwDataLen
);

Параметры:

hProv
[in] Дескриптор криптопровайдера. Получается через запрос функции CPAcquireContext().
hKey
[in] Дескриптор экспортируемого ключа.
hExpKey
[in] Дескриптор ключа, на котором осуществляется криптографическая защита экспортируемого ключа. Это должен быть ключ, общий с получателем корреспонденции. Зашифрованные данные ключа помещаются в ключевой блоб, предназначенный для внешнего хранения и передачи по каналам связи. Алгоритмы функции экспорта ключей гарантируют, что только пользователь предназначения сможет использовать этот ключевой блоб. Для защиты ключа используется алгоритм, указанный при создании ключа экспорта. Если ключевой блоб не должен быть зашифрован (например, тип ключевого блоба - PUBLICKEYBLOB), этот параметр должен быть нулевой.
dwBlobType
[in] Тип ключевого блоба, предназначенного для экспорта ключа. В настоящее время определены три типа ключевых блобов:
Тип | Использование
SIMPLEBLOB | Используется для транспортировки ключа сессии. pbData указывает на структуру CRYPT_SIMPLEBLOB.
PUBLICKEYBLOB | Используется для транспортировки открытых ключей. pbData указывает на структуру CRYPT_PUBLICKEYBLOB.
PRIVATEKEYBLOB | Используется для транспортировки ключевых пар (секретных ключей). pbData указывает на структуру CRYPT_PRIVATEKEYBLOB.
dwFlags
[in] Значения флагов. Параметр зарезервирован для будущего использования и должен быть 0.
pbData
[in] Буфер данных, куда функция копирует ключевой блоб.
pdwDataLen
[in/out] Адрес длины ключевого блоба. При вызове функции указанный параметр содержит число байтов в буфере pbData. После выполнения функции параметр будет установлен числом байтов данных, скопированных в буфер pbData. Если буфер, соответствующий pbData, недостаточно большой, будет возвращен код ошибки ERROR_MORE_DATA через функцию SetLastError(). В этом случае требуемый размер буфера возвращается в pdwDataLen. Если эта функция завершается с кодом ошибки, отличным от ERROR_MORE_DATA, в этом параметре возвращается ноль.

Возвращает:

При успешном завершении функция возвращает TRUE, в противном случае возвращается FALSE. Если возвращается FALSE, соответствующий код ошибки (см. таблицу) может быть получен через функцию GetLastError().
Возвращаемые значения | Описание
ERROR_MORE_DATA | Буфер pbData недостаточно большой, чтобы копировать затребованные данные.
NTE_BAD_FLAGS | Величина dwFlags имеет ненулевое значение.
NTE_BAD_KEY | Один или оба из ключей, указанных hKey и hExpKey, не действительны.
NTE_BAD_KEY_STATE | Попытка экспорта ключа, когда право экспорта криптопровайдером не предоставлено; попытка экспорта на ключе, для которого разрешение экспортировать не установлено.
NTE_BAD_TYPE | dwBlobType параметр определяет неизвестный тип блоба.
NTE_NO_MEMORY | Криптопровайдер во время операции исчерпал память.
NTE_FAIL | Ошибка при считывании данных из системного реестра.
GPE_CORRUPT_KEYCONTEXT | Нарушение целостности ключей.

Примечание:

Обычно для согласования (экспорта/импорта) сессионного ключа применяют алгоритм Диффи-Хеллмана. В этом случае ключ парной связи (ключ экспорта/импорта сессионного ключа) порождается операцией импорта (см. CPImportKey()) открытого ключа получателя (отправителя) на ключевой паре отправителя (получателя). Т.е. для экспорта сессионного ключа следует выполнить следующие шаги:

  • Импорт блоба открытого ключа получателя на своей ключевой паре;
  • Экспорт сессионого ключа на ключе парной связи.
      ...
      CPGetUserKey(hProv, AT_KEYEXCHANGE, &hUserKey);
      ...
      CPGenKey(hProv, CALG_G28147, CRYPT_EXPORTABLE, &hSessionKey);
      ...
      CPImportKey(hProv, pbRecipentPublicKey, cbRecipentPublicKey, hUserKey, 0, &hExchKey);
      CPExportKey(hProv, hSessionKey, hExchKey, SIMPLEBLOB, 0, pbSessionKeyForRecipient, &cbSessionKeyForRecipient);
      ...
В ядре ОС не поддерживается возможность работы с долговременными ключами. Поэтому ключ сессии (на файл или ассоциацию) должен быть передан из поддерживающего сервиса (демона).
      ...
      // Инициализация работы с драйвером
      CPGetProvParam(hProv, PP_RANDOM, pbRandomBlobToDriver, cbRandomBlobToDriver);
      ...
      // Передать инициализатор ДСЧ (pbRandomBlobToDriver) в драйвер и
      // получить от него случайную последовательность (pbRandomFromDriver).
      ...
      CPCreateHash(hProv, CALG_GR3411, 0, 0, &hDrvHash);
      CPHashData(hProv, hDrvHash, "DriverDaemon", sizeof("DriverDaemon"), 0);
      CPHashData(hProv, hDrvHash, pbRandomBlobToDriver, cbRandomBlobToDriver, 0);
      CPHashData(hProv, hDrvHash, pbRandomFromDriver, cbRandomFromDriver, 0);
      CPDeriveKey(hProv, hDrvHash, &hDrvKey);
      CPDestroyHash(hProv, hDrvHash);
      ...
      // Пороизводство ключа сессии (файла, ассоциации) и подготовка
      // его для передачи получателю и в драйвер
      CPImportKey(hProv, pbRecipentPublicKey, cbRecipentPublicKey, hUserKey, 0, &hExchKey);
      CPExportKey(hProv, hSessionKey, hExchKey, SIMPLEBLOB, 0, pbSessionKeyForRecipient, &cbSessionKeyForRecipient);
      CPExportKey(hProv, hSessionKey, hDrvKey, SIMPLEBLOB, 0, pbSessionKeyForDriver, &cbSessionKeyForDriver);
      ...
      // Передать pbSessionKeyForDriver в драйвер
      ...
На основе этого ключа получаются ключи блоков (пакетов) с помощью функций CPGenKey(), CPDeriveKey() или алгоритма диверсификации ключа в функции CPImportKey().
      ...
      // Инициализация работы с демоном (сервисом)
      ...
      // Получить инициализатор ДСЧ (pbRandomBlobFromDaemon) в драйвер.
      ...
      CPSetProvParam(hProv, PP_RANDOM, pbRandomBlobFromDaemon);
      CPGenRandom(hProv, cbRandomToDaemon, pbRandomToDaemon);
      CPCreateHash(hProv, CALG_GR3411, 0, 0, &hDmnHash);
      CPHashData(hProv, hDmnHash, "DriverDaemon", sizeof("DriverDaemon"), 0);
      CPHashData(hProv, hDmnHash, pbRandomBlobFromDaemon, cbRandomBlobFromDaemon, 0);
      CPHashData(hProv, hDmnHash, pbRandomToDaemon, cbRandomToDaemon, 0);
      CPDeriveKey(hProv, hDmnHash, &hDmnKey);
      CPDestroyHash(hProv, hDmnHash);
      ...
      // Передать случайную последовательность демону (сервису).
      ...
      // Получить pbSessionKeyFromDaemon из демона (сервиса)
      ...
      CPImportKey(hProv, pbSessionKeyFromDaemon, &cbSessionKeyFromDaemon, hDmnKey, 0, &hSessionKey);
      ...
      // Вариант получения ключа блока (пакета) на основе ключа сесcии (файла, ассоциации)
      // с помощью CPGenKey.
      CPGenKey(hProv, CALG_G28147, CRYPT_EXPORTABLE, &hBlkKey);
      CPExportKey(hProv, hBlkKey, hSessionKey, SIMPLEBLOB, 0, pbBlkBlob, &cbBlkBlob);
      ...
      // Вариант получения ключа блока (пакета) на основе ключа сесcии (файла, ассоциации)
      // с помощью CPDeriveKey.
      CPCreateHash(hProv, CALG_GR3411, 0, 0, &hHash);
      CPHashData(hProv, hHash, "DeriveBlkKey", sizeof("DeriveBlkKey"), 0);
      CPHashSessionKey(hProv, hHash, hSessionKey, 0);
      CPHashData(hProv, hHash, &dwBlockNumber, sizeof(dwBlockNumber), 0);
      CPDeriveKey(hProv, CALG_G28147, hHash, 0, &hBlkKey);
      CPDestroyHash(hProv, hHash);
      ...
      // Вариант получения ключа блока (пакета) на основе ключа сесcии (файла, ассоциации)
      // с помощью возможности диверсификации ключа функцией CPImportKey.
        // bBlockNumber байтовая последовательность, диверсифицирующая ключ.
      Blob.DiversBlobHeader.BlobHeader.bType = DIVERSKEYBLOB;
      Blob.DiversBlobHeader.BlobHeader.bVersion = 0x20;
      Blob.DiversBlobHeader.BlobHeader.reserverd = 0;
      Blob.DiversBlobHeader.BlobHeader.aiKeyAlg = CALG_G28147;
      Blob.DiversBlobHeader = CALG_PRO_DIVERS;
      Blob.DiversBlobHeader = 0x31564944;
        Blob.DiversBlobHeader = sizeof(bBlockNumber);
      CopyMemory((LPBYTE)Blob.bDiversData,bBlockNumber,sizeof(bBlockNumber));
      CPImportKey(hProv, &Blob, sizeof(Blob), hSessionKey, 0, &hBlkKey);
      ...

Требования:

Windows NT/2000/XP: Необходимо Windows NT 4.0 SP5 или старше с Internet Explorer 5.0 или старше.
Windows 98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле Wincrypt.h.
Solaris: Прототип описан в файле CSP_Wincrypt.h.
Ядро ОС: Поддерживается только типы SIMPLEBLOB и DIVERSKEYBLOB.

См. также:

CPImportKey() , CPExportKey() в MS CSP , CryptExportKey() в MS CryptoAPI 2.0


CPGenKey

Функция CPGenKey().

Производит случайные криптографические ключи или парные (секретный/открытый) ключи.

BOOL WINAPI CPGenKey (
  HCRYPTPROV hProv,
  ALG_ID AlgId,
  DWORD dwFlags,
  HCRYPTKEY * phKey
);

Параметры:

hProv
[in] Дескриптор криптопровайдера. Получается через запрос функции CPAcquireContext().
AlgId
[in] Идентификатор алгоритма шифрования или ЭЦП, для которого должен быть произведен ключ. Могут быть произведены ключи следующих классов:
  • временные симметричные ключи (сессионые ключи);
  • временные (эфемерные) ключевые пары алгоритмов Диффи-Хеллмана;
  • долговременные ключевые пары, сохраняемые в ключевом контейнере.

    Возможные сессионые ключи:
    Значение AlgId | Описание
    CALG_G28147 | Ключ шифрования и/или имтозащиты данных по ГОСТ 28147-89. В последствии этот ключ можно пометить как ключ для импорта/экспорта с помощью функции CPSetKeyParam().
    CALG_TLS1_MASTER | Специальный ключ для реализации протокола TLS.
    Возможные эфемерные ключи Диффи-Хеллмана:
    AlgId | Описание
    CALG_DH_EX_EPHEM | Эфемерная ключевая пара на базе ГОСТ Р 34.10-94. Предназначена для обмена сессионными ключами.
    CALG_DH_EL_EPHEM | Эфемерная ключевая пара на базе ГОСТ Р 34.10-2001. Предназначена для обмена сессионными ключами.
    Возможные долговременные ключевые пары:
    AlgId | Описание
    AT_KEYEXCHANGE | Производится ключевая пара, сохраняемая в ключевом контейнере. Предназначена для обмена сессионными ключами и ЭЦП. В качестве алгоритма ключевой пары выбирается алгоритм по умолчанию для hProv, параметр PP_DHOID CPGetProvParam().
    CALG_DH_EX_SF | Производится ключевая пара согласно ГОСТ Р 34.10-94, сохраняемая в ключевом контейнере. Предназначена для обмена сессионными ключами и ЭЦП.
    CALG_DH_EL_SF | Производится ключевая пара согласно ГОСТ Р 34.10-2001, сохраняемая в ключевом контейнере. Предназначена для обмена сессионными ключами и ЭЦП.
    AT_SIGNATURE | Производится ключевая пара, сохраняемая в ключевом контейнере. Предназначена для ЭЦП. В качестве алгоритма ключевой пары выбирается алгоритм по умолчанию для hProv, параметр PP_SIGNATUREOID функции CPGetProvParam().
    CALG_GR3410 | Производится ключевая пара согласно ГОСТ Р 34.10-94, сохраняемая в ключевом контейнере. Предназначена для ЭЦП.
    CALG_GR3410EL | Производится ключевая пара согласно ГОСТ Р 34.10-2001, сохраняемая в ключевом контейнере. Предназначена для ЭЦП.
dwFlags
[in] Флаги определяют признаки производимого ключа. Размеры ключей подписи и ключей обмена могут быть установлены при выработке ключа. Размер ключа устанавливается в старших 16 битах параметра dwFlags, эти 16 бит представляют размер модуля в битах. В данной версии криптопровайдера размер модуля ключа равен 1024. В настоящее время определенны следующие флаги:
Значение dwFlags | Описание
CRYPT_EXPORTABLE Если этот флаг установлен, то произведённый ключ может быть передан из криптопровайдера в ключевой блоб через функцию CPExportKey(). Если этот флаг не установлен, ключ не будет экспортируемым и будет доступен только в пределах текущей сессии приложению, которое создало этот ключ. Действие этого флага не распространяются на открытые ключи ключевой пары.

В текущей версии "КриптоПро CSP" экспорт секретных ключей ключевых пар невозможен.
CRYPT_USER_PROTECTED | Если этот флаг установлен, то при любом запросе на доступ к носителю секретного ключа пользователя выводится окно диалога, запрашивающего право доступа к ключу.
CRYPT_PREGEN | Если этот флаг установлен, то генерируется "пустая" ключевая пара обмена. Параметры этой ключевой пары должны быть установлены с использованием функции CPSetKeyParam().
phKey
[out] Адрес, по которому функция копирует дескриптор сформированного ключа (ключевой пары открытый/секретный ключи).

Возвращает:

При успешном завершении функция возвращает TRUE, в противном случае возвращается FALSE. Если возвращается FALSE, соответствующий код ошибки (см. таблицу) может быть получен через функцию GetLastError().
Возвращаемые значения | Описание
NTE_BAD_ALGID | Параметр AlgId определяет алгоритм, не поддерживаемый криптопровайдером. Эта ошибка возвращается также в случае попытки генерации пользовательских ключей AT_KEYEXCHANGE и AT_SIGNATURE криптопровайдером, сертифицированным по уровню KC2 и выше, при отсутствии физического ДСЧ в составе СКЗИ.
NTE_BAD_FLAGS | Величина dwFlags имеет ошибочное значение.
NTE_NO_MEMORY | Криптопровайдер во время операции исчерпал память.
NTE_FAIL | Ошибка при считывании данных из системного реестра.
GPE_CORRUPT_KEYCONTEXT | Нарушение целостности ключей.
SCARD_W_CANCELLED_BY_USER | Пользователь прервал операцию нажатием клавиши Cancel
SCARD_W_WRONG_CHV | Пользователь ввел неправильный пароль или пароль, установленный функцией SetProvParam(), неправильный
SCARD_E_INVALID_CHV | Пользователь ввел пароль с нарушением формата или пароль, установленный функцией SetProvParam(), имеет неправильный формат. Например, пароль имеет недопустимую длину или содержит недопустимые символы.
SCARD_W_CHV_BLOCKED | Ввод Pin-кода был заблокирован смарт-картой, т.к. исчерпалось количество попыток разрешенное картой для ввода.
NTE_TOKEN_KEYSET_STORAGE_FULL | Недостаточно места на носителе для сохранения информации.

Примечание:

Если при запросе функции CPAcquireContext() был создан ключевой контейнер с признаком CRYPT_VERIFYCONTEXT, прикладные программы не могут создавать долговременные ключевые пары. В этом случае функция CPGenKey() возвращает код ошибки NTE_PERM. Когда ключи порождаются для симметричного шифрования, по умолчанию ключ будет установлен в шифратор в режиме гаммирования с обратной связью (CFB) со случайным начальным вектором. Эти параметры может быть получены с использованием функции CPSetKeyParam() и частично изменены функцией CPSetKeyParam()

Функция CPGenKey() получает ключ с програмного ДСЧ контекста криптопровайдера hProv, который инициализируется при выполнении функции CPAcquireContext() c накопленного в контейнере ключевого носителя состояния ДСЧ и установленных в системе физических ДСЧ. Провайдер "КриптоПро CSP-ECC/TLS" гарантирует инициализацию состояния ДСЧ контейнера ключевого носителя с физического или, если нет физического, с клавиатурного ДСЧ.

В случае, если контекст криптопровайдера открыт в режиме CRYPT_VERIFYCONTEXT, и в системе не установлено физических ДСЧ, программный ДСЧ инициализируется с накапливаемого в реестре общесистемного состояния ДСЧ и накопленных состояний ДСЧ всех открытых ранее контейнеров ключевых носителей в рамках времени жизни разделяемой библиотеки "КриптоПро CSP-ECC/TLS". Для гарантированной инициализации программного ДСЧ с физического ДСЧ, в случае если ранее не открывались контейнеры ключевых носителей, следует использовать функцию CPSetProvParam() с флагом PP_USE_HARDWARE_RNG.

ФункцияCPGenKey() при выработке долговременных ключевых пар всегда использует физический ДСЧ. В случае, если контекст криптопровайдера hProv открыт в режиме CRYPT_SILENT (запрет UI, необходимый клавиатурному (клавиатура, мышь) ДСЧ), и в системе не установлен физический ДСЧ, выдаётся ошибка.

Требования:

Windows NT/2000/XP: Необходимо Windows NT 4.0 SP5 или старше с Internet Explorer 5.0 или старше.
Windows 98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле Wincrypt.h.
Solaris: Прототип описан в файле CSP_Wincrypt.h.
Ядро ОС: При использовании в ядре ОС CPGenKey допустимо вызывать только для производства ключей сессии.

См. также:

CPDestroyKey() , CPExportKey() , CPImportKey() , CPGetKeyParam() , CPSetKeyParam() , CPReleaseContext() , CPGenKey() в MS CSP , CryptGenKey() в MS CryptoAPI 2.0


CPGenRandom

Функция CPGenRandom().

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

BOOL WINAPI CPGenRandom (
  HCRYPTPROV hProv,
  DWORD dwLen,
  BYTE * pbBuffer
);

Параметры:

hProv
[in] Дескриптор криптопровайдера.
Указанный дескриптор получается через запрос функции CPAcquireContext().
dwLen
[in] Число байтов случайных данных, которые будут произведены.
pbBuffer
[in/out] Буфер, куда копируются случайные данные. Длина этого буфера в байтах передаётся параметром dwLen.

Возвращает:

При успешном завершении функция возвращает TRUE, в противном случае возвращается FALSE. Если возвращается FALSE, соответствующий код ошибки (см. таблицу) может быть получен через функцию GetLastError.
Возвращаемые значения | Описание
NTE_FAIL RPE_FAIL_STATBUFFER | Неудовлетворительная статистика датчика случайных чисел, контролируемая при открытии контейнера. Эта ошибка носит вероятностный характер. Для корректно работающей программы вероятность возникновения ошибки не превышает 10^(-4).
NTE_FAIL RPE_FAIL_TESTBUFFER | Неудовлетворительная постоянно действующая статистика датчика случайных чисел. Эта ошибка носит вероятностный характер. Для корректно работающей программы вероятность возникновения ошибки не превышает 10^(-16).
NTE_KEYSET_ENTRY_BAD | Данные не верно считаны из системного реестра.

Требования:

Windows NT/2000/XP: Необходимо Windows NT 4.0 SP5 или старше с Internet Explorer 5.0 или старше.
Windows 98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле Wincrypt.h.

См. также:

CryptGenRandom в MS CryptoAPI 2.0


CPGetKeyParam

Функция CPGetKeyParam().

Возвращает параметры ключа.

BOOL WINAPI CPGetKeyParam (
  HCRYPTPROV hProv,
  HCRYPTKEY hKey,
  DWORD dwParam,
  BYTE * pbData,
  DWORD * pdwDataLen,
  DWORD dwFlags
);

Параметры:

hProv
[in] Дескриптор криптопровайдера. Получается через запрос функции CPAcquireContext().
hKey
[in] Дескриптор ключа, параметры которого устанавливаются.
dwParam
[in] Параметр, принимающий следующие возможные значения:
Значение dwParam | Содержимое буфера pbData
KP_ALGID | Идентификатор алгоритма (ALG_ID), соответствующий данному ключу.
KP_PERMISSIONS | Флаги разрешения использования ключа. Задается величиной DWORD.
KP_IV | Начальный вектор инициализации (IV или синхропосылка) алгоритма шифрования.
KP_MODE Режим алгоритма шифрования. Задается величиной DWORD. Используются режимы шифрования:
  • CRYPT_MODE_ECB - ГОСТ 28147-89 режим простой замены;
  • CRYPT_MODE_OFB - ГОСТ 28147-89 режим гаммирования;
  • CRYPT_MODE_CFB - ГОСТ 28147-89 режим гаммирования с обратной связью.
  • CRYPT_MODE_CBC - блочный шифр с обратной связью на базе ГОСТ 28147-89;
KP_MODE_BITS | Глубина обратной связи. Задается величиной DWORD. По умолчанию значение этой величины равно 64, что соответствует режиму гаммирования с обратной связью ГОСТ 28147-89.
KP_MIXMODE | Дополнительный параметр ключа. Устанавливает режим преобразованием ключа после зашифрования каждых 1024 байт информации.
KP_KEYLEN | Длина ключа в битах. Задается величиной DWORD, указывающей число бит в ключе.
KP_BLOCKLEN | Длина блока в битах, обрабатываемого провайдером. Задается величиной DWORD, указывающей число бит в ключе в случае сессионного ключа, размер модуля р в случае ключевой пары на экспонециальной логике, размер модуля р в случае ключевой пары на базе эллиптической кривой.
KP_CIPHEROID | Идентификатор узла замены, устанавливаемого приложением. Строковая величина с признаком конца строки.
KP_DHOID | Идентификатор алгоритма Диффи-Хеллмана. Строковая величина с признаком конца строки.
KP_SIGNATUREOID | Идентификатор алгоритма подписи. Строковая величина с признаком конца строки.
KP_HASHOID | Идентификатор функции хеширования, устанавливаемой приложением. Строковая величина с признаком конца строки.
KP_Y | Открытый ключ ключевой пары.
pbData
[out] Буфер данных параметра. Функция копирует соответствующие параметру данные в буфер. Формат этих данных зависит от значения dwParam. Если параметр - NULL, то данные не копируются. Требуемый размер буфера в байтах возвращается в pdwDataLen. Подробнее см. Возвращение данных неопределенной длины.
pdwDataLen
[in/out] Адрес длины данных параметра. При вызове функции указанный параметр содержит число байтов в буфере pbData. После её выполнения параметр будет установлен числом байтов данных параметра, скопированных в буфер pbData. Если буфер, соответствующий pbData, недостаточно велик, чтобы в него копировать запрошенные данные, через функцию GetLastError() будет возвращен код ошибки ERROR_MORE_DATA. В этом случае требуемый размер буфера возвращается в pdwDataLen. Если эта функция завершается с кодом ошибки, отличным от ERROR_MORE_DATA, в этом параметре возвращается ноль.
dwFlags
[in] Значения флагов. Параметр зарезервирован для будущего использования и должен быть 0.

Возвращает:

При успешном завершении функция возвращает TRUE, в противном случае возвращается FALSE. Если возвращается FALSE, соответствующий код ошибки (см. таблицу) может быть получен через функцию GetLastError().
Возвращаемые значения | Описание
ERROR_MORE_DATA | Размер буфера pbData недостаточен для копирования затребованных данных.
NTE_BAD_FLAGS | Параметр dwFlags имеет ненулевое значение.
NTE_BAD_TYPE | Параметр dwParam передаёт неизвестное значение параметра.
NTE_PERM | Попытка чтения ключевых параметров, когда право чтения криптопровайдером не представлено.

Примечание:

Синхропосылка ключа для шифрования по алгоритму ГОСТ 28147-89 вырабатывается провайдером автоматически с установкой типа ключа CALG28147 (сессионный ключ). Эту синхропосылку рекомендуется получить на передающем конце из ключа с помощью функции CPGetKeyParam() для значения pvParam KP_IV. На приемном конце значение синхропосылки устанавливается на ключ функцией CPSetKeyParam() при значении pvParam KP_IV. Если требуется задание синхропосылки из приложения, то ее рекомендуется вырабатывать с помощью функции CPGenRandom(). Использовать в системе другие алгоритмы образования синхропосылок можно только по согласованию с разработчиком криптопровайдера.

Требования:

Windows NT/2000/XP: Необходимо Windows NT 4.0 SP5 или старше с Internet Explorer 5.0 или старше.
Windows 98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле Wincrypt.h.
Solaris: Прототип описан в файле CSP_Wincrypt.h.

См. также:

CPSetKeyParam() , CPGetKeyParam() в MS CSP , CryptGetKeyParam() в MS CryptoAPI 2.0


CPGetUserKey

Функция CPGetUserKey().

Возвращает дескриптор одной из постоянных ключевых пар в ключевом контейнере.

BOOL WINAPI CPGetUserKey (
  HCRYPTPROV hProv,
  DWORD dwKeySpec,
  HCRYPTKEY * phUserKey
);

Параметры:

hProv
[in] Дескриптор криптопровайдера.
Получается через запрос функции CPAcquireContext().
dwKeySpec
[in] Спецификация возвращаемого ключа. Следующие типы ключевых пар и ключей определены в настоящее время:
Значение | Описание
AT_KEYEXCHANGE | Ключевая пара обмена
AT_SIGNATURE | Ключевая пара цифровой подписи
phUserKey
[out] Адрес, по которому функция копирует дескриптор ключа.

Возвращает:

При успешном завершении функция возвращает TRUE, в противном случае возвращается FALSE. Если возвращается FALSE, соответствующий код ошибки (см. таблицу) может быть получен через функцию GetLastError().
Возвращаемые значения | Описание
NTE_NO_KEY | Ключ, указанный dwKeySpec параметром, не существует.
NTE_BAD_TYPE | Значение параметра dwKeySpec неизвестно.
SCARD_W_CANCELLED_BY_USER | Пользователь прервал операцию нажатием клавиши Cancel
SCARD_W_WRONG_CHV | Пользователь ввел неправильный пароль или пароль, установленный функцией SetProvParam(), неправильный
SCARD_E_INVALID_CHV | Пользователь ввел пароль с нарушением формата или пароль, установленный функцией SetProvParam(), имеет неправильный формат. Например, пароль имеет недопустимую длину или содержит недопустимые символы.
SCARD_W_CHV_BLOCKED | Ввод Pin-кода был заблокирован смарт-картой, т.к. исчерпалось количество попыток разрешенное картой для ввода.

Требования:

Windows NT/2000/XP: Необходимо Windows NT 4.0 SP5 или старше с Internet Explorer 5.0 или старше.
Windows 98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле Wincrypt.h.
Solaris: Прототип описан в файле CSP_Wincrypt.h.

См. также:

CPExportKey() , CPGenKey() , CPGetUserKey() в MS CSP , CryptGetUserKey() в MS CryptoAPI 2.0


CPImportKey

Функция CPImportKey().

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

BOOL WINAPI CPImportKey (
  HCRYPTPROV hProv,
  BYTE * pbData,
  DWORD dwDataLen,
  HCRYPTKEY hImpKey,
  DWORD dwFlags,
  HCRYPTKEY * phKey
);

Параметры:

hProv
[in] Дескриптор криптопровайдера. Получается через запрос функции CPAcquireContext().
pbData
[in] Буфер, содержащий ключевой блоб, произведенный с иcпользованием функции CPExportKey() данным или другим криптопровайдером, функционирующим на удаленном компьютере.
dwDataLen
[in] Длина ключевого блоба в байтах.
hImpKey
[in] Дескриптор ключа, на котором осуществляется снятие криптографической защиты импортируемого ключа. Значение этого параметра должно соответствовать значению hExpKey, определённому для функции CPExportKey() при создании ключевого блоба. Если ключевой блоб зашифрован на сессионном ключе, этот параметр должен содержать дескриптор на сессионный ключ. Если ключевой блоб не зашифрован (например, PUBLICKEYBLOB), то этот параметр не используется и должен быть равен нулю.
dwFlags
[in] Значение флага. Этот параметр в настоящее время используется только, когда ключевая пара (секретный/открытый ключи) импортируется в криптопровайдер (в форме PRIVATEKEYBLOB). В этом случае, если импортируемый ключ должен заново экспортироваться, в этот параметр должен быть помещен флаг CRYPT_EXPORTABLE. Если этот флаг не используется, вызовы к CryptExportKey() с дескриптором ключа будут терпеть неудачу.
phKey
[out] Адрес, по которому функция копирует дескриптор импортированного ключа.

Возвращает:

При успешном завершении функция возвращает TRUE, в противном случае возвращается FALSE. Если возвращается FALSE, соответствующий код ошибки (см. таблицу) может быть получен через функцию GetLastError.
Возвращаемые значения | Описание
NTE_BAD_DATA | Не прошёл контроль целостности импортируемого ключевого блоба.Ошибочная длина блоба.
NTE_BAD_FLAGS | Параметр dwFlags содержит ошибочную величину.
NTE_BAD_KEY | Один или оба из ключей, указанных hKey и hImpKey, не действительны. Байты в элементах заголовка ключевого блоба типа WORD, DWORD имеют обратный порядок по отношению к данной платформе.
NTE_BAD_TYPE | Тип ключевого блоба не поддерживается этим криптопровайдером и, возможно, ошибочен.
NTE_PERM | Попытка импорта ключа, когда право импорта криптопровайдером не предоставлено.
NTE_NO_MEMORY | Криптопровайдер во время операции исчерпал память.
NTE_FAIL | Нарушение целостности ключей в ОЗУ.
GPE_CORRUPT_KEYCONTEXT | Нарушение целостности ключей.
SCARD_W_CANCELLED_BY_USER | Пользователь прервал операцию нажатием клавиши Cancel
SCARD_W_WRONG_CHV | Пользователь ввел неправильный пароль или пароль, установленный функцией SetProvParam(), неправильный
SCARD_E_INVALID_CHV | Пользователь ввел пароль с нарушением формата или пароль, установленный функцией SetProvParam(), имеет неправильный формат. Например, пароль имеет недопустимую длину или содержит недопустимые символы.
SCARD_W_CHV_BLOCKED | Ввод Pin-кода был заблокирован смарт-картой, т.к. исчерпалось количество попыток, разрешенное картой для ввода.
NTE_TOKEN_KEYSET_STORAGE_FULL | Недостаточно места на носителе для сохранения информации.

Примечание:

Обычно для согласования (экспорта/импорта) сессионного ключа применяют алгоритм Диффи-Хеллмана. В этом случае ключ парной связи (ключ экспорта/импорта сессионного ключа) порождается операцией импорта открытого ключа получателя (отправителя) на ключевой паре отправителя (получателя). Т.е. для импорта сессионного ключа следует выполнить следующие шаги:

  • Импорт блоба открытого ключа отправителя на своей ключевой паре;
  • Импорт сессионого ключа на ключе парной связи.
          ...
      CPGetUserKey(hProv, AT_KEYEXCHANGE, &hUserKey);
      ...
      CPImportKey(hProv, pbSenderPublicKey, cbSenderPublicKey, hUserKey, 0, &hExchKey);
      CPImportKey(hProv, pbSessionKeyFromSender, &cbSessionKeyFromSender, hExchKey, 0, &hSessionKey);
      ...
В ядре ОС не поддерживается возможность работы с долговременными ключами. Поэтому ключ сессии (на файл или ассоциацию) должен быть передан из поддерживающего сервиса (демона).
      ...
      // Инициализация работы с драйвером
      CPGetProvParam(hProv, PP_RANDOM, pbRandomBlobToDriver, cbRandomBlobToDriver);
      ...
      // Передать инициализатор ДСЧ (pbRandomBlobToDriver) в драйвер и
      // получить от него случайную последовательность (pbRandomFromDriver).
      ...
      CPCreateHash(hProv, CALG_GR3411, 0, 0, &hDrvHash);
      CPHashData(hProv, hDrvHash, "DriverDaemon", sizeof("DriverDaemon"), 0);
      CPHashData(hProv, hDrvHash, pbRandomBlobToDriver, cbRandomBlobToDriver, 0);
      CPHashData(hProv, hDrvHash, pbRandomFromDriver, cbRandomFromDriver, 0);
      CPDeriveKey(hProv, hDrvHash, &hDrvKey);
      CPDestroyHash(hProv, hDrvHash);
      ...
      // Импорт ключа сессии (файла, ассоциации) от отправителя и подготовка
      // его для передачи в драйвер
      CPImportKey(hProv, pbSenderPublicKey, cbSenderPublicKey, hUserKey, 0, &hExchKey);
      CPImportKey(hProv, pbSessionKeyFromSender, &cbSessionKeyFromSender, hExchKey, 0, &hSessionKey);
      CPExportKey(hProv, hSessionKey, hDrvKey, SIMPLEBLOB, 0, pbSessionKeyForDriver, &cbSessionKeyForDriver);
      ...
      // Передать pbSessionKeyForDriver в драйвер
      ...
На основе этого ключа получаются ключи блоков (пакетов) с помощью CPGenKey(), CPDeriveKey() или алгоритма диверсификации ключа в функции CPImportKey().
      ...
      // Инициализация работы с демоном (сервисом)
      ...
      // Получить инициализатор ДСЧ (pbRandomBlobFromDaemon) в драйвер.
      ...
      CPSetProvParam(hProv, PP_RANDOM, pbRandomBlobFromDaemon);
      CPGenRandom(hProv, cbRandomToDaemon, pbRandomToDaemon);
      CPCreateHash(hProv, CALG_GR3411, 0, 0, &hDmnHash);
      CPHashData(hProv, hDmnHash, "DriverDaemon", sizeof("DriverDaemon"), 0);
      CPHashData(hProv, hDmnHash, pbRandomBlobFromDaemon, cbRandomBlobFromDaemon, 0);
      CPHashData(hProv, hDmnHash, pbRandomToDaemon, cbRandomToDaemon, 0);
      CPDeriveKey(hProv, hDmnHash, &hDmnKey);
      CPDestroyHash(hProv, hDmnHash);
      ...
      // Передать случайную последовательность демону (сервису).
      ...
      // Получить pbSessionKeyFromDaemon из демона (сервиса)
      ...
      CPImportKey(hProv, pbSessionKeyFromDaemon, &cbSessionKeyFromDaemon, hDmnKey, 0, &hSessionKey);
      ...
      // Вариант получения ключа блока (пакета) на основе ключа сесcии (файла, ассоциации)
      // с помощью CPGenKey.
      CPImportKey(hProv, pbBlkBlob, cbBlkBlob, hSessionKey, 0, &hBlkKey);
      ...
      // Вариант получения ключа блока (пакета) на основе ключа сесcии (файла, ассоциации)
      // с помощью CPDeriveKey.
        // bBlockNumber - указатель на байтовую последовательность, диверсифицирующая ключ.
      CPCreateHash(hProv, CALG_GR3411, 0, 0, &hHash);
      CPHashData(hProv, hHash, "DeriveBlkKey", sizeof("DeriveBlkKey"), 0);
      CPHashSessionKey(hProv, hHash, hSessionKey, 0);
      CPHashData(hProv, hHash, bBlockNumber, sizeof(dwBlockNumber), 0);
      CPDeriveKey(hProv, CALG_G28147, hHash, 0, &hBlkKey);
      CPDestroyHash(hProv, hHash);
      ...
      // Вариант получения ключа блока (пакета) на основе ключа сесcии (файла, ассоциации)
      // с помощью возможности диверсификации ключа функцией CPImportKey.
        // bBlockNumber байтовая последовательность, диверсифицирующая ключ.
      Blob.DiversBlobHeader.BlobHeader.bType = DIVERSKEYBLOB;
      Blob.DiversBlobHeader.BlobHeader.bVersion = 0x20;
      Blob.DiversBlobHeader.BlobHeader.reserverd = 0;
      Blob.DiversBlobHeader.BlobHeader.aiKeyAlg = CALG_G28147;
      Blob.DiversBlobHeader = CALG_PRO_DIVERS;
      Blob.DiversBlobHeader = 0x31564944;
        Blob.DiversBlobHeader = sizeof(bBlockNumber);
      CopyMemory((LPBYTE)Blob.bDiversData,bBlockNumber,sizeof(bBlockNumber));
      CPImportKey(hProv, &Blob, sizeof(Blob), hSessionKey, 0, &hBlkKey);
      ...

Требования:

Windows NT/2000/XP: Необходимо Windows NT 4.0 SP5 или старше с Internet Explorer 5.0 или старше.
Windows 98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле Wincrypt.h.
Solaris: Прототип описан в файле CSP_Wincrypt.h.
Ядро ОС: Поддерживается только типы SIMPLEBLOB и DIVERSKEYBLOB.

См. также:

CPExportKey() , CPGenKey() , CPImportKey() в MS CSP , CryptImportKey() в MS CryptoAPI 2.0


CPSetKeyParam

Функция CPSetKeyParam().

Устанавливает параметры ключа.

Параметры:

pbData
[in] Буфер данных параметра. При вызове функции буфер должен содержать данные, соответствующие значению параметра в dwParam. Формат данных зависит от типа параметра.
dwFlags
[in] Значения флагов. Параметр зарезервирован для будущего использования и должен быть 0.

BOOL WINAPI CPSetKeyParam (
  HCRYPTPROV hProv,
  HCRYPTKEY hKey,
  DWORD dwParam,
  BYTE * pbData,
  DWORD dwFlags
);

Параметры:

hProv
[in] Дескриптор криптопровайдера. Получается через запрос функции CPAcquireContext().
hKey
[in] Дескриптор ключа, параметры которого устанавливаются.
dwParam
[in] Параметр, принимающий следующие возможные значения:
Значение dwParam | Содержимое буфера pbData
KP_ALGID Идентификатор алгоритма ключа (ALG_ID), соответствующий данному ключу. Передаётся функции через буфер pbData. Возможо установить значение CALG_G28147 для ключей класса ALG_CLASS_DATA_ENCRYPT (сессионных ключей).
ALG_ID | Описание
CALG_G28147 | Ключ шифрования и/или имтозащиты данных по ГОСТ 28147-89. В последствии этот ключ можно пометить как ключ для импорта/экспорта с помощью функции CPSetKeyParam().
CALG_PRO_EXPORT | Ключ экспорта/импорта ключей типа CALG_G28147 для хранения на диске или передачи по каналу связи.
CALG_SIMPLE_EXPORT Ключ экспорта/импорта ключей типа CALG_G28147 по ГОСТ 28147-89 в режиме простой замены для хранения на ключевом носителе.

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

Недопустимо использование CALG_SIMPLE_EXPORT для экспорта/импорта ключей с целью хранения их диске.
CALG_TLS1_MASTER | Ключ для реализации протокола TLS.
CALG_TLS1_MAC_KEY | Ключ для реализации протокола TLS.
CALG_TLS1_ENC_KEY | Ключ для реализации протокола TLS.
KP_IV | Начальный вектор (IV). Последовательность байтов, содержащая IV, передаётся функции через буфер pbData.
KP_PADDING Способ дополнения. Величина DWORD, содержащая метод дополнения, используемый шифром ключа, передаётся функции через буфер pbData. В настоящее время определены следующие способы дополнения:
  • PKCS5_PADDING - PKCS 5.(См ПРИМЕЧАНИЕ в данном разделе и ПРИМЕЧАНИЕ к CryptSetKeyParam())
  • ZERO_PADDING - дополнение нулевыми байтами,
  • RANDOM_PADDING - дополнение случайными байтами.
KP_MODE Режим шифра. Задается величиной DWORD. Передаётся функции через буфер pbData. В следующем списке приведены режимы шифрования, определённые в настоящее время:
  • CRYPT_MODE_ECB - ГОСТ 28147-89 режим простой замены;
  • CRYPT_MODE_OFB - ГОСТ 28147-89 режим гаммирования;
  • CRYPT_MODE_CFB - ГОСТ 28147-89 режим гаммирования с обратной связью.
  • CRYPT_MODE_CBC - блочный шифр с обратной связью;
    • KP_MODE_BITS | Глубина обратной связи. Задается величиной DWORD. По умолчанию значение этой величины равно 64, что соответствует режиму гаммирования с обратной связью ГОСТ 28147-89.
    KP_MIXMODE | Дополнительный параметр ключа. Устанавливает режим преобразования ключа после зашифрования каждых 1024 байт информации. Режим преобразования ключа установлен по умолчанию. Выйти из этого режима можно, если для этого параметра pbData будет установлена в FALSE. Если pbData установлена в TRUE, устанавливается режим преобразования ключа. Размер pbData - 4 байта. Может быть установлен для ключей типа CALG_G28147. Задается величиной DWORD.
    KP_CIPHEROID | Идентификатор узла замены. Строковая величина с признаком конца строки.
    KP_DHOID | Идентификатор параметров ключа ГОСТ Р 34.10-94 и ГОСТ Р 34.10-2001 применяемых в алгоритме Диффи-Хеллмана. Строковая величина с признаком конца строки.
    KP_HASHOID | Идентификатор функции хеширования. Строковая величина с признаком конца строки.
    KP_CLIENT_RANDOM | Идентификатор величины ClientRandom, используемой с ключами типа CALG_TLS1_MASTER. Размер ClientRandom - 32 байта. Используется при преобразовании premaster_secret в master_secret и при генерации ключевой информации в момент создания хэша CALG_TLS1_MASTER_HASH
    KP_SERVER_RANDOM | Идентификатор величины ServerRandom, используемой с ключами типа CALG_TLS1_MASTER.Размер ServerRandom - 32 байта. Используется при преобразовании premaster_secret в master_secret и при генерации ключевой информации в момент создания хэша CALG_TLS1_MASTER_HASH
    KP_PREHASH | Идентификатор, используемый ключами типа CALG_TLS1_MASTER. Предварительно требуется установить KP_CLIENT_RANDOM и KP_SERVER_RANDOM. Вызов преобразует premaster_secret в master_secret
    KP_X | Секретный ключ в ключевой паре. 32 байта в форме little endian. Данные передаются в форме BLOB структуры, где член структуры pbData указавает на данные, а cbData передаёт длину данных.

    Параметры:

    pbData
    [in] Буфер данных параметра. При вызове функции буфер должен содержать данные, соответствующие значению параметра в dwParam. Формат данных зависит от типа параметра.
    dwFlags
    [in] Значения флагов. Параметр зарезервирован для будущего использования и должен быть 0.

    Возвращает:

    При успешном завершении функция возвращает TRUE, в противном случае возвращается FALSE. Если возвращается FALSE, соответствующий код ошибки (см. таблицу) может быть получен через функцию GetLastError.
    Возвращаемые значения | Описание
    NTE_BAD_FLAGS | Параметр dwFlags имеет ненулевое значение.
    NTE_BAD_TYPE | Параметр dwParam передаёт неизвестное значение параметра.
    NTE_PERM | Попытка чтения ключевых параметров, когда право чтения криптопровайдером не предоставлено.
    NTE_FIXEDPARAMETER Была произведена попытка установить параметры, постоянные для данного криптопровайдера.

    Примечание:

    ДОПОЛНЕНИЕ PKCS #5 Эта схема дополнения определена RSA Data Security, Inc. и описана в "Public-Key Cryptography Standards (PKCS)", PKCS #5, раздел 6.2. При использовании данной схемы, последовательность всегда дополняется знаками, даже в случае, когда её длина кратна длине блока шифрования. Последовательность дополнения состоит из байтов, каждый из которых равен числу дополнительных байтов. Если дополняется последовательность из 24 бит, последовательность дополнения равна “05 05 05 05 05”. Если дополняется 64 бита, последовательность дополнения равна “08 08 08 08 08 08 08 08”. При расшифровании, если расширение блока удовлнтворяет условиям дополнения PKCS #5, функция CPDecrypt() в переменной pdwDataLen, возвращает истинное значение длины открытого текста. Если расширение блока не удовлнтворяет условиям дополнения PKCS #5, функция CPDecrypt() возвращет ошибку NTE_BAD_DATA,а в переменной pdeDataLen значение длины шифрованного текста. Дополнение PKCS #5 не обеспечивает контроль целостности данных. ДОПОЛНЕНИЕ ZERO При использовании данной схемы, последовательность дополняется нулевыми байтами до наименьшей длины, кратний длине блока шифрования. ДОПОЛНЕНИЕ RANDOM При использовании данной схемы, последовательность дополняется случайными байтами до наименьшей длины, кратний длине блока шифрования. РЕЖИМ CRYPT_MODE_ECB В соответствии с требованиями ГОСТ 28147-89 режим шифроания простой заменой CRYPT_MODE_ECB может использоваться только для шифрования ключевой информации.

    Требования:

    Windows NT/2000/XP: Необходимо Windows NT 4.0 SP5 или старше с Internet Explorer 5.0 или старше.
    Windows 98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
    Файл описания: Прототип описан в файле Wincrypt.h.
    Solaris: Прототип описан в файле CSP_Wincrypt.h.

    См. также:

    CPGenKey() , CPGetKeyParam() , CPSetKeyParam() в MS CSP , CryptSetKeyParam() в MS CryptoAPI 2.0


Функции шифрования/расшифрования данных

Функции шифрования/расшифрования данных предназначены для выполнения операций, шифрования и расшифрования данных.
Функции | Описание
BOOL WINAPI CPEncrypt ( HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final, DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen, DWORD dwBufLen) | Функция CPEncrypt().
BOOL WINAPI CPDecrypt ( HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final, DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen) | Функция CPDecrypt().


CPDecrypt

Функция CPDecrypt().

Расшифровывает данные, предварительно зашифрованные функцией CPEncrypt(). Одновременно может быть произведено хэширование данных.

BOOL WINAPI CPDecrypt (
  HCRYPTPROV hProv,
  HCRYPTKEY hKey,
  HCRYPTHASH hHash,
  BOOL Final,
  DWORD dwFlags,
  BYTE * pbData,
  DWORD * pdwDataLen
);

Параметры:

hProv
[in] Дескриптор криптопровайдера. Получается через запрос функции CPAcquireContext().
hKey
[in] Дескриптор сессионного ключа, используемого для расшифрования данных.
hHash
[in] Дескриптор объекта хэширования. Если хэширование данных одновременно с их расшифрованием не требуется, этот параметр должен быть нулевой.
Final
[in] Булева величина. Определяет, является ли переданный функции блок последним расшифрованным блоком данных. Она должна быть установлена TRUE, если блок - последний или единственный, и FALSE – в противном случае.
dwFlags
[in] Значения флагов. Параметр зарезервирован для будущего использования и должен быть 0.
pbData
[in/out] Буфер, содержащий данные для расшифрования. После выполнения расшифрования открытый текст помещается в этот же буфер.
pdwDataLen
[in/out] Адрес длины данных. Параметр dwDataLen определяет число байтов шифртекста в буфере pbData. Через этот параметр функция возвращает указатель на число байтов открытого текста, помещенного в буфер pbData.

Возвращает:

При успешном завершении функция возвращает TRUE, в противном случае возвращается FALSE. Если возвращается FALSE, соответствующий код ошибки (см. таблицу) может быть получен через функцию GetLastError().
Возвращаемые значения | Описание
NTE_BAD_ALGID | Параметр AlgId определяет алгоритм, который не поддерживается криптопровайдером.
NTE_BAD_FLAGS | Величина dwFlags имеет ненулевое значение.
NTE_BAD_DATA | Данные для расшифрования недействительны. В частности, в блочных режимах шифрования, если Final = FALSE, а длина шифртекста не кратна длине блока шифрования, возвращается данная ошибка. Эта ошибка также возвращается в блочных режимах шифрования, если используется дополнение PKCS#5, Final = TRUE, а дополнение блока не удовлетворяет условиям дополнения PKCS#5.
NTE_BAD_LEN | Размер буфера для полученного открытого текста.
NTE_PERM | Право расшифрования на данном ключе криптопровайдером не предоставлено.
NTE_FAIL | Нарушение целостности ключей в ОЗУ.
GPE_CORRUPT_KEYCONTEXT | Нарушение целостности ключей.

Требования:

Windows NT/2000/XP: Необходимо Windows NT 4.0 SP5 или старше с Internet Explorer 5.0 или старше.
Windows 98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле Wincrypt.h.
Solaris: Прототип описан в файле CSP_Wincrypt.h.

См. также:

CPEncrypt() , CPGenKey() , CPDecrypt() в MS CSP , CryptDecrypt() в MS CryptoAPI 2.0


CPEncrypt

Функция CPEncrypt().

Производит зашифрование данных. Одновременно может быть произведено их хэширование.

BOOL WINAPI CPEncrypt (
  HCRYPTPROV hProv,
  HCRYPTKEY hKey,
  HCRYPTHASH hHash,
  BOOL Final,
  DWORD dwFlags,
  BYTE * pbData,
  DWORD * pdwDataLen,
  DWORD dwBufLen
);

Параметры:

hProv
[in] Дескриптор криптопровайдера. Получается через запрос функции CPAcquireContext().
hKey
[in] Дескриптор ключа сессии, используемого для зашифрования данных.
hHash
[in] Дескриптор объекта функции хэширования. Если значение хэш-функции не вычисляется, этот параметр равен нулю.
Final
[in] Булева величина. Определяет, является ли переданный функции блок последним зашифрованным блоком данных. Она должна быть установлена TRUE, если это последний (или единственный) блок, и FALSE – в противном случае.
dwFlags
[in] Значения флагов. Параметр зарезервирован для будущего использования и должен быть 0.
pbData
[in/out] Буфер, содержащий данные для зашифрования. После зашифрования зашифрованные данные помещаются в этот же буфер.
pdwDataLen
[in/out] Адрес длины данных. Параметр dwDataLen определяет число байтов открытого текста в буфере pbData. Через этот параметр функция возвращает указатель на число байтов шифртекста, помещенного в буфер pbData.
dwBufLen
[in] Размер буфера pbData в байтах.

Возвращает:

При успешном завершении функция возвращает TRUE, в противном случае возвращается FALSE. Если возвращается FALSE, соответствующий код ошибки (см. таблицу) может быть получен через функцию GetLastError().
Возвращаемые значения | Описание
NTE_BAD_ALGID | Ключ hKey определяет алгоритм, который данный криптопровайдер не поддерживает.
NTE_BAD_FLAGS | Величина dwFlags имеет ненулевое значение.
NTE_BAD_DATA | Данные для зашифрования недействительны. В частности, в блочных режимах шифрования, если Final = FALSE, а длина шифруемого текста не кратна длине блока шифрования, возвращается данная ошибка.
NTE_BAD_KEY | Ключ недействителен. В частности, эта ошибка возвращается, если на ключе в состоянии CRYPT_SIMPLEMIX_MODE зашифровано более 10**12 бит текста.
NTE_BAD_LEN | Размер буфера недостаточен для помещения в него шифртекста.
ERROR_MORE_DATA | Размер буфера pbData не достаточен для копирования затребованных данных.
NTE_PERM | Право зашифрования на данном ключе криптопровайдером не предоставлено.
NTE_FAIL | Нарушение целостности ключей в ОЗУ.
GPE_CORRUPT_KEYCONTEXT | Нарушение целостности ключей.

Требования:

Windows NT/2000/XP: Необходимо Windows NT 4.0 SP5 или старше с Internet Explorer 5.0 или старше.
Windows 98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле Wincrypt.h.
Solaris: Прототип описан в файле CSP_Wincrypt.h.

См. также:

CPDecrypt() , CPGenKey() , CPEncrypt() в MS CSP , CryptEncrypt() в MS CryptoAPI 2.0


Функции хэширования и ЭЦП

Функции хэширования и ЭЦП предназначены для вычисления значения хэш функции и формирования/проверки ЭЦП данных.
Функции | Описание
BOOL WINAPI CPCreateHash ( HCRYPTPROV hProv, ALG_ID AlgId, HCRYPTKEY hKey, DWORD dwFlags, HCRYPTHASH *phHash) | Функция CPCreateHash().
BOOL WINAPI CPDestroyHash ( HCRYPTPROV hProv, HCRYPTHASH hHash) | Функция CPDestroyHash().
BOOL WINAPI CPDuplicateHash ( HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD *pdwReserved, DWORD dwFlags, HCRYPTHASH *phHash) | Функция CPDuplicateHash().
BOOL WINAPI CPGetHashParam ( HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData, DWORD *pdwDataLen, DWORD dwFlags) | Функция CPGetHashParam().
BOOL WINAPI CPHashData ( HCRYPTPROV hProv, HCRYPTHASH hHash, BYTE *pbData, DWORD dwDataLen, DWORD dwFlags) | Функция CPHashData().
BOOL WINAPI CPHashSessionKey ( HCRYPTPROV hProv, HCRYPTHASH hHash, HCRYPTKEY hKey, DWORD dwFlags) | Функция CPHashSessionKey().
BOOL WINAPI CPSetHashParam ( HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData, DWORD dwFlags) | Функция CPSetHashParam().
BOOL WINAPI CPSignHash ( HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD dwKeySpec, LPCWSTR sDescription, DWORD dwFlags, BYTE *pbSignature, DWORD *pdwSigLen) | Функция CPSignHash().
BOOL WINAPI CPVerifySignature ( HCRYPTPROV hProv, HCRYPTHASH hHash, BYTE *pbSignature, DWORD dwSigLen, HCRYPTKEY hPubKey, LPCWSTR sDescription, DWORD dwFlags) | Функция CPVerifySignature().


CPCreateHash

Функция CPCreateHash().

Инициализирует дескриптор нового объекта функции хэширования потока данных.

BOOL WINAPI CPCreateHash (
  HCRYPTPROV hProv,
  ALG_ID AlgId,
  HCRYPTKEY hKey,
  DWORD dwFlags,
  HCRYPTHASH * phHash
);

Параметры:

hProv
[in] Дескриптор криптопровайдера. Получается через запрос функции CPAcquireContext().
AlgId
[in] Идентификатор используемого алгоритма хэширования. В криптопровайдере определены следующие алгоритмы хэширования:
  • CALG_GR3411 - Алгоритм хэширования в соответствии с ГОСТ Р 34.11-94;
  • CALG_G28147_IMIT - Алгоритм имитозащиты в соответствии с ГОСТ 28147-89;
  • CALG_TLS1_MASTER_HASH - Объект, содержащий ключевую информацию для создания ключей CALG_TLS1_ENC_KEY и CALG_TLS1_MAC_KEY;
  • CALG_TLS1PRF - Алгоритм "производящей функции" (PRF), генерирующей блок данных произвольной длины на основе ключа, метки и бинарных данных.
hKey
[in] Если используется алгоритм имитозащиты по ГОСТ 28147-89 (CALG_G28147_IMIT), в этом параметре передаётся ключ сессии для объекта функции хэширо

вания. Если используется алгоритм CALG_TLS1_MASTER_HASH, в этом параметре передается master_secret (ключ типа CALG_TLS1_MASTER), на основе которого будет создана ключевая информация по следующей формуле:
      key_block = PRF(SecurityParameters.master_secret,
                         "key expansion",
                         SecurityParameters.server_random +
                         SecurityParameters.client_random);
Предварительно следует установить KP_CLIENT_RANDOM и KP_SERVER_RANDOM.

Если используется алгоритм CALG_TLS1PRF, в этом параметре передается ключ типа CALG_TLS1_MASTER.

Для алгоритмов хэширования типа ГОСТ Р 34.11-94 этот параметр должен быть установлен в ноль.
dwFlags
[in] Значения флагов. Параметр зарезервирован для будущего использования и должен быть 0.
phHash
[out] Адрес по которому функция копирует дескриптор нового объекта функции хэширования.

Возвращает:

При успешном завершении функция возвращает TRUE, в противном случае возвращается FALSE. Если возвращается FALSE, соответствующий код ошибки (см. таблицу) может быть получен через функцию GetLastError().
Возвращаемые значения | Описание
NTE_BAD_ALGID | Параметр AlgId определяет алгоритм, который не поддерживается криптопровайдером.
NTE_BAD_FLAGS | Величина dwFlags имеет ненулевое значение.
NTE_NO_MEMORY | Криптопровайдер во время операции исчерпал память.
NTE_FAIL | Ошибка при считывании данных из системного реестра.
GPE_CORRUPT_KEYCONTEXT | Нарушение целостности ключей.

Требования:

Windows NT/2000/XP: Необходимо Windows NT 4.0 SP5 или старше с Internet Explorer 5.0 или старше.
Windows 98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле Wincrypt.h.
Solaris: Прототип описан в файле CSP_Wincrypt.h.

См. также:

CPDestroyHash() , CPHashData() , CPCreateHash() в MS CSP , CryptCreateHash() в MS CryptoAPI 2.0


CPDestroyHash

Функция CPDestroyHash().

Разрушает объект функции хэширования.

BOOL WINAPI CPDestroyHash (
  HCRYPTPROV hProv,
  HCRYPTHASH hHash
);

Параметры:

hProv
[in] Дескриптор криптопровайдера. Получается через запрос функции CPAcquireContext().
hHash
[in] Дескриптор разрушаемого объекта функции хэширования.

Возвращает:

При успешном завершении функция возвращает TRUE, в противном случае возвращается FALSE. Если возвращается FALSE, соответствующий код ошибки (см. таблицу) может быть получен через функцию GetLastError().
Возвращаемые значения | Описание
NTE_BAD_TYPE | Тип алгоритма hHash ошибочен.

Требования:

Windows NT/2000/XP: Необходимо Windows NT 4.0 SP5 или старше с Internet Explorer 5.0 или старше.
Windows 98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле Wincrypt.h.
Solaris: Прототип описан в файле CSP_Wincrypt.h.

См. также:

CPCreateHash() , CPDestroyHash() в MS CSP , CryptDestroyHash() в MS CryptoAPI 2.0


CPDuplicateHash

Функция CPDuplicateHash().

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

BOOL WINAPI CPDuplicateHash (
  HCRYPTPROV hProv,
  HCRYPTHASH hHash,
  DWORD * pdwReserved,
  DWORD dwFlags,
  HCRYPTHASH * phHash
);

Параметры:

hProv
[in] Дескриптор криптопровайдера. Получается через запрос функции CPAcquireContext().
hHash
[in] Дескриптор объекта функции хэширования.
pdwReserved
[in] Параметр зарезервирован для будущего использования и должен быть NULL.
dwFlags
[in] Параметр зарезервирован для будущего использования и должен быть 0.
phHash
[out] Адрес по которому функция копирует дескриптор нового объекта функции хэширования.

Возвращает:

При успешном завершении функция возвращает TRUE, в противном случае возвращается FALSE. Если возвращается FALSE, соответствующий код ошибки (см. таблицу) может быть получен через функцию GetLastError().
Возвращаемые значения | Описание
NTE_NO_MEMORY | Криптопровайдер во время операции исчерпал память.

Требования:

Windows NT/2000/XP: Необходимо Windows NT 4.0 SP5 или старше с Internet Explorer 5.0 или старше.
Windows 98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле Wincrypt.h.
Solaris: Прототип описан в файле CSP_Wincrypt.h.

См. также:

CPDestroyHash() , CPDuplicateHash() в MS CSP , CryptDuplicateHash() в MS CryptoAPI 2.0


CPGetHashParam

Функция CPGetHashParam().

Возвращает параметры объекта функции хэширования и значение функции хэширования.

BOOL WINAPI CPGetHashParam (
  HCRYPTPROV hProv,
  HCRYPTHASH hHash,
  DWORD dwParam,
  BYTE * pbData,
  DWORD * pdwDataLen,
  DWORD dwFlags
);

Параметры:

hProv
[in] Дескриптор криптопровайдера. Получается через запрос функции CPAcquireContext().
hHash
[in] Дескриптор объекта функции хэширования, параметры которого определяются.
dwParam
[in] Параметр, принимающий следующие возможные значения:
Значение dwParam | Содержимое буфера pbData
HP_ALGID | Алгоритм функции хэширования. Идентификатор алгоритма (ALG_ID), соответствующий данному объекту функции хэширования. Возвращается через буфер pbData. В pdwDataLen будет возвращена величина 4.
HP_HASHSIZE | Размер значения функции хэширования. Величина DWORD, определяющая число байтов в значении функции хэширования, будет возвращена через буфер pbData. В pdwDataLen будет возвращена величина 4.
HP_HASHVAL | Значение функции хэширования. Вычисленное значение функции хэширования будет возвращено через буфер pbData. Длина значения функции хэширования будет возвращена в pdwDataLen. Объект хэширования закрывается. При повторном обращении этой функцией к закрытому объекту вычисленное значение функции хэширования повторяется. Закрытый объект может быть разрушен вызовом функции CPDestroyHash().
KP_HASHOID | Идентификатор функции хеширования, устанавливаемой приложением. Строковая величина с признаком конца строки.
Следующее значение параметра устанавливается для объекта функции хеширования типа CALG_GR341:
Значение dwParam | Содержимое буфера pbData
HP_HASHSTARTVECT | Значение стартового вектора объекта функции хэширования. Значение стартового вектора объекта функции хэширования будет возвращено через буфер pbData. Длина значения стартового вектора объекта функции хэширования будет возвращена в pdwDataLen.
pbData
[out] Буфер данных параметра. Функция копирует соответствующие параметру данные в буфер. Формат этих данных зависит от значения dwParam. Если параметр - NULL, то данные не копируются. Требуемый размер буфера в байтах возвращается в pdwDataLen. Подробнее см. Возвращение данных неопределенной длины.
pdwDataLen
[in/out] Адрес длины данных параметра. При вызове функции указанный параметр содержит число байтов в буфере pbData. После её исполнения параметр будет установлен числом байтов данных параметра, скопированных в буфер pbData. Если буфер, соответствующий pbData недостаточно большой, чтобы в него копировать запрошенные данные, будет возвращен код ошибки ERROR_MORE_DATA через функцию SetLastError(). В этом случае требуемый размер буфера возвращается в pdwDataLen. Если функция завершается с кодом ошибки, отличным от ERROR_MORE_DATA, в этом параметре возвращается ноль.
dwFlags
[in] Значения флагов. Параметр зарезервирован для будущего использования и должен быть 0.

Возвращает:

При успешном завершении функция возвращает TRUE, в противном случае возвращается FALSE. Если возвращается FALSE, соответствующий код ошибки (см. таблицу) может быть получен через функцию GetLastError().
Возвращаемые значения | Описание
ERROR_MORE_DATA | Размер буфера pbData недостаточен для копирования затребованных данных.
NTE_BAD_FLAGS | Параметр dwFlags имеет ненулевое значение.
NTE_BAD_TYPE | Параметр dwParam передаёт неизвестное значение параметра.
SCARD_W_CANCELLED_BY_USER | Пользователь прервал операцию нажатием клавиши Cancel
SCARD_W_WRONG_CHV | Пользователь ввел неправильный пароль или пароль установленный функцией SetProvParam неправильный
SCARD_E_INVALID_CHV | Пользователь ввел пароль с нарушением формата или пароль, установленный функцией SetProvParam(), имеет неправильный формат. Например, пароль имеет недопустимую длину или содержит недопустимые символы.
SCARD_W_CHV_BLOCKED | Ввод Pin-кода был заблокирован смарт-картой, т.к. исчерпалось количество попыток разрешенное картой для ввода.

Требования:

Windows NT/2000/XP: Необходимо Windows NT 4.0 SP5 или старше с Internet Explorer 5.0 или старше.
Windows 98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле Wincrypt.h.
Solaris: Прототип описан в файле CSP_Wincrypt.h.

См. также:

CPCreateHash() , CPGetKeyParam() , CPSetHashParam() , CPGetHashParam() в MS CSP , CryptGetHashParam() в MS CryptoAPI 2.0


CPHashData

Функция CPHashData().

Передаёт данные указанному объекту функции хэширования.

BOOL WINAPI CPHashData (
  HCRYPTPROV hProv,
  HCRYPTHASH hHash,
  BYTE * pbData,
  DWORD dwDataLen,
  DWORD dwFlags
);

Параметры:

hProv
[in] Дескриптор криптопровайдера. Получается через запрос функции CPAcquireContext().
hHash
[in] Дескриптор объекта функции хэширования. Приложение получает этот дескриптор, используя функцию CPCreateHash().
pbData
[in] Адрес хэшируемых данных.
dwDataLen
[in] Число байтов хэшируемых данных.
dwFlags
[in] Значения флагов. В настоящее время для этой функции значения флагов не определены. Криптопровайдер игнорирует этот параметр.

Возвращает:

При успешном завершении функция возвращает TRUE, в противном случае возвращается FALSE. Если возвращается FALSE, соответствующий код ошибки (см. таблицу) может быть получен через функцию GetLastError().
Возвращаемые значения | Описание
NTE_BAD_ALGID | Ключ сессии hKey определяет алгоритм, который данный криптопровайдер не поддерживает.
NTE_BAD_HASH_STATE | Была сделана попытка добавить данные к объекту функции хэширования, который уже отмечен как "закрытый".
NTE_BAD_KEY | Используется алгоритм хэширования (CALG_G28147_IMIT), но сессионный ключ разрушен прежде, чем действие хэширования завершено.
NTE_FAIL | Нарушение целостности ключей в ОЗУ.

Требования:

Windows NT/2000/XP: Необходимо Windows NT 4.0 SP5 или старше с Internet Explorer 5.0 или старше.
Windows 98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле Wincrypt.h.
Solaris: Прототип описан в файле CSP_Wincrypt.h.

См. также:

CPCreateHash() , CPHashSessionKey() , CPHashData() в MS CSP , CryptHashData() в MS CryptoAPI 2.0


CPHashSessionKey

Функция CPHashSessionKey().

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

BOOL WINAPI CPHashSessionKey (
  HCRYPTPROV hProv,
  HCRYPTHASH hHash,
  HCRYPTKEY hKey,
  DWORD dwFlags
);

Параметры:

hProv
[in] Дескриптор криптопровайдера. Получается через запрос функции CPAcquireContext().
hHash
[in] Дескриптор объекта функции хэширования. Приложение получает этот дескриптор, используя функцию CPCreateHash().
hKey
[in] Дескриптор хэшируемого ключа сессии.
dwFlags
[in] Параметр зарезервирован для будущего использования и должен быть 0.

Возвращает:

При успешном завершении функция возвращает TRUE, в противном случае возвращается FALSE. Если возвращается FALSE, соответствующий код ошибки (см. таблицу) может быть получен через функцию GetLastError().
Возвращаемые значения | Описание
NTE_BAD_ALGID | Параметр AlgId определяет алгоритм, который не поддерживается криптопровайдером.
NTE_BAD_FLAGS | Величина dwFlags имеет ненулевое значение.
NTE_BAD_HASH_STATE | Была сделана попытка добавить данные к объекту функции хэширования, который уже отмечен как "закрытый".
NTE_BAD_KEY | Тип хэшируемого ключа не соответствует ALG_TYPE_BLOCK.

Примечание:

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

Требования:

Windows NT/2000/XP: Необходимо Windows NT 4.0 SP5 или старше с Internet Explorer 5.0 или старше.
Windows 98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле Wincrypt.h.
Solaris: Прототип описан в файле CSP_Wincrypt.h.

См. также:

CPCreateHash() , CPGenKey() , CPHashData() , CPHashSessionKey() в MS CSP , CryptHashSessionKey() в MS CryptoAPI 2.0


CPSetHashParam

Функция CPSetHashParam().

Устанавливает параметры объекта хэширования.

BOOL WINAPI CPSetHashParam (
  HCRYPTPROV hProv,
  HCRYPTHASH hHash,
  DWORD dwParam,
  BYTE * pbData,
  DWORD dwFlags
);

Параметры:

hProv
[in] Дескриптор криптопровайдера. Получается через запрос функции CPAcquireContext().
hHash
[in] Дескриптор объекта хэширования, параметры которого устанавливаются.
dwParam
[in] Параметр, принимающий следующие возможные значения:
Значение dwParam | Содержимое буфера pbData
HP_HASHVAL | Устанавливается для объекта функции хэширования типа CALG_GR3411. Величина, 32 байта, должна быть установлена в буфер pbData.
HP_HASHSTARTVECT | Стартовый вектор функции хеширования, устанавливаемый приложением. Массив из 8 байт для CALG_G28147_IMIT, для CALG_GR3411 этот парамерт не поддерживается.
HP_HASHSIZE | Устанавливается для объекта функции хэширования типа CALG_G12847_IMIT. В буфер pbData записывается величина DWORD, определяющая число байтов имитовставки в диапазоне от 1 до 4. По умолчанию длина имитовставки равна 4 байтам.
KP_HASHOID | Идентификатор функции хеширования. Строковая величина с признаком конца строки.
HP_TLS1PRF_SEED | Составляющая аргумента функции GOSTR3411_PRF. Принимает различные значения в сообщениях клиента и сервера при реализации TLS Handshake Protocol. Задается в виде структуры CRYPT_DATA_BLOB.
HP_TLS1PRF_LABEL | Составляющая аргумента функции GOSTR3411_PRF. Принимает различные значения в сообщениях клиента и сервера при реализации TLS Handshake Protocol. Задается в виде структуры CRYPT_DATA_BLOB.
pbData
[in] Буфер данных параметра. При вызове функции буфер должен содержать данные, соответствующие значению параметра в dwParam. Формат данных зависит от типа параметра dwParam.
dwFlags
[in] Значения флагов. Параметр зарезервирован для будущего использования и должен быть 0.

Возвращает:

При успешном завершении функция возвращает TRUE, в противном случае возвращается FALSE. Если возвращается FALSE, соответствующий код ошибки (см. таблицу) может быть получен через функцию GetLastError().
Возвращаемые значения | Описание
NTE_BAD_FLAGS | Параметр dwFlags имеет ненулевое значение.
NTE_BAD_TYPE | Параметр dwParam передаёт неизвестное значение параметра.
NTE_BAD_HASH_STATE | Была сделана попытка получить значение функции хэширвания для "не закрытого" объекта функции хэширования.
SCARD_W_CANCELLED_BY_USER | Пользователь прервал операцию нажатием клавиши Cancel
SCARD_W_WRONG_CHV | Пользователь ввел неправильный пароль или пароль, установленный функцией SetProvParam(), неправильный
SCARD_E_INVALID_CHV | Пользователь ввел пароль с нарушением формата или пароль, установленный функцией SetProvParam(), имеет неправильный формат. Например, пароль имеет недопустимую длину или содержит недопустимые символы.
SCARD_W_CHV_BLOCKED | Ввод Pin-кода был заблокирован смарт-картой, т.к. исчерпалось количество попыток, разрешенное картой для ввода.
NTE_TOKEN_KEYSET_STORAGE_FULL | Недостаточно места на носителе для сохранения информации.

Требования:

Windows NT/2000/XP: Необходимо Windows NT 4.0 SP5 или старше с Internet Explorer 5.0 или старше.
Windows 98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле Wincrypt.h.
Solaris: Прототип описан в файле CSP_Wincrypt.h.

См. также:

CPCreateHash() , CPGetHashParam() , CPSignHash() , CPSetHashParam() в MS CSP , CryptSetHashParam() в MS CryptoAPI 2.0


CPSignHash

Функция CPSignHash().

Возвращает значение электронной цифровой подписи от значения функции хэширования.

BOOL WINAPI CPSignHash (
  HCRYPTPROV hProv,
  HCRYPTHASH hHash,
  DWORD dwKeySpec,
  LPCWSTR sDescription,
  DWORD dwFlags,
  BYTE * pbSignature,
  DWORD * pdwSigLen
);

Параметры:

hProv
[in] Дескриптор криптопровайдера. Получается через запрос функции CPAcquireContext().
hHash
[in] Дескриптор объекта функции хэширования, который должен быть подписан.
dwKeySpec
[in] Тип ключевой пары, использующейся при подписи значения функции хэширования. Могут быть использованы следующие значения:
Значение | Описание
AT_KEYEXCHANGE | Ключевая пара обмена
AT_SIGNATURE | Ключевая пара цифровой подписи
sDescription
[in] Описание подписываемых данных, добавляемых к объекту hash перед тем, как будет произведена подпись. При проверке подписи функцией CPVerifySignature(), должно использоваться то же описание подписанных данных. Это гарантирует, что подписывающая сторона и проверяющая знают то, что подписывается или проверяется. Если описание не включается в подпись, этот параметр устанавливается в NULL.

Параметр сохранён для совместимости со спецификацией Microsoft Cryptographic Service Provider. С целью предотвращения уязвимости безопасности ЭЦП использовать этот параметр не рекомендуется. Он должен быть установлен в NULL.
dwFlags
[in] Значения флагов. Параметр зарезервирован для будущего использования и должен быть 0.
pbSignature
[in] Буфер, через который возвращается значение подписи. Если через этот параметр паредаётся NULL, то подпись не вычисляется. В этом случае требуемый размер буфера (в байтах) возвращается через параметр pdwSigLen.
pdwSigLen
[in/out] Адрес длины данных подписи. При вызове функции указанный параметр должен содержать число байтов в буфере pbSignature. После её исполнения параметр будет установлен числом байтов данных, скопированных в буфер pbSignature. Если буфер, соответствующий pbSignature, недостаточно большой, чтобы в него копировать подпись, будет возвращен код ошибки ERROR_MORE_DATA через функцию SetLastError(). В этом случае требуемый размер буфера возвращается в pdwSigLen. Если эта функция завершается с кодом ошибки, отличным от ERROR_MORE_DATA, в этом параметре возвращается ноль.

Возвращает:

При успешном завершении функция возвращает TRUE, в противном случае возвращается FALSE. Если возвращается FALSE, соответствующий код ошибки (см. таблицу) может быть получен через функцию GetLastError().
Возвращаемые значения | Описание
NTE_BAD_ALGID | Дескриптор hHash определяет алгоритм, который данный криптопровайдер не поддерживает.
NTE_BAD_FLAGS | dwFlags параметр отличен от нуля, либо параметр dwKeySpec содержит ошибочную величину.
NTE_BAD_KEY | Секретный ключ, указанный dwKeySpec, не существует.
NTE_NO_MEMORY | Криптопровайдер во время операции исчерпал память.
ERROR_MORE_DATA | pbSignature буфер мал для копирования затребованных данных.
NTE_FAIL | Нарушение целостности ключей в ОЗУ.
GPE_CORRUPT_KEYPAIR_INFO | Нарушение целостности ключей.
SCARD_W_CANCELLED_BY_USER | Пользователь прервал операцию нажатием клавиши Cancel
SCARD_W_WRONG_CHV | Пользователь ввел неправильный пароль или пароль установленный функцией SetProvParam неправильный
SCARD_E_INVALID_CHV | Пользователь ввел пароль с нарушением формата или пароль, установленный функцией SetProvParam(), имеет неправильный формат. Например, пароль имеет недопустимую длину или содержит недопустимые символы.
SCARD_W_CHV_BLOCKED | Ввод Pin-кода был заблокирован смарт-картой, т.к. исчерпалось количество попыток разрешенное картой для ввода.

Примечание:

Перед вызовом функции CPSignHash() должен быть получен дескриптор объекта хэширования через вызов функции CPCreateHash(). После этого используется функция CPHashData() или CPHashSessionKey() чтобы добавить данные или ключи сессии к объекту хэширования.

Функция CPSignHash() выполняет следующие внутренние шаги:

  • объект функции хэширования "закрывается”; извлекается значение функции хэширования;
  • значение функции хэширования дополняется, как это требуется алгоритмом подписи;
  • вычисляется фактическое значение подписи.

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

Требования:

Windows NT/2000/XP: Необходимо Windows NT 4.0 SP5 или старше с Internet Explorer 5.0 или старше.
Windows 98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле Wincrypt.h.
Solaris: Прототип описан в файле CSP_Wincrypt.h.
Ядро ОС: В ядре ОС эта функция не поддерживается.

См. также:

CPCreateHash() , CPDestroyHash() , CPHashData() , CPHashSessionKey() , CPVerifySignature() , CPSignHash() в MS CSP , CryptSignHash() в MS CryptoAPI 2.0


CPVerifySignature

Функция CPVerifySignature().

Осуществляет проверку цифровой подписи, соответствующей объекту функции хэширования.

BOOL WINAPI CPVerifySignature (
  HCRYPTPROV hProv,
  HCRYPTHASH hHash,
  BYTE * pbSignature,
  DWORD dwSigLen,
  HCRYPTKEY hPubKey,
  LPCWSTR sDescription,
  DWORD dwFlags
);

Параметры:

hProv
[in] Дескриптор криптопровайдера. Получается через запрос функции CPAcquireContext().
hHash
[in] Дескриптор объекта функции хэширования, подпись которого проверяется.
pbSignature
[in] Буфер, содержащий значение проверяемой подписи.
dwSigLen
[in] Длина (в байтах) значения подписи.
sDescription
[in] Описание подписанных данных идентичное описанию, использованному при создании подписи. Это должна быть точно та же самая последовательность, которая использовалась в функции CPSignHash() при создании подписи. Если эта последовательность не соответствует использованной в функции CPSignHash(), проверка подписи сообщит, что подпись не верна.
dwFlags
[in] Значения флагов. Параметр зарезервирован для будущего использования и должен быть 0.

Возвращает:

При успешном завершении функция возвращает TRUE, в противном случае возвращается FALSE. Если возвращается FALSE, соответствующий код ошибки (см. таблицу) может быть получен через функцию GetLastError.
Возвращаемые значения | Описание
NTE_BAD_ALGID | Дескриптор hHash определяет алгоритм, который этот криптопровайдер не поддерживает.
NTE_BAD_FLAGS | dwFlags параметр отличен от нуля, либо параметр dwKeySpec содержит ошибочную величину.
NTE_BAD_KEY | hPubKey параметр содержит дескриптор на недопустимый открытый ключ.
NTE_BAD_SIGNATURE | Проверка подписи не прошла. Это могло случиться потому, что изменились сами данные, последовательность описания не соответствует, или открытый ключ был определен ошибочно параметром hPubKey. Эта ошибка может быть возвращена также, если алгоритмы хэширования или подписи не соответствуют тем, с помощью которых вычислялась подпись.
NTE_NO_MEMORY | Криптопровайдер во время операции исчерпал память.
NTE_FAIL | Нарушение целостности ключей в ОЗУ.
RPE_CORRUPT_KEYPAIR_INFO | Нарушение целостности ключей.

Примечание:

Функция CPVerifySignature выполняет следующие внутренне шаги:

  • если параметр описания sDescription поддержан, он добавляется к объекту функции хэширования;
  • объект функции хэширования "закрывается" и значение функции хэширования извлекается;
  • значение функции хэширования дополняется, как это требуется алгоритмом подписи;
  • осуществляется проверка подписи c использованием открытого ключа hPubKey;
  • если подпись, переданная через буфер pbSignature, и вычисленное значение подписи не совпадают, возвращается код ошибки NTE_BAD_SIGNATURE.

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

Требования:

Windows NT/2000/XP: Необходимо Windows NT 4.0 SP5 или старше с Internet Explorer 5.0 или старше.
Windows 98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле Wincrypt.h.
Solaris: Прототип описан в файле CSP_Wincrypt.h.
Ядро ОС: В ядре ОС эта функция не поддерживается.

См. также:

CPCreateHash() , CPHashData() , CPSignHash() , CPVerifySignature() в MS CSP , CryptVerifySignature() в MS CryptoAPI 2.0


Структуры данных

Предназначены для взаимодействия с программами пользователя непосредственно использующими "КриптоПро CSP".
Составные типы | Описание
struct _VTABLEPROVSTRUC | Структура _VTABLEPROVSTRUC.
struct _PUBLICKEYSTRUC | Структура PUBLICKEYSTRUC.
struct CRYPT_SIMPLEBLOB_HEADER | Структура CRYPT_SIMPLEBLOB_HEADER.
struct CRYPT_SIMPLEBLOB | Псевдоструктура CRYPT_SIMPLEBLOB.
struct _CRYPT_PUBKEYPARAM_ | Структура CRYPT_PUBKEYPARAM.
struct CRYPT_PUBKEY_INFO_HEADER | Структура CRYPT_PUBKEY_INFO_HEADER.
struct CRYPT_PUBLICKEYBLOB | Псевдоструктура CRYPT_PUBLICKEYBLOB.
struct CRYPT_PRIVATEKEYBLOB | Псевдоструктура CRYPT_PRIVATEKEYBLOB.
struct _CRYPT_DIVERSBLOBHEADER | Структура CRYPT_DIVERSBLOBHEADER.
struct CRYPT_CHANGE_PIN_PARAM_ | Структура передачи информации для: 1) смены пароля контейнера, 2) указания способа доступа к контейнеру (имя, handle, пароль), на ключе которого зашифровано содержимое другого контейнера.
struct _LPSZ_CONTAINER_NAME | Имя контейнера.
Макросы | Описание
#define MAX_OID_LEN 64 | Максимальная длина OID.
#define SECRET_KEY_LEN 32 | Длина ключа.
#define G28147_KEYLEN SECRET_KEY_LEN | Длина ключа ГОСТ 28147-89.
#define EXPORT_IMIT_SIZE 4 | Длина имитовставки.
#define SEANCE_VECTOR_LEN 8 | Длина вектора инциализации алгоритма.
#define GR3410_1_MAGIC 0x3147414D | Признак ключей.
#define G28147_MAGIC 0x374a51fd | Признак ключей ГОСТ 28147-89 и TLS.
#define DIVERS_MAGIC 0x31564944 | Признак ключевого блоба функции диверсификации ключа.
#define BLOB_VERSION (BYTE)0x20 | Текущее значение версии ключевого блоба.


BLOB_VERSION

Текущее значение версии ключевого блоба.

#define BLOB_VERSION   (BYTE)0x20


DIVERS_MAGIC

Признак ключевого блоба функции диверсификации ключа.

#define DIVERS_MAGIC   0x31564944


EXPORT_IMIT_SIZE

Длина имитовставки.

Длина в байтах имитовставки при импорте/экспорте

#define EXPORT_IMIT_SIZE   4


G28147_KEYLEN

Длина ключа ГОСТ 28147-89.

Длина в байтах ключа ГОСТ 28147-89. SECRET_KEY_LEN

#define G28147_KEYLEN   SECRET_KEY_LEN


G28147_MAGIC

Признак ключей ГОСТ 28147-89 и TLS.

Признак ключей ГОСТ 28147-89 и мастер-ключей TLS

#define G28147_MAGIC   0x374a51fd


GR3410_1_MAGIC

Признак ключей.

Признак ключей ГОСТ Р 34.10-94 и ГОСТ Р 34.10-2001

#define GR3410_1_MAGIC   0x3147414D


MAX_OID_LEN

Максимальная длина OID.

Максимальная длина OID, используемых в СКЗИ "КриптоПро CSP".

#define MAX_OID_LEN   64


SEANCE_VECTOR_LEN

Длина вектора инциализации алгоритма.

Длина в байтах вектора инциализации алгоритма

#define SEANCE_VECTOR_LEN   8


SECRET_KEY_LEN

Длина ключа.

Длина в байтах ключа ГОСТ 28147-89 и секретных ключей ГОСТ Р 34.10-94 и ГОСТ Р 28147-89.

#define SECRET_KEY_LEN   32


_VTABLEPROVSTRUC Struct Reference

Описание структуры _VTABLEPROVSTRUC

Структура _VTABLEPROVSTRUC.

Cодержит указатели на callback функции, которые могут быть использованы функциями криптопровайдера (CSP).

struct _VTABLEPROVSTRUC {
   DWORD Version;
   FARPROC FuncVerifyImage;
   FARPROC FuncReturnhWnd;
   DWORD dwProvType;
   BYTE* pbContextInfo;
   DWORD cbContextInfo;
   LPSTR pszProvName;
};

Описание данных, членов структуры

FuncReturnhWnd
Указатель на callback функцию, возвращаемую информацию о дескрипторе окна. Дескриптор окна будет использован для взаимодействия с пользователем через Microsoft® Win32®.
FuncVerifyImage
Указатрль на callback функцию, используемую для проверки ЭЦП модуля. См. Примечание.
Version
DWORD значение, определяющее версию структуры. Используются три версии структуры. Microsoft® Windows NT® версия 4.0 and Microsoft® Windows® 95 используют версию 1, которая содержит только три первых члена: Version, FuncVerifyImage, FuncReturnhWnd. Версия 2 используется в Windows 98. Используются первые шесть членов структуры. Версия 3 используется в Windows 2000. Оба включает все семь членов структуры.
cbContextInfo
Значение, определяющее количество элементов в массиве pbContextInfo.
dwProvType
Значение, определяющее тип криптопровайдера. Определены следующие типы криптопровайдеров:
  • PROV_GOST_DH
  • PROV_RSA_FULL
  • PROV_RSA_SIG
  • PROV_DSS
  • PROV_FORTEZZA
  • PROV_MS_EXCHANGE
pbContextInfo
Указатель на массив контекстной информации. Переменные pbContextInfo и cbContextInfo определяют состав передаваемой информации, используемо при вызове функции CPSetProvParam с параметром PP_CONTEXT_INFO.
pszProvName
Строка, содержащая имя провайдера.

Примечание:

Указатель на структуру _VTABLEPROVSTRUC доступен только во врема вызова функции CPAcquireContext(). Если члены структуры необходимы для дальнейшей работы, необходимо произвести копирование значений. Скопированные указатели на функции, содержащиеся в струкруре и сами функции, могут быть использованы до тех пор пока не закрылась сессия с криптопровайдером. Все дополнительные модули (DLL), которые использует криптопровайдер могут быть подписаны, как и основной модуль. Перд загрузкой дополнительны модулей с использованием функции LoadLib, можно проверить подпись дополнительных модулей. Криптопровайдер может производить такую проверку, используя указатель на функцию FuncVerifyImag(), как показано в следующем примере:

 BOOL (FARPROC *ProvVerifyImage)(LPCSTR lpszImage, BYTE *pSigData);
 BYTE bSignature[72];

 // "ProvVerifyImage" has been set to "pVTable->FuncVerifyImage"
 // within the CPAcquireContext function.

 // Load the C:\Winnt40\System32\signature.sig file into the
 // bSignature buffer. During development, this file is created
 // with the Sign.exe utility.
 ...

 // Verify the signature on the C:\Winnt40\System32\Signature.dll file.
 if(RCRYPT_FAILED(ProvVerifyImage("c:\\winnt40\\system32\\signature.dll",
                                  bSignature)) {
     SetLastError(NTE_BAD_SIGNATURE);
    return CRYPT_FAILED;
 }

 // Load the DLL with the LoadLib function, then acquire pointers to
 // the member functions with the GetProcAddress function.
 ...

Примеры:

ctkey.c.


_PUBLICKEYSTRUC Struct Reference

Описание структуры _PUBLICKEYSTRUC

Структура PUBLICKEYSTRUC.

Так же, как структура BLOBHEADER, указывает тип ключевого блоба и алгоритм ключа находящегося в нём. Экземпляр этой структуры находится в начале поля pbData каждого ключевого блоба.

struct _PUBLICKEYSTRUC {
   BYTE bType;
   BYTE bVersion;
   WORD reserved;
   ALG_ID aiKeyAlg;
};

Описание данных, членов структуры

aiKeyAlg
Алгоритм ключа содержащегося в ключевом блобе.
bType
Тип ключевого блоба. Поддерживаются следующие типы ключевых блобов:
bType | Описание
PUBLICKEYBLOB | Предназначен для транспорта открытых ключей.
PRIVATEKEYBLOB | Предназначен для транспорта ключевых пар (секретных ключей).
SIMPLEBLOB | Предназначен для транспорта сессионых ключей.
bVersion
Номер версии формата ключевого блоба. В настоящий момент, версия всегда должна быть равна 0x02.
reserved
Зарезервировано для использования в будущем. Должно устанавливаться в 0.

Требования:

Windows NT/2000: Необходимо Windows NT 4.0 или старше с Internet Explorer 5.0 или старше.
Windows 95/98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле Wincrypt.h.
Solaris: Прототип описан в файле CSP_Wincrypt.h.

См. также:

CRYPT_PUBKEY_INFO_HEADER , CRYPT_SIMPLEBLOB_HEADER , CRYPT_PUBLICKEYBLOB , CRYPT_PRIVATEKEYBLOB , CRYPT_SIMPLEBLOB


CRYPT_SIMPLEBLOB_HEADER Struct Reference

Описание структуры CRYPT_SIMPLEBLOB_HEADER

Структура CRYPT_SIMPLEBLOB_HEADER.

Является расширением структуры BLOBHEADER и находится в начале поля pbData ключевого блоба типа SIMPLEBLOB для ключей "КриптоПро CSP".

struct CRYPT_SIMPLEBLOB_HEADER {
   BLOBHEADER BlobHeader;
   DWORD Magic;
   ALG_ID EncryptKeyAlgId;
};

Описание данных, членов структуры

BlobHeader
Общий заголовок ключевого блоба. Определяет алгоритм ключа находящегося в ключевом блобе. См. _PUBLICKEYSTRUC.
EncryptKeyAlgId
Определяет алгоритм экспорта ключа. Этот алгоритм является параметром ключа экспорта. См. CPGetKeyParam().
Magic
Признак ключей по ГОСТ 28147-89 или мастер ключей TLS, устанавливается в G28147_MAGIC.

Требования:

Windows NT/2000: Необходимо Windows NT 4.0 или старше с Internet Explorer 5.0 или старше.
Windows 95/98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле CSPKernel.h.

См. также:

_PUBLICKEYSTRUC , PCRYPT_SIMPLEBLOB , CPExportKey() , CPGetKeyParam()


CRYPT_SIMPLEBLOB Struct Reference

Описание структуры CRYPT_SIMPLEBLOB

Псевдоструктура CRYPT_SIMPLEBLOB.

Полностью описывает ключевой блоб типа SIMPLEBLOB для ключей "КриптоПро CSP". Все поля этой псевдоструктуры выравнены по границе байта и находятся в сетевом порядке байт (ASN1 DER).

struct CRYPT_SIMPLEBLOB {
   CRYPT_SIMPLEBLOB_HEADER tSimpleBlobHeader;
   BYTE bSV [SEANCE_VECTOR_LEN];
   BYTE bEncryptedKey [G28147_KEYLEN];
   BYTE bMacKey [EXPORT_IMIT_SIZE];
   BYTE bEncryptionParamSet [1];
};

Описание данных, членов структуры

bEncryptedKey
Зашифрованный ключ ГОСТ 28147-89. См. G28147_KEYLEN.
bEncryptionParamSet
Содержит ASN1 структуру в DER кодировке, определяющую параметры алгоритама шифрования ГОСТ 28147-89:
      encryptionParamSet
          OBJECT IDENTIFIER (
              id-Gost28147-89-TestParamSet |      -- Only for tests use
              id-Gost28147-89-CryptoPro-A-ParamSet |
              id-Gost28147-89-CryptoPro-B-ParamSet |
              id-Gost28147-89-CryptoPro-C-ParamSet |
              id-Gost28147-89-CryptoPro-D-ParamSet |
              id-Gost28147-89-CryptoPro-Simple-A-ParamSet |
              id-Gost28147-89-CryptoPro-Simple-B-ParamSet |
              id-Gost28147-89-CryptoPro-Simple-C-ParamSet |
              id-Gost28147-89-CryptoPro-Simple-D-ParamSet
См. MAX_OID_LEN.
bMacKey
Имитовставка по ГОСТ 28147-89 на ключ. Рассчитывается до зашифрования и проверяется после расшифрования. См. EXPORT_IMIT_SIZE.
bSV
Вектор инциализации для алгоритма CALG_PRO_EXPORT. См. SEANCE_VECTOR_LEN.
tSimpleBlobHeader
Общий заголовок ключевого блоба типа SIMPLEBLOB "КриптоПро CSP".

Требования:

Windows NT/2000: Необходимо Windows NT 4.0 или старше с Internet Explorer 5.0 или старше.
Windows 95/98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле CSPKernel.h.

См. также:

CRYPT_SIMPLEBLOB_HEADER , CPExportKey() , CPGetKeyParam()


_CRYPT_PUBKEYPARAM_ Struct Reference

Описание структуры _CRYPT_PUBKEYPARAM_

Структура CRYPT_PUBKEYPARAM.

Содержит признак ключей по ГОСТ Р 34.10-94 или ГОСТ Р 34.10-2001.

struct _CRYPT_PUBKEYPARAM_ {
   DWORD Magic;
   DWORD BitLen;
};

Описание данных, членов структуры

BitLen
Длина открытого ключа в битах.
Magic
Признак ключей по ГОСТ Р 34.10-94 или ГОСТ Р 34.10-2001 устанавливается в GR3410_1_MAGIC.

Требования:

Windows NT/2000: Необходимо Windows NT 4.0 или старше с Internet Explorer 5.0 или старше.
Windows 95/98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле CSPKernel.h.

См. также:

CRYPT_PUBKEY_INFO_HEADER , CPExportKey() , CPGetKeyParam()


CRYPT_PUBKEY_INFO_HEADER Struct Reference

Описание структуры CRYPT_PUBKEY_INFO_HEADER

Структура CRYPT_PUBKEY_INFO_HEADER.

Содержит заголовок блоба открытго ключа или блоба ключевой пары по ГОСТ Р 34.10-94 или ГОСТ Р 34.10-2001.

struct CRYPT_PUBKEY_INFO_HEADER {
   BLOBHEADER BlobHeader;
   CRYPT_PUBKEYPARAM KeyParam;
};

Описание данных, членов структуры

BlobHeader
Общий заголовок ключевого блоба. Определяет его тип и алгоритм ключа находящегося в ключевом блобе. Для открытых ключей алгоритм ключа всегда, либо CALG_GR3410, либо CALG_GR3410EL. Для ключевых пар алгоритм отражает её назначение. См. _PUBLICKEYSTRUC.
KeyParam
Основной признак и длинна ключей ГОСТ Р 34.10-94 и ГОСТ Р 34.10-2001.

Требования:

Windows NT/2000: Необходимо Windows NT 4.0 или старше с Internet Explorer 5.0 или старше.
Windows 95/98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле CSPKernel.h.

См. также:

_PUBLICKEYSTRUC , CRYPT_PUBKEYPARAM , CPExportKey() , CPGetKeyParam()


CRYPT_PUBLICKEYBLOB Struct Reference

Описание структуры CRYPT_PUBLICKEYBLOB

Псевдоструктура CRYPT_PUBLICKEYBLOB.

Описывает ключевой блоб типа PUBLICKEYBLOB для ключей "КриптоПро CSP". Все поля этой псевдоструктуры выравнены по границе байта и находятся в сетевом порядке байт (ASN1 DER).

struct CRYPT_PUBLICKEYBLOB {
   CRYPT_PUBKEY_INFO_HEADER tPublicKeyParam;
   BYTE bASN1GostR3410_94_PublicKeyParameters [1];
   BYTE bPublicKey [1];
};

Описание данных, членов структуры

bASN1GostR3410_94_PublicKeyParameters
Содержит ASN1 структуру в DER кодировке, определяющую параметры открытого ключа:
      GostR3410-94-PublicKeyParameters ::=
           SEQUENCE {
              publicKeyParamSet
                  OBJECT IDENTIFIER (
                      id-GostR3410-94-TestParamSet |      -- Only for tests use
                      id-GostR3410-94-CryptoPro-A-ParamSet |
                      id-GostR3410-94-CryptoPro-B-ParamSet |
                      id-GostR3410-94-CryptoPro-C-ParamSet |
                      id-GostR3410-94-CryptoPro-D-ParamSet |
                      id-GostR3410-94-CryptoPro-XchA-ParamSet |
                      id-GostR3410-94-CryptoPro-XchB-ParamSet |
                      id-GostR3410-94-CryptoPro-XchC-ParamSet
                  ),
              digestParamSet
                  OBJECT IDENTIFIER (
                      id-GostR3411-94-TestParamSet |      -- Only for tests use
                      id-GostR3411-94-CryptoProParamSet
                  ),
              encryptionParamSet
                  OBJECT IDENTIFIER (
                      id-Gost28147-89-TestParamSet |      -- Only for tests use
                      id-Gost28147-89-CryptoPro-A-ParamSet |
                      id-Gost28147-89-CryptoPro-B-ParamSet |
                      id-Gost28147-89-CryptoPro-C-ParamSet |
                      id-Gost28147-89-CryptoPro-D-ParamSet |
                      id-Gost28147-89-CryptoPro-Simple-A-ParamSet |
                      id-Gost28147-89-CryptoPro-Simple-B-ParamSet |
                      id-Gost28147-89-CryptoPro-Simple-C-ParamSet |
                      id-Gost28147-89-CryptoPro-Simple-D-ParamSet
                  ) OPTIONAL
          }
bPublicKey
Содержит открытый ключ в сетевом представлении (ASN1 DER). Длина массива равна tPublicKeyParam.KeyParam.BitLen/8.
tPublicKeyParam
Общий заголовок ключевого блоба типа PUBLICKEYBLOB "КриптоПро CSP".

Требования:

Windows NT/2000: Необходимо Windows NT 4.0 или старше с Internet Explorer 5.0 или старше.
Windows 95/98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле CSPKernel.h.

См. также:

CRYPT_PUBKEY_INFO_HEADER , CPExportKey() , CPGetKeyParam()


CRYPT_PRIVATEKEYBLOB Struct Reference

Описание структуры CRYPT_PRIVATEKEYBLOB

Псевдоструктура CRYPT_PRIVATEKEYBLOB.

Описывает ключевой блоб типа PRIVATEKEYBLOB для ключей "КриптоПро CSP". Все поля этой псевдоструктуры выравнены по границе байта и находятся в сетевом порядке байт (ASN1 DER).

struct CRYPT_PRIVATEKEYBLOB {
   CRYPT_PUBKEY_INFO_HEADER tPublicKeyParam;

BYTE bExportedKeys [1];
};

Описание данных, членов структуры

tPublicKeyParam
Общий заголовок ключевого блоба типа PRIVATEKEYBLOB "КриптоПро CSP".

Требования:

Windows NT/2000: Необходимо Windows NT 4.0 или старше с Internet Explorer 5.0 или старше.
Windows 95/98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле CSPKernel.h.

См. также:

CRYPT_PUBKEY_INFO_HEADER , CPExportKey() , CPGetKeyParam()


_CRYPT_DIVERSBLOBHEADER Struct Reference

Описание структуры _CRYPT_DIVERSBLOBHEADER

Структура CRYPT_DIVERSBLOBHEADER.

Описывает блоб типа DIVERSBLOB для процедуры диверсификации ключей "КриптоПро CSP-ECC/TLS". Все поля этой псевдоструктуры выравнены по границе байта и находятся в сетевом порядке байт (ASN1 DER).

struct _CRYPT_DIVERSBLOBHEADER {
   BLOBHEADER BlobHeader;
   ALG_ID aiDiversAlgId;
   DWORD dwDiversMagic;
   DWORD cbDiversData;
};

Описание данных, членов структуры

BlobHeader
Общий заголовок блоба, диверсифицирующего ключ. Определяет алгоритм диверсифицирумого ключа.
aiDiversAlgId
Определяет алгоритм диверсификации ключа.
cbDiversData
Длина данных, по которым диверсифицируется ключ.
dwDiversMagic
Признак диверсификации ключа, устанавливается в DIVERS_MAGIC.

Требования:

Windows NT/2000: Необходимо Windows NT 4.0 или старше с Internet Explorer 5.0 или старше.
Windows 95/98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле WinCryptEx.h или CSP_WinCrypt.h для Solaris.

См. также:

CPImportKey()


_LPSZ_CONTAINER_NAME Struct Reference

Описание структуры _LPSZ_CONTAINER_NAME

Имя контейнера.

Является нуль-терминированой строкой идентифицирующей носитель ключевой информации.

Возможные значения имени контейнера:
Значение | Описание
NULL | Контейнер по умолчанию. Если конфигурация "Крипто-Про CSP" настроена на хранение ключей на диске, то именем контейнера по умолчанию является имя пользователя ОС, вызвавшего CSP.
CONTAINER | Имя контейнера.
MEDIA\UNIQUE | Контейнер по умолчанию на носителе (MEDIA\UNIQUE).
MEDIA\UNIQUE\FOLDER | Контейнер на заданном носителе (MEDIA\UNIQUE). Если носитель не поддерживает уникальных имен, то уникальное имя носителя отсутствует, но символ \ опускать в этом случае нельзя. Если носитель поддерживает длинные имена (например, реестр), то имя контейнера в этом случае совпадает FOLDER.
MEDIA\UNIQUE\FOLDER\CRC | Контейнер на заданном носителе (MEDIA\UNIQUE) с именем CRC16 которого совпадает с CRC. Если носитель не поддерживает уникальных имен, то уникальное имя носителя отсутствует, но символ \ опускать в этом случае нельзя.
\\.\READER\MEDIA\UNIQUE | Контейнер по умолчанию на носителе (MEDIA\UNIQUE), с заданным именем считывателя.
\\.\READER\MEDIA\UNIQUE\FOLDER | Контейнер на заданном носителе (MEDIA\UNIQUE), с заданным именем считывателя. Если носитель не поддерживает уникальных имен, то уникальное имя носителя отсутствует, но символ \ опускать в этом случае нельзя. Если носитель поддерживает длинные имена (например, реестр), то имя контейнера в этом случае совпадает с FOLDER.
\\.\READER\MEDIA\UNIQUE\FOLDER\CRC | Контейнер на заданном носителе (MEDIA\UNIQUE), с заданным именем считывателя и CRC16 имени контейнера совпадает с CRC Если носитель не поддерживает уникальных имен, то уникальное имя носителя отсутствует, но символ \ опускать в этом случае нельзя. Если носитель поддерживает длинные имена (например, реестр), то имя контейнера в этом случае совпадает с FOLDER.
\\.\READER\CONTAINER | Имя контейнера на заданном считывателе.
\\.\READER | Контейнер по умолчанию на заданном считывателе.

Во всех перечисленных выше формах (кроме NULL), оконечный символ \ не влияет на смысл контейнера.

Пользователь задаёт имя контейнера, возможно с заданием имени считывателя, в аргументах функции CPAcquireContext().

Функция CPGetProvParam() возвращает:

  • имя контейнера (CONTAINER) как параметр PP_CONTAINER
  • и возвращает уникальное имя (MEDIA\UNIQUE\FOLDER\CRC) контейнера как параметр PP_UNIQUE_CONTAINER (Значение UNIQUE отсутствует для считывателей, не поддерживающих уникальность имен. Значение CRC отсутствует для носителей, поддерживающих длинные имена, т.е. для которых имя FOLDER ВСЕГДА совпадает с именем NAME).
На данный момент поддерживаются следующие считыватели (READER):
Имя | Описание
FAT12_[DRIVE] | дисковод, где [DRIVE] имя дисковода, например для дисковода A: имя FAT12_A (Windows, Solaris)
DS9097E_[COM], DS9097U_[COM], DS1410E_[LPT] | считыватель Touch-Memory, где [COM] ([LPT]) имя COM (LPT) порта, например для считывателя Touch-Memory DS9097E посоединенного ко второму COM порту его имя будет DS9097E_COM1 (Windows)
ACCORD | считыватель Touch-Memory через ACCORD (Windows)
SABLE | считыватель Touch-Memory через Соболь (Windows)
REGISTRY | считыватель ключей хранимых в реестре Windows (Windows)
HDIMAGE | считыватель ключей хранимых в файлах на диске (Solaris)
[PCSC считыватель] | считыватель смарт-карт через интерфейс PCSC, где [PCSC считыватель] имя считывателя так как он зарегистрирован, например для первого зарегистрированного считывателя GCR410 имя будет "GEMPLUS GCR410P 0" (Windows)

Поддерживаются следующие типы носителей (MEDIA):
Имя | Описание
FAT12 | дискета (или любой другой отчуждаемый носитель, поддерживающий файловую систему) (Windows, Solaris)
DS | Touch-Memory (Windows)
REGISTRY | реестр. Поддерживает длинные имена (Windows)
HDIMAGE | НЖМД. (Solaris)
SCARD | смарт-карта, или любое другое устройство с интерфейсом смарт-карты, например eToken. (Windows)

Вид уникального номера (UNIQUE) носителя в зависимости от его типа носителя:
Тип носителя | Вид уникального номера | Описание
Дискета | [SERIAL]_[VOLUME] | [SERIAL] серийный номер дискеты, 8 16-ричных цифр (задается при форматировании), [VOLUME] - метка тома 11 символов (задается при форматировании или, если нет метки, то при генерации первого контейнера). Если метка тома, по каким-то причинам отсутствует, то уникальное имя будет представлено в виде [SERIAL].
Touch-Memory | [тип]_[номер] | [тип] - тип Touch-memory на текущий момент поддерживаются 1993, 1994, 1995, 1996. [номер] - 6 16-ричных цифр уникального номера таблетки.
смарт-карта MPCOS 3DES | MPCOS-EMV_[номер] | [номер] - 16 16-ричных цифр уникального номера карты
смарт-карта и электронный ключ РИК | RIC_[номер] | [номер] 8 16-ричных цифр уникального номера карты
электронный ключ eToken HS | eToken_HS_[номер] | [номер] - 16 16-ричных цифр уникального номера электронного ключа
реестр | не поддерживается | не поддерживается

Вид имени папки (FOLDER) носителя в зависимости от типа носителя:
Тип носителя | Вид имени папки | Описание
Дискета | [имя].[NNN] | [имя] - 8 первых символов имени контейнера; Для символов от 'a' до 'z', от 'A' до 'Z', от '0' до '9' и символа '-' симолы остаются без изменений, для отсальных символов происходит замена на символ с ASCII кодом вычисляемым по формула c%('z'-'a'+1)+'a', где c исходный симол имени контейнера. [NNN] - порядковый номер контейнера на этом носителе внутри множества совпадающих имен [имя].
Touch-Memory | [N] | [N] - 16-ричных порядковый номер контейнера на носителе
смарт-карта и электронные ключи | не поддерживается | не поддерживается
реестр | [имя] | [имя] - имя контейнера

Список поддерживаемых считывателей и типов носителей может быть изменен.

struct _LPSZ_CONTAINER_NAME {

LPSTR lpszName;
};

См. также:

CPAcquireContext() , CPGetProvParam() , CPSetProvParam() , CPAcquireContext() в MS CSP , CPGetProvParam() в MS CSP , CPSetProvParam() в MS CSP , CryptAcquireContext() в MS CryptoAPI 2.0 , CryptGetProvParam() в MS CryptoAPI 2.0 , CryptSetProvParam() в MS CryptoAPI 2.0


Дополнительные параметры и определения

Предназначены для взаимодействия с программами пользователя непосредственно использующими "КриптоПро CSP". Идентификаторы DP1 - DP9 используются только программой doxygen.exe при формировании файла Ext_CSP_index.chm.
Макросы | Описание
#define DP1 | Идентификаторы алгоритмов криптопровайдера.
#define DP2 | Режимы шифрования.
#define DP3 | Дополнительные параметры криптопровайдера.
#define DP4 | Параметры дополнительных ключевых блобов.
#define DP5 | Дополнительные параметры объекта хеширования.
#define DP6 | Дополнительные параметры ключей.
#define DP7 | Дополнительные коды ошибок криптопровайдера.
#define DP8 | Групповые идентификаторы криптографических параметров алгоритмов.
#define DP9 | Идентификаторы криптографических параметров алгоритмов.


DP1

Идентификаторы алгоритмов криптопровайдера.

Идентификаторы алгоритмов приведены в файле WinCryptEx.h
Идентификатор | Описание идентификатора
CALG_GR3411 | Идентификатор алгоритма хеширования по ГОСТ Р 34.11-94.
CALG_G28147_MAC | Идентификатор алгоритма имитозащиты по ГОСТ 28147 89.
CALG_G28147_IMIT | Идентификатор алгоритма имитозащиты по ГОСТ 28147 89.
CALG_GR3410 | Идентификатор алгоритма имитозащиты по ГОСТ 28147 89.
CALG_GR3410EL | Идентификатор алгоритма ЭЦП по ГОСТ Р 34.10-2001.
CALG_G28147 | Идентификатор алгоритма шифрования по ГОСТ 28147 89.
CALG_DH_EX_SF | Идентификатор алгоритма обмена ключей по Диффи-Хеллману на базе секретного ключа пользователя.
CALG_DH_EX_EPHEM | Идентификатор CALG_DH_EX алгоритма обмена ключей по Диффи-Хеллману на базе эфемерного секретного ключа. Открытый ключ получается по ГОСТ Р 34.10 94.
CALG_DH_EX | Идентификатор CALG_DH_EX алгоритма обмена ключей по Диффи-Хеллману на базе секретного ключа пользователя. Открытый ключ получается по ГОСТ Р 34.10 94.
CALG_DH_EL_SF | Идентификатор алгоритма обмена ключей по Диффи-Хеллману на базе секретного ключа пользователя. Открытый ключ получается по ГОСТ Р 34.10 2001.
CALG_DH_EL_EPHEM | Идентификатор алгоритма обмена ключей по Диффи-Хеллману на базе эфемерного секретного ключа. Открытый ключ получается по ГОСТ Р 34.10 2001.
CALG_PRO_AGREEDKEY_DH | Идентификатор алгоритма выработки ключа парной связи по Диффи-Хеллману.
CALG_PRO_EXPORT | Идентификатор алгоритма защищённого экспорта ключа.
CALG_SIMPLE_EXPORT | Идентификатор алгоритма простого экспорта ключа.
CALG_SIMMETRYKEY | Идентификатор алгоритма шифрования по ГОСТ 28147 8.
CALG_TLS1_MASTER_HASH | Идентификатор алгоритма выработки объекта MASTER_HASH протокола TLS1.
CALG_TLS1_MAC_KEY | Идентификатор алгоритма выработки ключа имитозащиты протокола TLS1.
CALG_TLS1_ENC_KEY | Идентификатор алгоритма выработки ключа шифрования протокола TLS1.
CALG_PRO_DIVERS | Идентификатор алгоритма КриптоПро диверсификации ключа.
CALG_RIC_DIVERS | Идентификатор алгоритма РИК диверсификации ключа.

#define DP1


DP2

Режимы шифрования.

Определения данных параметров приведены в файле WinCryptEx.h
Параметр | Значение параметра
CRYPT_PROMIX_MODE | Задание режимов шифрования/расшифрования по ГОСТ 28147-89 с преобразованием ключа через каждые 1 КВ обрабатываемой информации
CRYPT_SIMPLEMIX_MODE | Задание режимов шифрования/расшифрования по ГОСТ 28147-89 без преобразования ключа в процессе обработки информации

#define DP2


DP3

Дополнительные параметры криптопровайдера.

Определения данных параметров приведены в файле WinCryptEx.h

Параметр | Значение параметра
PP_ENUMOIDS_EX | Задает перечень идентификаторов объектов, используемых в криптопровайдере
PP_HASHOID | Выдает установленный в контейнере OID узла замены функции хеширования ГОСТ Р 34.11-94 для наследования криптографическими объектами
PP_CIPHEROID | Выдает установленный в контейнере OID узла замены алгоритма шифрования ГОСТ 28147-89 для наследования криптографическими объектами
PP_SIGNATUREOID | Выдает установленный в контейнере OID параметров цифровой подписи для наследования криптографическими объектами
PP_DHOID | Выдает установленный в контейнере OID параметров алгоритма Диффи-Хеллмана для наследования криптографическими объектами
PP_CHECKPUBLIC | Флаг контроля открытого ключа. Если флаг установлен, осуществляется проверка алгебраических свойств открытого ключа

Параметры криптопровайдера, используемые для перехода на платформы, отличные от WIN32

Параметр | Значение параметра
PP_ANSILASTERROR | Запрос последней ошибки при обращении к функциям ANSI
PP_RANDOM | Выдает блоб типа SIMPLEBLOB для инициализации ДСЧ в драйвере шифрования
PP_DRVCONTAINER | Выдает указатель (handel) контейнера в драйвере
PP_MUTEX_ARG | Инициализирует синхронизацию потоков криптопровайдера в драйверном исполнении
PP_ENUM_HASHOID | Задает в провайдере перечень идентификаторов криптографических объектов, связанных с функцией хеширования
PP_ENUM_CIPHEROID | Задает в провайдере перечень идентификаторов криптографических объектов, связанных с функцией шифрования
PP_ENUM_SIGNATUREOID | Задает в провайдере перечень идентификаторов криптографических объектов, связанных с функцией цифровой подписи
PP_ENUM_DHOID | Задает в провайдере перечень идентификаторов криптографических объектов, связанных с алгоритмом Диффи-Хеллмана

#define DP3


DP4

Параметры дополнительных ключевых блобов.

Определения данных параметров приведены в файле WinCryptEx.h
Параметр | Значение параметра
DIVERSKEYBLOB | Тип ключевого блоба для диверсификации ключей с помощью функции CPImportKey в режиме ключа импорта CALG_PRO_EXPORT

#define DP4


DP5

Дополнительные параметры объекта хеширования.

Определения данных параметров приведены в файле WinCryptEx.h
Параметр | Значение параметра
HP_HASHSTARTVECT | Стартовый вектор функции хештрования, устанавливаемый приложением
HP_OID | Задает узел замены функции хеширования

#define DP5


DP6

Дополнительные параметры ключей.

Определения данных параметров приведены в файле WinCryptEx.h

Параметр | Значение параметра
KP_IV | Начальный вектор инициализации алгоритма шифрования ГОСТ 28147-89
KP_MIXMODE | Определяет использование преобразования ключа после обработки 1КВ информации в режимах шифрования/расшифрования и вычисления имитовставки алгоритма ГОСТ 28147-89
KP_OID | Задает узел замены функции хеширования
KP_HASHOID | Идентификатор узла замены функции хеширования ГОСТ Р 34.11-94
KP_CIPHEROID | Идентификатор узла замены алгоритма шифрования ГОСТ 28147-89
KP_SIGNATUREOID | Идентификатор параметров цифровой подписи
KP_DHOID | Идентификатор параметров алгоритма Диффи-Хеллмана

#define DP6


DP7

Дополнительные коды ошибок криптопровайдера.

Определения кодов приведены в файле WinCryptEx.h

Параметр | Значение параметра
GPE_FAIL_TESTBUFFER | Последовательности ДСЧ не прошла статистический контроль на материале 1 КВ
GPE_FAIL_STATBUFFER | Последовательности ДСЧ не прошла статистический контроль на материале 18 КВ
GPE_DIFERENT_PARAMETERS | Неправильные параметры
GPE_CORRUPT_KEYCONTEXT | Нарушена целостность ключей алгоритма ГОСТ 28147-89
GPE_CHECKPROC_GAMMING_OFB | Ошибка в режиме гаммирования алгоритма ГОСТ 28147-89
GPE_CHECKPROC_ENCRYPT_CFB | Ошибка в режиме гаммирования с обратной связьюалгоритма ГОСТ 28147-89
GPE_CHECKCARRIER | При закрытии ключевого контейнера в считывателе отсутствует или подменен ключевой носитель
GPE_CORRUPT_KEYPAIR_INFO | Искажена ключевая пара цифровой подписи
GPE_CHECKPROC_TESTFAIL | Ошибка при тестировании функций провайдера
GPE_RANDOMFAIL | Ошибка в функционировании ДСЧ

Коды ошибок возвращаются 4 байтами в аргументе pbData функции CryptGetProvParam() при значении аргумента hProv=PP_LAST_ERROR.

#define DP7


DP8

Групповые идентификаторы криптографических параметров алгоритмов.

Определения идентификаторов приведены в файле WinCryptEx.h

Параметр | Индекс | Значение параметра
szOID_CP_GOST_28147 | "1.2.643.2.2.21" | Алгоритм шифрования ГОСТ 28147-89
szOID_CP_GOST_R3411 | "1.2.643.2.2.9" | Функция хеширования ГОСТ Р 34.11-94
szOID_CP_GOST_R3410 | "1.2.643.2.2.20" | Алгоритм ГОСТ Р 34.10-94, используемый при экспорте/импорте ключей
szOID_CP_GOST_R3410EL | "1.2.643.2.2.19" | Алгоритм ГОСТ Р 34.10-2001, используемый при экспорте/импорте ключей
szOID_CP_DH_EX | "1.2.643.2.2.99" | Алгоритм Диффи-Хеллмана на базе потенциальной функции
szOID_CP_DH_EL | "1.2.643.2.2.98" | Алгоритм Диффи-Хеллмана на базе эллиптической кривой
szOID_CP_GOST_R3411_R3410 | "1.2.643.2.2.4" | Алгоритм цифровой подписи ГОСТ Р 34.10-94
szOID_CP_GOST_R3411_R3410EL | "1.2.643.2.2.3" | Алгоритм цифровой подписи ГОСТ Р 34.10-2001
szOID_KP_TLS_PROXY | "1.2.643.2.2.34.1" | Аудит TLS-трафика
szOID_KP_RA_CLIENT_AUTH | "1.2.643.2.2.34.2" | Идентификация пользователя на центре регистрации
szOID_KP_WEB_CONTENT_SIGNING | "1.2.643.2.2.34.3" | Подпись содержимого сервера Интернет

#define DP8


DP9

Идентификаторы криптографических параметров алгоритмов.

Определения идентификаторов приведены в файле WinCryptEx.h

Параметр | Индекс | Значение параметра
OID_HashTest | "1.2.643.2.2.30.0" | Тестовый узел замены
OID_HashVerbaO | "1.2.643.2.2.30.1" | Узел замены функции хеширования, вариант "Верба-О"
OID_HashVerba_1 | "1.2.643.2.2.30.2" | Узел замены функции хеширования, вариант 1
OID_HashVerba_2 | "1.2.643.2.2.30.3" | Узел замены функции хеширования, вариант 2
OID_HashVerba_3 | "1.2.643.2.2.30.4" | Узел замены функции хеширования, вариант 3
OID_HashVar_Default | "1.2.643.2.2.30.1" | Узел замены функции хеширования, дефолтовый вариант. В качестве дефолтового используется узел замены варианта "Верба-О"
OID_CryptTest | "1.2.643.2.2.31.0" | Тестовый узел замены алгоритма шифрования
OID_CipherVerbaO | "1.2.643.2.2.31.1" | Узел замены алгоритма шифрования,вариант "Верба-О"
OID_CipherVerba_1 | "1.2.643.2.2.31.2" | Узел замены алгоритма шифрования,вариант 1
OID_CipherVerba_2 | "1.2.643.2.2.31.3" | Узел замены алгоритма шифрования,вариант 2
OID_CipherVerba_3 | "1.2.643.2.2.31.4" | Узел замены алгоритма шифрования,вариант 3
OID_CipherVar_Default | "1.2.643.2.2.31.0" | Узел замены функции алгоритма шифрования, дефолтовый вариант. В качестве дефолтового используется узел замены варианта "Верба-О
OID_CipherOSCAR | "1.2.643.2.2.31.5" | Узел замены, вариант карты КриптоРИК
OID_CipherTestHash | "1.2.643.2.2.31.6" | Узел замены, используемый при шифровании с хешированием
OID_SignDH128VerbaO | "1.2.643.2.2.32.2" | Параметры P,Q,A цифровой подписи ГОСТ Р 34.10-94, вариант "Верба-О". Могут использоваться также в алгоритме Диффи-Хеллмана
OID_SignDH128Verba_1 | "1.2.643.2.2.32.3" | Параметры P,Q,A цифровой подписи ГОСТ Р 34.10-94, вариант 1. Могут использоваться также в алгоритме Диффи-Хеллмана
OID_SignDH128Verba_2 | "1.2.643.2.2.32.4" | Параметры P,Q,A цифровой подписи ГОСТ Р 34.10-94, вариант 2. Могут использоваться также в алгоритме Диффи-Хеллмана
OID_SignDH128Verba_3 | "1.2.643.2.2.32.5" | Параметры P,Q,A цифровой подписи ГОСТ Р 34.10-94, вариант 3. Могут использоваться также в алгоритме Диффи-Хеллмана
OID_DH128Var_1 | "1.2.643.2.2.33.1" | Параметры P,Q,A алгоритма Диффи-Хеллмана на базе экспоненциальной функции, вариант 1
OID_DH128Var_2 | "1.2.643.2.2.33.2" | Параметры P,Q,A алгоритма Диффи-Хеллмана на базе экспоненциальной функции, вариант 2
OID_DH128Var_3 | "1.2.643.2.2.33.3" | Параметры P,Q,A алгоритма Диффи-Хеллмана на базе экспоненциальной функции, вариант 3
OID_ECCTest3410 | "1.2.643.2.2.35.0" | Тестовые параметры a, b, p,q, (x,y) алгоритма ГОСТ Р 34.10-2001
OID_ECCSignDHPRO | "1.2.643.2.2.35.1" | Параметры a, b, p,q, (x,y) цифровой подписи и алгоритма Диффи-Хеллмана на базе алгоритма ГОСТ Р 34.10-2001, вариант провайдера
OID_ECCSignDHOSCAR | "1.2.643.2.2.35.2" | Параметры a, b, p,q, (x,y) цифровой подписи и алгоритма Диффи-Хеллмана на базе алгоритма ГОСТ Р 34.10-2001, вариант карты КриптоРИК
OID_ECCDHPRO | "1.2.643.2.2.36.0" | Параметры a, b, p,q, (x,y) алгоритма Диффи-Хеллмана на базе алгоритма ГОСТ Р 34.10-2001, вариант провайдера. Используются те же параметры, что и с идентификатором OID_ECCSignDHPRO
OID_ECCSignDHVar1 | "1.2.643.2.2.35.3" | Параметры a, b, p,q, (x,y) цифровой подписи и алгоритма Диффи-Хеллмана на базе алгоритма ГОСТ Р 34.10-2001.

#define DP9


LPSZ_CONTAINER_NAME

Имя контейнера.

Является нуль-терминированой строкой идентифицирующей носитель ключевой информации.

Возможные значения имени контейнера:
Значение | Описание
NULL | Контейнер по умолчанию. Если конфигурация "Крипто-Про CSP" настроена на хранение ключей на диске, то именем контейнера по умолчанию является имя пользователя ОС, вызвавшего CSP.
CONTAINER | Имя контейнера.
MEDIA\UNIQUE | Контейнер по умолчанию на носителе (MEDIA\UNIQUE).
MEDIA\UNIQUE\FOLDER | Контейнер на заданном носителе (MEDIA\UNIQUE). Если носитель не поддерживает уникальных имен, то уникальное имя носителя отсутствует, но символ \ опускать в этом случае нельзя. Если носитель поддерживает длинные имена (например, реестр), то имя контейнера в этом случае совпадает FOLDER.
MEDIA\UNIQUE\FOLDER\CRC | Контейнер на заданном носителе (MEDIA\UNIQUE) с именем CRC16 которого совпадает с CRC. Если носитель не поддерживает уникальных имен, то уникальное имя носителя отсутствует, но символ \ опускать в этом случае нельзя.
\\.\READER\MEDIA\UNIQUE | Контейнер по умолчанию на носителе (MEDIA\UNIQUE), с заданным именем считывателя.
\\.\READER\MEDIA\UNIQUE\FOLDER | Контейнер на заданном носителе (MEDIA\UNIQUE), с заданным именем считывателя. Если носитель не поддерживает уникальных имен, то уникальное имя носителя отсутствует, но символ \ опускать в этом случае нельзя. Если носитель поддерживает длинные имена (например, реестр), то имя контейнера в этом случае совпадает с FOLDER.
\\.\READER\MEDIA\UNIQUE\FOLDER\CRC | Контейнер на заданном носителе (MEDIA\UNIQUE), с заданным именем считывателя и CRC16 имени контейнера совпадает с CRC Если носитель не поддерживает уникальных имен, то уникальное имя носителя отсутствует, но символ \ опускать в этом случае нельзя. Если носитель поддерживает длинные имена (например, реестр), то имя контейнера в этом случае совпадает с FOLDER.
\\.\READER\CONTAINER | Имя контейнера на заданном считывателе.
\\.\READER | Контейнер по умолчанию на заданном считывателе.

Во всех перечисленных выше формах (кроме NULL), оконечный символ \ не влияет на смысл контейнера.

Пользователь задаёт имя контейнера, возможно с заданием имени считывателя, в аргументах функции CPAcquireContext().

Функция CPGetProvParam() возвращает:

  • имя контейнера (CONTAINER) как параметр PP_CONTAINER
  • и возвращает уникальное имя (MEDIA\UNIQUE\FOLDER\CRC) контейнера как параметр PP_UNIQUE_CONTAINER (Значение UNIQUE отсутствует для считывателей, не поддерживающих уникальность имен. Значение CRC отсутствует для носителей, поддерживающих длинные имена, т.е. для которых имя FOLDER ВСЕГДА совпадает с именем NAME).
На данный момент поддерживаются следующие считыватели (READER):
Имя | Описание
FAT12_[DRIVE] | дисковод, где [DRIVE] имя дисковода, например для дисковода A: имя FAT12_A (Windows, Solaris)
DS9097E_[COM], DS9097U_[COM], DS1410E_[LPT] | считыватель Touch-Memory, где [COM] ([LPT]) имя COM (LPT) порта, например для считывателя Touch-Memory DS9097E посоединенного ко второму COM порту его имя будет DS9097E_COM1 (Windows)
ACCORD | считыватель Touch-Memory через ACCORD (Windows)
SABLE | считыватель Touch-Memory через Соболь (Windows)
REGISTRY | считыватель ключей хранимых в реестре Windows (Windows)
HDIMAGE | считыватель ключей хранимых в файлах на диске (Solaris)
[PCSC считыватель] | считыватель смарт-карт через интерфейс PCSC, где [PCSC считыватель] имя считывателя так как он зарегистрирован, например для первого зарегистрированного считывателя GCR410 имя будет "GEMPLUS GCR410P 0" (Windows)

Поддерживаются следующие типы носителей (MEDIA):
Имя | Описание
FAT12 | дискета (или любой другой отчуждаемый носитель, поддерживающий файловую систему) (Windows, Solaris)
DS | Touch-Memory (Windows)
REGISTRY | реестр. Поддерживает длинные имена (Windows)
HDIMAGE | НЖМД. (Solaris)
SCARD | смарт-карта, или любое другое устройство с интерфейсом смарт-карты, например eToken. (Windows)

Вид уникального номера (UNIQUE) носителя в зависимости от его типа носителя:
Тип носителя | Вид уникального номера | Описание
Дискета | [SERIAL]_[VOLUME] | [SERIAL] серийный номер дискеты, 8 16-ричных цифр (задается при форматировании), [VOLUME] - метка тома 11 символов (задается при форматировании или, если нет метки, то при генерации первого контейнера). Если метка тома, по каким-то причинам отсутствует, то уникальное имя будет представлено в виде [SERIAL].
Touch-Memory | [тип]_[номер] | [тип] - тип Touch-memory на текущий момент поддерживаются 1993, 1994, 1995, 1996. [номер] - 6 16-ричных цифр уникального номера таблетки.
смарт-карта MPCOS 3DES | MPCOS-EMV_[номер] | [номер] - 16 16-ричных цифр уникального номера карты
смарт-карта и электронный ключ РИК | RIC_[номер] | [номер] 8 16-ричных цифр уникального номера карты
электронный ключ eToken HS | eToken_HS_[номер] | [номер] - 16 16-ричных цифр уникального номера электронного ключа
реестр | не поддерживается | не поддерживается

Вид имени папки (FOLDER) носителя в зависимости от типа носителя:
Тип носителя | Вид имени папки | Описание
Дискета | [имя].[NNN] | [имя] - 8 первых символов имени контейнера; Для символов от 'a' до 'z', от 'A' до 'Z', от '0' до '9' и символа '-' симолы остаются без изменений, для отсальных символов происходит замена на символ с ASCII кодом вычисляемым по формула c%('z'-'a'+1)+'a', где c исходный симол имени контейнера. [NNN] - порядковый номер контейнера на этом носителе внутри множества совпадающих имен [имя].
Touch-Memory | [N] | [N] - 16-ричных порядковый номер контейнера на носителе
смарт-карта и электронные ключи | не поддерживается | не поддерживается
реестр | [имя] | [имя] - имя контейнера

Список поддерживаемых считывателей и типов носителей может быть изменен.

typedef struct _LPSZ_CONTAINER_NAME    LPSZ_CONTAINER_NAME;

См. также:

CPAcquireContext() , CPGetProvParam() , CPSetProvParam() , CPAcquireContext() в MS CSP , CPGetProvParam() в MS CSP , CPSetProvParam() в MS CSP , CryptAcquireContext() в MS CryptoAPI 2.0 , CryptGetProvParam() в MS CryptoAPI 2.0 , CryptSetProvParam() в MS CryptoAPI 2.0


CRYPT_CHANGE_PIN_PARAM_ Struct Reference

Описание структуры CRYPT_CHANGE_PIN_PARAM_

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

struct CRYPT_CHANGE_PIN_PARAM_ {
   BYTE type;
   CRYPT_CHANGE_PIN_SOURCE dest;
};

Описание данных, членов структуры

dest
Данные соответствующего типа
type
Тип данных. CRYPT_CHANGE_PIN_PASSWD - пароль или PIN, CRYPT_CHANGE_PIN_CONTAINER - имя контейнера зашифрования, CRYPT_CHANGE_PIN_HANDLE_CONTAINER - HANDLE контейнера зашифрования. Используется имя контейнера. CRYPT_CHANGE_PIN_HANDLE_UNIQUE - HANDLE контейнера зашифрования. Используется уникальное имя контейнера. CRYPT_CHANGE_PIN_WINDOW - тип и значение выбираются в окне, CRYPT_CHANGE_PIN_CLEAR - очитсить пароль.

Требования:

Windows NT/2000: Необходимо Windows NT 4.0 или старше с Internet Explorer 5.0 или старше.
Windows 95/98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле WinCryptEx.h или CSP_WinCrypt.h для Solaris.

См. также:

CPSetProvParam()


CRYPT_CHANGE_PIN_SOURCE_ Union Reference

Описание объединения CRYPT_CHANGE_PIN_SOURCE_

Структура передачи пароля, pin-кода, имени контейнера, HANDLE контейнера при смене пароля.

union CRYPT_CHANGE_PIN_SOURCE_ {

char* passwd

HCRYPTPROV prov

};

Описание данных, членов объединения

passwd
Пароль, PIN-код, имя контейнера.
prov
HANDLE контейнера.


Example Documentation

ctkey.c

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

/*
 * Copyright(C) 2000-2001 Проект ИОК
 *
 * Этот файл содержит информацию, являющуюся
 * собственностью компании Крипто Про.
 *
 * Любая часть этого файла не может быть скопирована,
 * исправлена, переведена на другие языки,
 * локализована или модифицирована любым способом,
 * откомпилирована, передана по сети с или на
 * любую компьютерную систему без предварительного
 * заключения соглашения с компанией Крипто Про.
 *
 * Программный код, содержащийся в этом файле, предназначен
 * исключительно для целей обучения и не может быть использован
 * для защиты информации.
 *
 * Компания Крипто-Про не несет никакой
 * ответственности за функционирование этого кода.
 */

#include "tmain.h"

#ifdef UNIX
#include "CSP_WinCrypt.h"
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#include <link.h>

extern DWORD GetLastError(void);
#endif /* UNIX */

#ifndef PROG
#define PROG main_keyset
#endif

#if !defined(UNIX)
extern HANDLE   hCSPDLL = 0;        /* Дескриптор загруженного модуля криптопровайдера*/
#else
extern void     *hCSPDLL = NULL;    /* Дескриптор загруженного модуля криптопровайдера*/
#endif /* !defined(UNIX) */

#ifdef UNIX
static BOOL CPlevel=1;  /* Флаг непосредственного использования функций криптопровайдера*/
#else /* UNIX */
static BOOL CPlevel;    /* Флаг непосредственного использования функций криптопровайдера*/
#endif /* UNIX */

#ifndef UNIX
/*-------------------------------------------------------------------*/
/* Определение функции, загружающей криптопровайдер по заданному типу*/
typedef struct _VTABLEPROVSTRUC {
    DWORD Version;
    FARPROC FuncVerifyImage;
    FARPROC FuncReturnhWnd;
    DWORD dwProvType;
    BYTE *pbContextInfo;
    DWORD cbContextInfo;
    LPSTR pszProvName;
} VTABLEPROVSTRUC, *PVTABLEPROVSTRUC;
#endif /* UNIX */

/*------------------------------------------------------*/
/* Определение функции CPAcquireContext*/
typedef BOOL (WINAPI *CPAcquireContext_t) (
    HCRYPTPROV *phProv,       /* out*/
    CHAR *pszContainer,       /* in, out*/
    DWORD dwFlags,            /* in*/
    PVTABLEPROVSTRUC pVTable  /* in*/
);
static CPAcquireContext_t MyAcquireContext;

/*------------------------------------------------------*/
/* Определение функции CPGetProvParam */
typedef BOOL (WINAPI *CPGetProvParam_t) (
    HCRYPTPROV hProv,  /* in*/
    DWORD dwParam,     /* in*/
    BYTE *pbData,      /* out*/
    DWORD *pdwDataLen, /* in, out*/
    DWORD dwFlags      /* in*/
);
static CPGetProvParam_t MyGetProvParam;

/*------------------------------------------------------*/
/* Определение функции CPSetProvParam */
typedef BOOL (WINAPI *CPSetProvParam_t) (
    HCRYPTPROV hProv,  /* in*/
    DWORD dwParam,     /* in*/
    BYTE *pbData,      /* in*/
    DWORD dwFlags      /* in*/
);
static CPSetProvParam_t MySetProvParam;

/*------------------------------------------------------*/
/* Определение функции CPGetUserKey */
typedef BOOL (WINAPI *CPGetUserKey_t) (
    HCRYPTPROV hProv,
    DWORD dwKeySpec,
    HCRYPTKEY *phUserKey
);
static CPGetUserKey_t MyGetUserKey;

/*------------------------------------------------------*/
/* Определение функции CPGenKey */
typedef BOOL (WINAPI *CPGenKey_t) (
    HCRYPTPROV hProv,     /* in*/
    ALG_ID Algid,         /* in*/
    DWORD dwFlags,        /* in*/
    HCRYPTKEY *phKey     /* out*/
);
static CPGenKey_t MyGenKey;

/*------------------------------------------------------*/
/* Определение функции CPExportKey */
typedef BOOL (WINAPI *CPExportKey_t) (
    HCRYPTPROV hProv,      /* in*/
    HCRYPTKEY hKey,        /* in*/
    HCRYPTKEY hPubKey,     /* in*/
    DWORD dwBlobType,      /* in*/
    DWORD dwFlags,         /* in*/
    BYTE *pbData,          /* out*/
    DWORD *pdwDataLen      /* in, out*/
);
static CPExportKey_t MyExportKey;

/*------------------------------------------------------*/
/* Определение функции CPImportKey */
typedef BOOL (WINAPI *CPImportKey_t) (
    HCRYPTPROV hProv,       /* in*/
#ifndef UNIX
    CONST
#endif /* UNIX */
BYTE *pbData,     /* in*/
    DWORD  dwDataLen,       /* in*/
    HCRYPTKEY hPubKey,      /* in*/
    DWORD dwFlags,          /* in*/
HCRYPTKEY *phKey        /* out*/
);
static CPImportKey_t MyImportKey;

/*------------------------------------------------------*/
/* Определение функции CPGetKeyParam*/
typedef BOOL (WINAPI *CPGetKeyParam_t) (
    HCRYPTPROV hProv,       /* in*/
    HCRYPTKEY hKey,         /* in*/
    DWORD dwParam,          /* in*/
    BYTE *pbData,           /* out*/
    DWORD *pdwDataLen,      /* in, out*/
    DWORD dwFlags           /* in*/
);
static CPGetKeyParam_t MyGetKeyParam;

/*------------------------------------------------------*/
/* Определение функции CPSetKeyParam*/
typedef BOOL (WINAPI *CPSetKeyParam_t) (
    HCRYPTPROV hProv,       /* in*/
    HCRYPTKEY hKey,         /* in*/
    DWORD dwParam,          /* in*/
    BYTE *pbData,           /* in*/
    DWORD dwFlags           /* in*/
);
static CPSetKeyParam_t MySetKeyParam;

/*------------------------------------------------------*/
/* Определение функции CPCreateHash */
typedef BOOL (WINAPI *CPCreateHash_t) (
    HCRYPTPROV hProv,    /* in*/
    ALG_ID Algid,        /* in*/
    HCRYPTKEY hKey,      /* in*/
    DWORD dwFlags,       /* in*/
    HCRYPTHASH *phHash   /* out*/
);
static CPCreateHash_t MyCreateHash;

/*------------------------------------------------------*/
/* Определение функции CPGetHashParam */
typedef BOOL (WINAPI *CPGetHashParam_t) (
    HCRYPTPROV hProv,        /* in*/
    HCRYPTHASH hHash,        /* in*/
    DWORD dwParam,           /* in*/
    BYTE *pbData,            /* out*/
    DWORD *pdwDataLen,       /* in, out*/
    DWORD dwFlags            /* in*/
);
static CPGetHashParam_t MyGetHashParam;

/*------------------------------------------------------*/
/* Определение функции CPDestroyHash */
typedef BOOL (WINAPI *CPDestroyHash_t) (
    HCRYPTPROV hProv, /* in*/
    HCRYPTHASH hHash  /* in*/
);
static CPDestroyHash_t MyDestroyHash;

/*------------------------------------------------------*/
/* Определение функции CPHashData */
typedef BOOL (WINAPI *CPHashData_t) (
    HCRYPTPROV hProv,       /* in*/
    HCRYPTHASH hHash,       /* in*/
#ifndef UNIX
    CONST
#endif /* UNIX */
BYTE *pbData,     /* in*/
    DWORD dwDataLen,        /* in*/
    DWORD dwFlags           /* in*/
);
static CPHashData_t MyHashData;

/*------------------------------------------------------*/
/* Определение функции CPSignHash */
typedef BOOL (WINAPI *CPSignHash_t) (
    HCRYPTPROV hProv,           /* in*/
    HCRYPTHASH hHash,           /* in*/
    DWORD dwKeySpec,            /* in*/
    LPCWSTR sDescription,       /* in*/
    DWORD dwFlags,              /* in*/
    BYTE *pbSignature,          /* out*/
    DWORD *pdwSigLen            /* in, out*/
);
static CPSignHash_t MySignHash;

/*------------------------------------------------------*/
/* Определение функции CPVerifySignature */
typedef BOOL (WINAPI *CPVerifySignature_t) (
    HCRYPTPROV hProv,         /* in*/
    HCRYPTHASH hHash,         /* in*/
#ifndef UNIX
    CONST
#endif /* UNIX */
    BYTE *pbSignature,  /* in*/
    DWORD dwSigLen,           /* in*/
    HCRYPTKEY hPubKey,        /* in*/
    LPCWSTR sDescription,     /* in*/
    DWORD dwFlags             /* in*/
);
static CPVerifySignature_t MyVerifySignature;

/*------------------------------------------------------*/
/* Определение функции CPDestroyKey */
typedef BOOL (WINAPI *CPDestroyKey_t) (
    HCRYPTPROV hProv,  /* in*/
    HCRYPTKEY  hKey    /* in*/
);
static CPDestroyKey_t MyDestroyKey;

/*------------------------------------------------------*/
/* Определение функции CPReleaseContext */
typedef BOOL (WINAPI *CPReleaseContext_t) (
    HCRYPTPROV hProv,  /* in*/
    DWORD dwFlags      /* in*/
);
static CPReleaseContext_t MyReleaseContext;

/*------------------------------------------------------*/
int show_info (HCRYPTPROV hProv, HCRYPTKEY hKeyS, HCRYPTKEY hKeyE);

static BOOL CopyKeyParam( HCRYPTPROV hSrcProv, HCRYPTPROV hDestProv,
    DWORD param, HCRYPTKEY hSrcKey, HCRYPTKEY hDestKey );
static BOOL CopyPrivateKey( HCRYPTPROV hSrc, HCRYPTPROV hDest,
    HCRYPTKEY hKey );
static BOOL CopyContainerParam( HCRYPTPROV hSrc, HCRYPTPROV hDest );
static BOOL CopyContainerParam1( HCRYPTPROV hSrc, HCRYPTPROV hDest,
    DWORD pp );
static char *GetContainerName( int cplevel, PVTABLEPROVSTRUC st,
    char * szProvider, DWORD dwProvType );

#ifdef UNIX
#define UniSetProvParam(hP,p1,p2,p3) (MySetProvParam(hP,p1,p2,p3))
#define UniGetProvParam(hP,p1,p2,p3,p4) (MyGetProvParam(hP,p1,p2,p3,p4))
#define UniGetUserKey(hP,p1,p2) (MyGetUserKey(hP,p1,p2))
#define UniGenKey(hP,p1,p2,p3) (MyGenKey(hP,p1,p2,p3))
#define UniSignHash(hP,p1,p2,p3,p4,p5,p6) (MySignHash(hP,p1,p2,p3,p4,p5,p6))
#define UniExportKey(hP,p1,p2,p3,p4,p5,p6) (MyExportKey(hP,p1,p2,p3,p4,p5,p6))
#define UniDestroyKey(hP,p1) (MyDestroyKey(hP,p1))
#define UniImportKey(hP,p1,p2,p3,p4,p5) (MyImportKey(hP,p1,p2,p3,p4,p5))
#define UniGetKeyParam(hP,p1,p2,p3,p4,p5) (MyGetKeyParam(hP,p1,p2,p3,p4,p5))
#define UniSetKeyParam(hP,p1,p2,p3,p4) (MySetKeyParam(hP,p1,p2,p3,p4))
#define UniReleaseContext(hP,p1) (MyReleaseContext(hP,p1))
#define UniVerifySignature(hP,p1,p2,p3,p4,p5,p6) (MyVerifySignature(hP,p1,p2,p3,p4,p5,p6))
#else /* UNIX */
#define UniSetProvParam(hP,p1,p2,p3) (CPlevel?MySetProvParam(hP,p1,p2,p3):CryptSetProvParam(hP,p1,p2,p3))
#define UniGetProvParam(hP,p1,p2,p3,p4) (CPlevel?MyGetProvParam(hP,p1,p2,p3,p4):CryptGetProvParam(hP,p1,p2,p3,p4))
#define UniGetUserKey(hP,p1,p2) (CPlevel?MyGetUserKey(hP,p1,p2):CryptGetUserKey(hP,p1,p2))
#define UniGenKey(hP,p1,p2,p3) (CPlevel?MyGenKey(hP,p1,p2,p3):CryptGenKey(hP,p1,p2,p3))
#define UniSignHash(hP,p1,p2,p3,p4,p5,p6) (CPlevel?MySignHash(hP,p1,p2,p3,p4,p5,p6):CryptSignHash(p1,p2,p3,p4,p5,p6))
#define UniExportKey(hP,p1,p2,p3,p4,p5,p6) (CPlevel?MyExportKey(hP,p1,p2,p3,p4,p5,p6):CryptExportKey(p1,p2,p3,p4,p5,p6))
#define UniDestroyKey(hP,p1) (CPlevel?MyDestroyKey(hP,p1):CryptDestroyKey(p1))
#define UniImportKey(hP,p1,p2,p3,p4,p5) (CPlevel?MyImportKey(hP,p1,p2,p3,p4,p5):CryptImportKey(hP,p1,p2,p3,p4,p5))
#define UniGetKeyParam(hP,p1,p2,p3,p4,p5) (CPlevel?MyGetKeyParam(hP,p1,p2,p3,p4,p5):CryptGetKeyParam(p1,p2,p3,p4,p5))
#define UniSetKeyParam(hP,p1,p2,p3,p4) (CPlevel?MySetKeyParam(hP,p1,p2,p3,p4):CryptSetKeyParam(p1,p2,p3,p4))
#define UniReleaseContext(hP,p1) (CPlevel?MyReleaseContext(hP,p1):CryptReleaseContext(hP,p1))
#define UniVerifySignature(hP,p1,p2,p3,p4,p5,p6) (CPlevel?MyVerifySignature(hP,p1,p2,p3,p4,p5,p6):CryptVerifySignature(p1,p2,p3,p4,p5,p6))
#endif /* UNIX */

static void crc16( const char *text, unsigned char *CRC );

#ifdef UNIX
extern int num_passes, num_threads;

#define FN_VERIFY_SIGNATURE 1
#define FN_GET_PROV_PARAM 2
#define FN_STRESS 3

typedef struct pthr_param_ {
  int func;
  HCRYPTPROV hProv;
  HCRYPTHASH hHash;
  BYTE *pb1;
  DWORD dw1;
  DWORD dw2;
  HCRYPTKEY hKey;
  LPCWSTR str;
  char *str1;
} pthr_param;

void *threaded_func(void *p)
{
  pthr_param *ppar=(pthr_param *)p;
  BOOL ret;
  int count;

  for(count=0;count<num_passes;count++){
    switch(ppar->func){
    case FN_VERIFY_SIGNATURE:
      ret=CPVerifySignature(ppar->hProv, ppar->hHash, ppar->pb1, ppar->dw1,
                            ppar->hKey, ppar->str, ppar->dw2);
      break;
    case FN_GET_PROV_PARAM:
      /*    ret=CPGetPRovParam */
      break;
    case FN_STRESS:{
      HCRYPTPROV hProv;
      VTABLEPROVSTRUC vTable;

      vTable.Version = 1; /* min*/
      vTable.FuncVerifyImage = NULL;
      vTable.FuncReturnhWnd = NULL;

      ret=CPAcquireContext(&hProv, ppar->str1, 0, &vTable);
      if(ret){
        ret=CPReleaseContext(hProv,0);
        if(!ret) printf("thread_func: CPReleaseContext: %d\n",ret);
      } else printf("thread_func: CPAcquireContext: %d\n",ret);
      break;
    }
    default:
      break;
    }
  }

  return (void*)ret;
}

BOOL do_threaded(pthr_param par)
{
  pthread_t *thread_ids;
  int i, ret = TRUE;
  void *pret;

  printf("Multithreaded: threads %d, passes %d\n",num_threads,num_passes);

  thread_ids=(pthread_t *)malloc(sizeof(pthread_t)*num_threads);
  if(!thread_ids) return FALSE;

  for(i=0;i<num_threads;i++){
    if(pthread_create(thread_ids+i, NULL, &threaded_func, (void*)&par)){
      ret=FALSE;
      goto exit;
    }
  }
  for(i=0;i<num_threads;i++){
    pthread_join(thread_ids[i], &pret);
    if(ret==TRUE) ret=(BOOL)pret;
  }
 exit:
  free(thread_ids);

  return ret;
}

BOOL ThrVerifySignature(
                       HCRYPTPROV hProv,         /* in*/
                       HCRYPTHASH hHash,         /* in*/
                       BYTE *pbSignature,  /* in*/
                       DWORD dwSigLen,           /* in*/
                       HCRYPTKEY hPubKey,        /* in*/
                       LPCWSTR sDescription,     /* in*/
                       DWORD dwFlags             /* in*/
                       )
{
  pthr_param par;

  par.func=FN_VERIFY_SIGNATURE;
  par.hProv=hProv;
  par.hHash=hHash;
  par.pb1=pbSignature;
  par.dw1=dwSigLen;
  par.dw2=dwFlags;
  par.hKey=hPubKey;
  par.str=sDescription;

  return do_threaded(par);
}
#endif /* UNIX */

/*------------------------------------------------------*/
/* MAIN */
/*------------------------------------------------------*/
int
PROG (int argc, char **argv)
{
    HCRYPTPROV  hProv = 0;          /* Дескриптор провайдера*/
    char *      szContainer = NULL; /* Имя ключевого контейнера*/
    char *      szCopyContainer = NULL; /* Имя результирующего ключевого контейнера. */
    char *      szProvider = NULL;  /* Имя провайдера*/
    DWORD dwProvType = PROV_GOST_DH; /*Тип провайдера по умолчанию*/

    HCRYPTKEY   hKeyS = 0;          /* Дескриптор ключа ЭЦП AT_SIGNATURE*/
    HCRYPTKEY   hKeyE = 0;          /* Дескриптор ключа обмена AT_EXCHANGE */
    BOOL        bResult = 0;        /* Код возврата*/
    ALG_ID      Algid;              /* Идентификатор алгоритма*/
    DWORD       dwFlags = 0;        /* Флаги*/
     DWORD      dwParam;
    BYTE        pbProvName [1024*4];
    DWORD       dwProvNameLen;
    BYTE        pbProvContainer [1024*4];
    DWORD       dwProvContainerLen;
    int         exported = 0;
    int         ret = 0;
    int         print_help = 0;
    int         c;
    int         show = 0;
    char        *infilename = NULL;
    char        *outfilename = NULL;
    char        *exportfilename = NULL;
    char        *importfilename = NULL;
    char        *signaturefilename = NULL;
    int         keyType = AT_KEYEXCHANGE | AT_SIGNATURE;
    int         sign = 0;
    int         verify = 0;
#ifdef UNIX
    int stress=0;
#endif /* UNIX */
    char        *ptr = NULL;
    HCRYPTKEY   hImportedKey = 0;
    HCRYPTKEY   hSignatureKey = 0;
    unsigned char *in_data = NULL;
    size_t      in_data_len = 0;
    ALG_ID      my_alg = CALG_GR3411;
    char        *my_hash_alg = NULL;
    HCRYPTHASH  hHash = 0;
    char        *pubkeyfilename = NULL;
    int         hash = 0;
    ALG_ID      hash_alg = CALG_GR3411;
    char        *ptr_hash_alg = NULL;
    char        *hashfile = NULL;
    ALG_ID      some_alg = 0;
#ifndef UNIX
    PCCRYPT_OID_INFO info = NULL;
#endif /* UNIX */
    DWORD       key_length = 0;
    int counter = 0;
    int enum_containers = 0;
    int hard_rng = 0;
    char        *password = NULL;
    char        *new_password = NULL;
    char        *new_encryption_container = NULL;
    int         change_passwd_wnd = 0;
    char        *enc_passwd = NULL;
    char        *enc_passwd2 = NULL;
    int         reboot = 0;
    DWORD       get_param = 0;
    const char  *get_param_text = "";
    char        *set_param = 0;
    DWORD       enum_param = 0;
    const char  *enum_param_text = "";
    int         unique = 0;
    int         fqcn = 0;
    int         crc = 0;

    VTABLEPROVSTRUC vTable;

    /*-----------------------------------------------------------------------------*/
    /* определение опций разбора параметров*/
    static struct option long_options[] = {
        {"cplevel",             no_argument,            NULL, 'l'},
        {"container",           required_argument,      NULL, 'c'},
        {"provider",            required_argument,      NULL, 'p'},
        {"provtype",            required_argument,      NULL, 't'},
        {"verifycontext",       no_argument,            NULL, 'v'},
        {"newkeyset",           no_argument,            NULL, 'n'},
        {"machinekeyset",       no_argument,            NULL, 'm'},
        {"deletekeyset",        no_argument,            NULL, 'd'},
        {"info",                no_argument,            NULL, 's'},
        {"keytype",             required_argument,      NULL, '1'},
        {"export",              required_argument,      NULL, '2'},
        {"import",              required_argument,      NULL, '3'},
        {"sign",                required_argument,      NULL, '4'},
        {"verify",              required_argument,      NULL, '5'},
        {"in",                  required_argument,      NULL, '6'},
        {"out",                 required_argument,      NULL, '7'},
        {"signature",           required_argument,      NULL, '8'},
        {"pubkey",              required_argument,      NULL, '9'},
        {"hash",                required_argument,      NULL, 'a'},
        {"hashout",             required_argument,      NULL, 'b'},
        {"alg",                 required_argument,      NULL, 'f'},
        {"calg",                required_argument,      NULL, 'x'},
        {"enum_param",          required_argument,      NULL, 'E'},
        {"get_param",           required_argument,      NULL, 'P'},
        {"set_param",           required_argument,      NULL, 'T'},
        {"hard_rng",            no_argument,            NULL, 'k'},
        {"general",             no_argument,            NULL, 'G'},
#if(_WIN32_WINNT >= 0x0500)
        {"silent",              no_argument,            NULL, 'i'},
#endif /*(_WIN32_WINNT >= 0x0500)*/
        {"exported",    no_argument,            NULL, 'e'},
        {"length",      required_argument,      NULL, 'g'},
        {"enum_containers", no_argument,        NULL, 'j'},
        {"passwd",      required_argument,      NULL, 'w'},
        {"chpasswd",    required_argument,      NULL, '0'},
        {"qchpasswd",   no_argument,            NULL, 'Q'},
        {"enchpasswd",  required_argument,      NULL, 'H'},
        {"enc_passwd",  required_argument,      NULL, '_'},
        {"enc_passwd2",  required_argument,     NULL, '+'},
        {"counter",     required_argument,      NULL, 'u'},
        {"reboot",      no_argument,            NULL, 'R'},
        {"copy",        required_argument,      NULL, 'C'},
        {"unique",      no_argument,            NULL, 'q'},
        {"fqcn",        no_argument,            NULL, '\\'},
        {"crc",         no_argument,            NULL, 'r'},
#ifdef UNIX
        {"stress",      no_argument,            NULL, 'S'},
#endif /* UNIX */
        {"help",        no_argument,            NULL, 'h'},
        {0, 0, 0, 0}
    };

    /*-----------------------------------------------------------------------------*/
    /* разбор параметров*/
    while ((c = getopt_long_only (argc, argv, "", long_options, (int *)0)) != EOF) {
        switch (c) {
#ifndef UNIX
        case 'f':
            some_alg = atol (optarg);

            info = CryptFindOIDInfo(CRYPT_OID_INFO_ALGID_KEY,
                (void*) &some_alg, 0);
            if (info) {
                printf ("Name: %S  OID: %s\n", info->pwszName, info->pszOID);
            }
            break;
        case 'x':
                printf ("alg: %s\n", optarg);
            info = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY, optarg,
                CRYPT_HASH_ALG_OID_GROUP_ID);
            if (info) {
                printf ("Name: %S  OID: %s %d %d\n", info->pwszName,
                    info->pszOID, info->Algid);
            }
            break;
#endif /* UNIX */
        case 'l':
            CPlevel = 1;
            break;
        case 's':
            show = 1;
            break;
        case 'c':
            szContainer = (char *)optarg;
            break;
        case 'q':
            unique = 1;
            break;
        case 'a':
            hash = 1;
            ptr_hash_alg = optarg;
            if (strcmp(ptr_hash_alg, "SHA1") == 0)
                hash_alg = CALG_SHA1;
            else if (strcmp(ptr_hash_alg, "GOST") == 0)
                hash_alg = CALG_GR3411;
            else if (strcmp(ptr_hash_alg, "MD2") == 0)
                hash_alg = CALG_MD2;
            else if (strcmp(ptr_hash_alg, "MD5") == 0)
                hash_alg = CALG_MD5;
            else {
                print_help = 1;
                goto bad;
            }
            break;
        case 'b':
            hashfile = optarg;
            break;
#ifndef UNIX
        case 'p':
            szProvider = abbr2provider (optarg);
            break;
        case 't':
            dwProvType = abbr2provtype (optarg);
            break;
#endif /* UNIX */
        case 'v':
            dwFlags |= CRYPT_VERIFYCONTEXT;
            break;
        case 'n':
            dwFlags |= CRYPT_NEWKEYSET;
            break;
        case 'm':
            dwFlags |= CRYPT_MACHINE_KEYSET;
            break;
        case 'd':
            dwFlags |= CRYPT_DELETEKEYSET;
            break;
        case 'G':
            dwFlags |= CRYPT_GENERAL;
            break;
        case '1':
            ptr = optarg;
            if (strcmp(ptr, "signature") == 0)
                keyType = AT_SIGNATURE;
            else if (strcmp(ptr, "exchange") == 0)
                keyType = AT_KEYEXCHANGE;
            else if (strcmp(ptr, "none") == 0)
                keyType = 0;
            else {
                print_help = 1;
                goto bad;
            }
            break;
        case '2':
            exportfilename = optarg;
            break;
        case '3':
            importfilename = optarg;
            break;
        case '4':
            sign = 1;
            my_hash_alg = optarg;
            if (strcmp(my_hash_alg, "SHA1") == 0)
                my_alg = CALG_SHA1;
            else if (strcmp(my_hash_alg, "GOST") == 0)
                my_alg = CALG_GR3411;
            else if (strcmp(my_hash_alg, "MD2") == 0)
                my_alg = CALG_MD2;
            else if (strcmp(my_hash_alg, "MD5") == 0)
                my_alg = CALG_MD5;
            else {
                print_help = 1;
                goto bad;
            }
            break;
        case '5':
            verify = 1;
            my_hash_alg = optarg;
            if (strcmp(my_hash_alg, "SHA1") == 0)
                my_alg = CALG_SHA1;
            else if (strcmp(my_hash_alg, "GOST") == 0)
                my_alg = CALG_GR3411;
            else if (strcmp(my_hash_alg, "MD2") == 0)
                my_alg = CALG_MD2;
            else if (strcmp(my_hash_alg, "MD5") == 0)
                my_alg = CALG_MD5;
            else {
                print_help = 1;
                goto bad;
            }
            break;
        case '6':
            infilename = optarg;
            break;
        case '7':
            outfilename = optarg;
            break;
        case '8':
            signaturefilename = optarg;
            break;
        case '9':
            pubkeyfilename = optarg;
            break;
        case 'k':
            hard_rng = 1;
            break;
#if(_WIN32_WINNT >= 0x0500)
        case 'i':
            dwFlags |= CRYPT_SILENT;
            break;
#endif /*(_WIN32_WINNT >= 0x0500)*/
        case 'e':
            exported = 1;
            break;
        case 'h':
            ret = 1;
            print_help = 1;
            goto bad;
        case 'g':
            key_length = atol (optarg);
            if( key_length != 1024 && key_length != 512 )
                goto bad;
            break;
        case 'u':
            counter = atol (optarg);
            break;
        case 'j':
            enum_containers = 1;
            break;
        case 'w':
            password = optarg;
            break;
        case '0':
            new_password = optarg;
            break;
        case 'Q':
            change_passwd_wnd = 1;
            break;
        case 'H':
            new_encryption_container = optarg;
            break;
        case '_':
            enc_passwd = optarg;
            break;
        case '+':
            enc_passwd2 = optarg;
            break;
        case 'R':
            reboot = 1;
            break;
        case 'C':
            szCopyContainer = (char *)optarg;
            break;
#ifdef UNIX
        case 'S':
            stress = 1;
            break;
#endif /* UNIX */
        case 'E':
            {
                char *arg = (char *)optarg;
                if( !strcmp( arg, "hash" ) )
                {
                    enum_param = PP_ENUM_HASHOID;
                    enum_param_text = "PP_ENUM_HASHOID";
                }
                else if( !strcmp( arg, "cipher" ) )
                {
                    enum_param = PP_ENUM_CIPHEROID;
                    enum_param_text = "PP_ENUM_CIPHEROID";
                }
                else if( !strcmp( arg, "sign" ) )
                {
                    enum_param = PP_ENUM_SIGNATUREOID;
                    enum_param_text = "PP_ENUM_SIGNATUREOID";
                }
                else if( !strcmp( arg, "dh" ) )
                {
                    enum_param = PP_ENUM_DHOID;
                    enum_param_text = "PP_ENUM_DHOID";
                }
                else
                    goto bad;
                break;
            }
        case 'P':
            {
                char *arg = (char *)optarg;
                if( !strcmp( arg, "hash" ) )
                {
                    get_param = PP_HASHOID;
                    get_param_text = "PP_HASHOID";
                }
                else if( !strcmp( arg, "cipher" ) )
                {
                    get_param = PP_CIPHEROID;
                    get_param_text = "PP_CIPHEROID";
                }
                else if( !strcmp( arg, "sign" ) )
                {
                    get_param = PP_SIGNATUREOID;
                    get_param_text = "PP_SIGNATUREOID";
                }
                else if( !strcmp( arg, "dh" ) )
                {
                    get_param = PP_DHOID;
                    get_param_text = "PP_DHOID";
                }
                else
                    goto bad;
                break;
            }
        case 'T':
            set_param = (char *)optarg;
            break;
        case '\\':
            fqcn = 1;
            break;
        case 'r':
            crc = 1;
            break;
        case '?':
        default:
            goto bad;
        }
    }
    if (c != EOF) {
        print_help = 1;
        goto bad;
    }
    if( crc )
    {
        unsigned char crc[2] = { 0, 0 };
        if( szContainer == NULL )
        {
            printf("-container must be set.\n");
            goto bad;
        }
        crc16( szContainer, crc );
        printf( "set crc=%02X%02X", (int)crc[0], (int)crc[1] );
        return 1;
    }

#ifdef UNIX
    if(stress){
      pthr_param par;

      par.func=FN_STRESS;
      par.str1=szContainer;

      return do_threaded(par);
    }
#endif /* UNIX */

#ifndef UNIX
    /*---------------------------------------------------------*/
    /* Проверим уровень использования функций криптопровайдера.*/
    if (CPlevel) {
        /* Если непосредственно используем криптопровайдер,
         * загрузим соответствующий модуль.*/
        hCSPDLL = load_CSP_library (dwProvType, NULL);
        if (! hCSPDLL)
            HandleErrorFL ("Cannot load CSP DLL.\n");
    }
#endif /* UNIX */

    if (CPlevel) {
        char *szContainerName = NULL;

        /* Для последующего использования CPAcquireContext нужно
         * определить структуру. Подробнее см. CPAcquireContext */
        vTable.Version = 1; /* min*/
        vTable.FuncVerifyImage = NULL;
        vTable.FuncReturnhWnd = NULL;

#ifdef UNIX
        MyAcquireContext=&CPAcquireContext;
        MyReleaseContext=&CPReleaseContext;
        MyGetProvParam=&CPGetProvParam;
        MySetProvParam=&CPSetProvParam;
        MyGetUserKey=&CPGetUserKey;
        MyGetKeyParam=&CPGetKeyParam;
        MySetKeyParam=&CPSetKeyParam;
        MyExportKey=&CPExportKey;
        MyImportKey=&CPImportKey;
        MyGenKey=&CPGenKey;
        MyDestroyKey=&CPDestroyKey;
        MyCreateHash=&CPCreateHash;
        MyHashData=&CPHashData;
        MySignHash=&CPSignHash;
        MyVerifySignature=&ThrVerifySignature;
        MyGetHashParam=&CPGetHashParam;
        MyDestroyHash=&CPDestroyHash;
#else /* UNIX */
        MyAcquireContext = (CPAcquireContext_t) GetProcAddress (hCSPDLL,"CPAcquireContext");
        MyReleaseContext = (CPReleaseContext_t) GetProcAddress (hCSPDLL,"CPReleaseContext");
        MyGetProvParam = (CPGetProvParam_t) GetProcAddress (hCSPDLL,"CPGetProvParam");
        MySetProvParam = (CPSetProvParam_t) GetProcAddress (hCSPDLL,"CPSetProvParam");
        MyGetUserKey = (CPGetUserKey_t) GetProcAddress (hCSPDLL,"CPGetUserKey");
        MyGetKeyParam = (CPGetKeyParam_t) GetProcAddress (hCSPDLL,"CPGetKeyParam");
        MySetKeyParam = (CPSetKeyParam_t) GetProcAddress (hCSPDLL,"CPSetKeyParam");
        MyExportKey = (CPExportKey_t) GetProcAddress (hCSPDLL,"CPExportKey");
        MyImportKey = (CPImportKey_t) GetProcAddress (hCSPDLL,"CPImportKey");
        MyGenKey = (CPGenKey_t) GetProcAddress (hCSPDLL,"CPGenKey");
        MyDestroyKey = (CPDestroyKey_t) GetProcAddress (hCSPDLL,"CPDestroyKey");
        MyCreateHash = (CPCreateHash_t) GetProcAddress (hCSPDLL,"CPCreateHash");
        MyHashData = (CPHashData_t) GetProcAddress (hCSPDLL,"CPHashData");
        MySignHash = (CPSignHash_t) GetProcAddress (hCSPDLL,"CPSignHash");
        MyVerifySignature = (CPVerifySignature_t) GetProcAddress (hCSPDLL,"CPVerifySignature");
        MyGetHashParam = (CPGetHashParam_t) GetProcAddress (hCSPDLL,"CPGetHashParam");
        MyDestroyHash = (CPDestroyHash_t) GetProcAddress (hCSPDLL,"CPDestroyHash");
#endif /* UNIX */

        if (!MyAcquireContext || !MyReleaseContext || !MyDestroyKey || !MyCreateHash || !MySignHash
            || !MyHashData || !MyVerifySignature || !MyGetProvParam || !MyImportKey || !MyExportKey
            || !MyGetKeyParam || !MyGetHashParam || !MyDestroyHash || !MySetProvParam)
            HandleErrorFL ("Cannot load CSP functions.\n");
        /* Инициализируем контекст криптопровайдера через функции CP*/
        if( szContainer && !strcmp( szContainer, "default" )
            && !( dwFlags & CRYPT_NEWKEYSET )
            && !( dwFlags & CRYPT_VERIFYCONTEXT )
            && dwProvType == PROV_GOST_DH )
            szContainerName = GetContainerName( CPlevel, &vTable,
                szProvider, dwProvType );
        bResult = MyAcquireContext (&hProv,
            szContainerName ? szContainerName : szContainer, dwFlags, &vTable);
        if( szContainerName )
            free( szContainerName );
    } else {
#ifndef UNIX
        /* Инициализируем контекст криптопровайдера через функции CryptoAPI 1.0*/
        int i;
        char *szContainerName = NULL;

        if( szContainer && !strcmp( szContainer, "default" )
            && !( dwFlags & CRYPT_NEWKEYSET )
            && !( dwFlags & CRYPT_VERIFYCONTEXT )
            && dwProvType == PROV_GOST_DH )
            szContainerName = GetContainerName( CPlevel, NULL, szProvider,
                dwProvType );
        if (counter < 0) {
            CryptAcquireContext (&hProv, szContainer, szProvider,
                dwProvType, dwFlags);
            counter = -counter;
        }
        if (!counter)
            counter = 1;
        for (i=0; i<counter; i++) {
            /* Инициализируем контекст криптопровайдера через функции CryptoAPI 1.0*/
            bResult = CryptAcquireContext (&hProv,
                szContainerName ? szContainerName : szContainer, szProvider,
                dwProvType, dwFlags);
            if (counter > 1) {
                printf (".");
                if (i%70 == 69 || i == counter - 1)
                    printf ("\n");
            }
            if (i < counter - 1 && bResult)
                CryptReleaseContext (hProv, 0);
        }
        if (counter > 1) {
            printf ("Wait for 10 sec before continue...\n");
            Sleep (1000 * 10);
            printf ("\n");
        }
        if( szContainerName )
            free( szContainerName );
#endif /* UNIX */
    }

    if (bResult) {
        printf ("CryptAcquireContext succeeded.HCRYPTPROV: %lu\n", hProv);
    } else {
        HandleErrorFL ("Error during CryptAcquireContext.\n");
        goto bad;
    }
    if (hard_rng) {
        bResult = UniSetProvParam(hProv, PP_USE_HARDWARE_RNG, NULL, 0);
        if( !bResult )
        {
            HandleErrorFL ("Error during CryptSetProvParam(PP_USE_HARDWARE_RNG).\n");
            goto bad;
        }
    }
    if (enc_passwd) {
        CRYPT_CHANGE_PIN_PARAM set_pin;

        set_pin.type = CRYPT_CHANGE_PIN_CONTAINER;
        set_pin.dest.passwd = enc_passwd;
        bResult = UniSetProvParam( hProv, PP_ENCRYPTION_CONTAINER,
            (BYTE*)&set_pin, 0 );
        if( !bResult )
        {
            HandleErrorFL ("Error during UniSetProvParam.\n");
            goto bad;
        }
    }
    if (enc_passwd2) {
        HCRYPTPROV hEncProv;
        HCRYPTPROV hEncProvValue;
        CRYPT_CHANGE_PIN_PARAM set_pin;

        DWORD len = sizeof( HCRYPTPROV );
        if (CPlevel)
            bResult = MyAcquireContext (&hEncProv, enc_passwd2,
                dwFlags & ~CRYPT_NEWKEYSET, &vTable);
#ifndef UNIX
        else
            bResult = CryptAcquireContext (&hEncProv, enc_passwd2, szProvider,
                dwProvType, dwFlags & ~CRYPT_NEWKEYSET);
#endif /* UNIX */
        if( !bResult )
        {
            HandleErrorFL ("Error during CryptAcquireContext.\n");
            goto bad;
        }
        if (password) {
            DWORD flags = 0;

            bResult = UniSetProvParam(hEncProv, PP_KEYEXCHANGE_PIN,
                (BYTE*)password, flags);
            if( !bResult )
            {
                HandleErrorFL ("Error during CryptSetProvParam(PP_KEYEXCHANGE_PIN).\n");
                goto bad;
            }
            password = NULL;
        }
        bResult = UniGetProvParam(hEncProv,PP_HCRYPTPROV,
            (BYTE*)&hEncProvValue, &len, 0 );
        if( !bResult )
        {
            UniReleaseContext( hEncProv, 0 );
            HandleErrorFL ("Error during CryptGetProvParam.\n");
            goto bad;
        }
        set_pin.type = CRYPT_CHANGE_PIN_HANDLE_CONTAINER;
        set_pin.dest.prov = hEncProvValue;
        bResult = UniSetProvParam( hProv, PP_ENCRYPTION_CONTAINER,
            (BYTE*)&set_pin, 0 );
        if( !bResult )
        {
            HandleErrorFL ("Error during UniSetProvParam.\n");
            goto bad;
        }
    }
    if (password) {
        DWORD flags = 0;

        bResult = UniSetProvParam(hProv, PP_KEYEXCHANGE_PIN,
            (BYTE*)password, flags);
        if( !bResult )
        {
            HandleErrorFL ("Error during CryptSetProvParam(PP_KEYEXCHANGE_PIN).\n");
            goto bad;
        }
    }
    if (new_password) {
        DWORD flags = 0;
        CRYPT_CHANGE_PIN_PARAM param;

        param.type = CRYPT_CHANGE_PIN_PASSWD;
        param.dest.passwd = new_password;
        bResult = UniSetProvParam(hProv, PP_CHANGE_PIN,
            (BYTE*)&param, flags);
        if( !bResult )
        {
            HandleErrorFL ("Error during CryptGetProvParam(PP_CHANGE_PIN).\n");
            goto bad;
        }
    }
    if (change_passwd_wnd) {
        DWORD flags = 0;
        CRYPT_CHANGE_PIN_PARAM param;

        param.type = CRYPT_CHANGE_PIN_WINDOW;
        bResult = UniSetProvParam(hProv, PP_CHANGE_PIN,
            (BYTE*)&param, flags);
        if( !bResult )
        {
            HandleErrorFL ("Error during CryptGetProvParam(PP_CHANGE_PIN).\n");
            goto bad;
        }
    }
    if (new_encryption_container) {
        DWORD flags = 0;
        CRYPT_CHANGE_PIN_PARAM param;

        param.type = CRYPT_CHANGE_PIN_CONTAINER;
        param.dest.passwd = new_encryption_container;
        bResult = UniSetProvParam(hProv, PP_CHANGE_PIN,
            (BYTE*)&param, flags);
        if( !bResult )
        {
            HandleErrorFL ("Error during CryptGetProvParam(PP_CHANGE_PASSWORD).\n");
            goto bad;
        }
    }
    if (enum_param) {
        char *oid;
        DWORD length = 0;
        DWORD base_flags = CRYPT_FIRST;
        char t[80];

        bResult = UniGetProvParam(hProv, enum_param, NULL,
            &length, CRYPT_FIRST);
        if( !bResult )
        {
            sprintf (t, "Error during CryptGetProvParam(%s).\n",
                enum_param_text );
            HandleErrorFL( t );
            goto bad;
        }
        oid = (char*)malloc( length );
        if( !oid )
        {
            sprintf (t, "Error during CryptGetProvParam(%s).\n",
                enum_param_text );
            HandleErrorFL( t );
            goto bad;
        }
        printf( "%s:\n", enum_param_text );
        while( UniGetProvParam( hProv, enum_param,
            (BYTE*)oid,
            &length, base_flags ) )
        {
            printf( "  %s\n", oid );
            base_flags &= ~CRYPT_FIRST;
        }
        free( oid );
    }
    if (get_param) {
        char *oid;
        DWORD length = 0;
        char t[80];
        bResult = UniGetProvParam(hProv, get_param, NULL,
            &length, 0);
        if( !bResult )
        {
            sprintf (t, "Error during CryptGetProvParam(%s).\n",
                get_param_text );
            HandleErrorFL( t );
            goto bad;
        }
        oid = (char*)malloc( length );
        if( !oid )
        {
            sprintf (t, "Error during CryptGetProvParam(%s).\n",
                get_param_text );
            HandleErrorFL( t );
            goto bad;
        }
        bResult = UniGetProvParam(hProv, get_param, (BYTE*)oid,
            &length, 0);
        if( !bResult )
        {
            free( oid );
            sprintf (t, "Error during CryptGetProvParam(%s).\n",
                get_param_text );
            HandleErrorFL( t );
            goto bad;
        }
        printf( "%s:%s\n", get_param_text, oid );
        free( oid );
    }
    if (set_param)
    {
        char t[80];
        bResult = UniSetProvParam(hProv, get_param, (BYTE*)set_param, 0 );
        if( !bResult )
        {
            sprintf (t, "Error during CryptSetProvParam(%s,%s).\n",
                get_param_text, set_param );
            HandleErrorFL( t );
            goto bad;
        }
        printf( "%s:%s\n", get_param_text, set_param );
    }
    if (enum_containers) {
        DWORD length = 0;
        char *container_name;

        DWORD base_flags =
            dwFlags & CRYPT_MACHINE_KEYSET ? CRYPT_MACHINE_KEYSET : 0;
        base_flags |= CRYPT_FIRST;
        if( unique )
            base_flags |= CRYPT_UNIQUE;
        if( fqcn )
            base_flags |= CRYPT_FQCN;

        bResult = UniGetProvParam(hProv, PP_ENUMCONTAINERS, NULL,
            &length, base_flags);
        container_name = (char*)malloc( length );
        if( !container_name )
        {
            HandleErrorFL ("Error during CryptGetProvParam(PP_ENUMCONTAINERS).\n");
            goto bad;
        }
        while( UniGetProvParam( hProv, PP_ENUMCONTAINERS,
            (BYTE*)container_name,
            &length, base_flags ) )
        {
            if( base_flags & CRYPT_UNIQUE )
            {
                if( strlen( container_name ) > 38
                    || strlen( container_name + strlen( container_name ) + 1 )
                    > 38 )
                {
                    printf( "%38s|\n%76s\n", container_name,
                        container_name + strlen( container_name ) + 1 );
                }
                else
                    printf( "%38s|%38s\n", container_name,
                        container_name + strlen( container_name ) + 1 );
            }
            else
                printf( "%s\n", container_name );
            base_flags &= ~CRYPT_FIRST;
        }
        free( container_name );
        if( GetLastError() != ERROR_NO_MORE_ITEMS )
        {
            UniReleaseContext (hProv, 0);
            HandleErrorFL ("Error during GetProvParam.\n");
            goto bad;
        }
        printf( "OK.\n" );
        ret = 1;
        bResult = UniReleaseContext (hProv, 0);
        if (!bResult) {
            HandleErrorFL ("Error during CryptReleaseContext.\n");
            goto bad;
        }
        if( reboot )
            cpcsp_reboot( hCSPDLL );
#ifndef UNIX
        if( hCSPDLL ) FreeLibrary( hCSPDLL );
#endif /* UNIX */
        return ret;
    }

    /* Если был установлен флаг удаления ключевого контейнера, выводим сообщение.*/
    if (dwFlags & CRYPT_DELETEKEYSET) {
        printf ("Container %s deleted.\n",
            szContainer ? szContainer : "(default)");
        ret = 1;
        goto bad;
    }
    /*-----------------------------------------------------------------------------*/
    /* Определим полное имя провайдера*/
    dwParam = PP_NAME;
    dwProvNameLen = sizeof (pbProvName);

    bResult = UniGetProvParam (hProv, dwParam, pbProvName, &dwProvNameLen, 0);
    if (bResult) {
        printf ("CryptGetProvParam succeeded.\n");
        printf ("Provider name: %s\n", pbProvName);
    } else {
        HandleErrorFL ("Error reading CSP name.\n");
        goto bad;
    }

    /*-----------------------------------------------------------------------------*/
    /* Определим имя ключевого контейнера*/
    dwProvContainerLen = sizeof (pbProvContainer);
    if( unique )
        dwParam = PP_UNIQUE_CONTAINER;
    else
        dwParam = PP_CONTAINER;
    bResult = UniGetProvParam (hProv, dwParam, pbProvContainer, &dwProvContainerLen, 0);
    if (bResult) {
        printf ("A crypto context has been acquired and \n");
        printf ("The name on the key container is \"%s\"\n\n", pbProvContainer);
    } else {
        HandleErrorFL("A context was acquired or created, but an error occurred getting the key container name.\n");
        goto bad;
    }

    /*-----------------------------------------------------------------------------*/
    /* Определим наличие ключа ЭЦП*/
    if( !hash && (keyType & AT_SIGNATURE) && !(dwFlags & CRYPT_VERIFYCONTEXT) )
    {
        bResult = UniGetUserKey (hProv, AT_SIGNATURE, &hKeyS);
        if (bResult) {
            printf ("A signature key is available. HCRYPTKEY: %lu\n", hKeyS);
        }
        else {
            printf ("No signature key is available.\n");
            /*-----------------------------------------------------------------------------*/
            /* Если ключа ЭЦП нет, создадим*/
            if (GetLastError () == NTE_NO_KEY) {
                printf ("The signature key does not exist.\n");
                printf ("Create a signature key pair.\n");

                Algid = AT_SIGNATURE;
                bResult = UniGenKey (hProv, Algid, key_length << 16
                    | ( exported ? CRYPT_EXPORTABLE : 0 ), &hKeyS);
                if (bResult)
                    printf ("Created a signature key pair.\n");
                else {
                    HandleErrorFL ("Error occurred creating a signature key.\n");
                    goto bad;
                }
            } else {
                HandleErrorFL ("An error other than NTE_NO_KEY getting signature key.\n");
                goto bad;
            }
            printf ("A signature key was created.\n");
        }
    }

    /*-----------------------------------------------------------------------------*/
    /* Определим наличие ключа обмена*/
    if( !hash && (keyType & AT_KEYEXCHANGE) && !(dwFlags & CRYPT_VERIFYCONTEXT) )
    {
        bResult = UniGetUserKey (hProv, AT_KEYEXCHANGE, &hKeyE);
        if (bResult)
            printf ("\nAn exchange key exists. HCRYPTKEY: %lu\n", hKeyE);
        else {
            printf ("\nNo exchange key is available.\n");
            /*-----------------------------------------------------------------------------*/
            /* Если ключа обмена нет, создадим*/
            if (GetLastError () == NTE_NO_KEY) {
                printf ("The exchange key does not exist.\n");
                printf ("Attempting to create an exchange key pair.\n");

                Algid = AT_KEYEXCHANGE;

                bResult = UniGenKey (hProv, Algid, key_length << 16
                    | ( exported ? CRYPT_EXPORTABLE : 0 ), &hKeyE);
                if (bResult)
                    printf ("Exchange key pair created.\n");
                else {
                    HandleErrorFL ("Error occurred attempting to create an exchange key.\n");
                    goto bad;
                }
            } else {
                HandleErrorFL ("An error other than NTE_NO_KEY occurred.\n");
                goto bad;
            }
            printf ("An exchange key pair existed, or one was created.\n\n");
        }
    }

    /*-----------------------------------------------------------------------------*/
    /* Вызовем функцию, если задана опция отображения полной информации о провайдере.*/
    if (show) bResult = show_info (hProv, hKeyS, hKeyE);

    /*-----------------------------------------------------------------------------*/
    /* Дополнительные тесты на экспорт импорт ключа и */
    /* подпись/проверку подписи на них*/
    /*-----------------------------------------------------------------------------*/

    /*-----------------------------------------------------------------------------*/
    /* Экспорт открытого ключа заданного типа в файл, заданный переменной exportfilename*/
    if (exportfilename) {
        DWORD key_len = 0;
        BYTE *out_key = NULL;
        PUBLICKEYSTRUC str;
        /*-----------------------------------------------------------------------------*/
        /* Экспорт ключа ЭЦП*/
        if (keyType == AT_SIGNATURE) {
            ret = UniExportKey(hProv, hKeyS,0,PUBLICKEYBLOB,0,NULL,&key_len);

            if (!ret)
                HandleErrorFL ("Error occurred when exporting key.\n");
            out_key = (BYTE*) malloc(key_len);
            if (!out_key)
                HandleErrorFL ("Error occurred when exporting key.\n");
            ret = UniExportKey(hProv, hKeyS,0,PUBLICKEYBLOB,0,out_key,&key_len);
            if (!ret)
                HandleErrorFL ("Error occurred when exporting key.\n");
            ret = write_file (exportfilename, key_len, out_key);
            memcpy (&str, out_key, sizeof (PUBLICKEYSTRUC));
            free (out_key);
            if (ret) {
                printf ("Public key ALG_ID: %u %s was exported into file %s\n", str.aiKeyAlg, "AT_SIGNATURE", exportfilename);
            }
        }
        /*-----------------------------------------------------------------------------*/
        /* Экспорт ключа обмена*/
        else if (keyType == AT_KEYEXCHANGE) {
            ret = UniExportKey (hProv, hKeyE,0,PUBLICKEYBLOB,0,NULL,&key_len);
            if (!ret)
                HandleErrorFL ("Error occurred when exporting key.\n");
            out_key = (BYTE*) malloc(key_len);
            if (!out_key)
                HandleErrorFL ("Error occurred when exporting key.\n");
            ret = UniExportKey (hProv, hKeyE,0,PUBLICKEYBLOB,0,out_key,&key_len);
            if (!ret)
                HandleErrorFL ("Error occurred when exporting key.\n");
            ret = write_file (exportfilename, key_len, out_key);
            memcpy (&str, out_key, sizeof (PUBLICKEYSTRUC));
            free (out_key);
            if (ret)
                printf ("Public key ALG_ID: %u %s was exported into file %s\n\n", str.aiKeyAlg, "AT_KEYEXCHANGE", exportfilename);
        }
        else
            HandleErrorFL ("No keytype specified.\n" );
    }

    /*-----------------------------------------------------------------------------*/
    /* Импорт открытого ключа из файла.*/
    if (importfilename) {
        PUBLICKEYSTRUC str;
#ifndef UNIX
        PCCRYPT_OID_INFO info = NULL;
#endif /* UNIX */
        BYTE * in_key = NULL;
        BYTE tmp[1024];
        size_t key_len = 0;
        DWORD tmp_par;
        HCRYPTKEY hPubKey = 0;

        /*-----------------------------------------------------------------------------*/
        /* При выполнении импорта может быть использован дополнительных ключ*/
        /* для алгоритма Diffi-Helmana.*/
        /* Если это специфигированно флагом -pubkey filename, предварительно прочитаем ключ в hPubKey*/
        if (pubkeyfilename) {
            ret = get_file_data_pointer (pubkeyfilename, &key_len, &in_key);
            if (!ret)
                HandleErrorFL ("Error occurred when importing key.\n");
            /*-----------------------------------------------------------------------------*/
            /* Выполним импорт дополнительного ключа*/
            ret = UniImportKey (hProv,in_key,(DWORD) key_len,0,0,&hPubKey);
            if (!ret)
                HandleErrorFL ("Error occurred when importing key.\n");
            /*-----------------------------------------------------------------------------*/
            /* Отобразим идентификатор алгоритма ключа*/
            memcpy (&str, in_key, sizeof (PUBLICKEYSTRUC));
            printf ("Public key ALG_ID: %u was imported from file %s\n", str.aiKeyAlg, pubkeyfilename);
            release_file_data_pointer (in_key);
            in_key = NULL;
        }

        /*-----------------------------------------------------------------------------*/
        /* Если при выполнении функции импорта в опциях задан флаг использования ключа обмена */
        /* -keytype exchange, и ранне прочитали открытый ключ, */
        /* импорт будет использовать ранее считанный ключ*/
        if (! hPubKey && keyType == AT_KEYEXCHANGE)
            hPubKey = hKeyE;
        key_len = 0;
        ret = get_file_data_pointer (importfilename, &key_len, &in_key);
        if (!ret)
            HandleErrorFL ("Error occurred when importing key.\n");
        /*-----------------------------------------------------------------------------*/
        /* Выполним импорт ключа с использование ранее считанного*/
        ret = UniImportKey (hProv,in_key,(DWORD) key_len,hPubKey,0,&hImportedKey);
        if (!ret)
            HandleErrorFL ("Error occurred when exporting key.\n");
        /*-----------------------------------------------------------------------------*/
        /* Отобразим идентификатор алгоритма ключа в блобе*/
        memcpy (&str, in_key, sizeof (PUBLICKEYSTRUC));
        release_file_data_pointer (in_key);
        printf ("Public key ALG_ID: %u was imported from file %s\n", str.aiKeyAlg, importfilename);

        /*-----------------------------------------------------------------------------*/
        /* Отобразим идентификатор алгоритма ключа после преобразования*/
        if (!CPlevel) {
#ifndef UNIX
            info = CryptFindOIDInfo(CRYPT_OID_INFO_ALGID_KEY, (void*) &str.aiKeyAlg, 0);
            if (info) {
                wprintf (L"OID : %S  Name : %s\n", info->pszOID, info->pwszName);
            }
#endif /* UNIX */
        }
        tmp_par=(DWORD)key_len; /* 32/64 bit problem; size_t is 8 bytes */
        ret = UniGetKeyParam (hProv,hImportedKey,KP_ALGID,tmp,&tmp_par,0);
        key_len=tmp_par;
        if (!ret)
            HandleErrorFL ("Error occurred when importing key.\n");
        printf ("Imported Key ALG_ID: %u(%x) \n\n", *(ALG_ID*) tmp, *(ALG_ID*) tmp);

        printf ("\n");
    }

    /*-----------------------------------------------------------------------------*/
    /* Прочитаем файл, используемый как входные данные*/
    if (infilename) {
        ret = get_file_data_pointer (infilename, &in_data_len, &in_data);
        if (!ret)
            HandleErrorFL ("Error occurred when reading infilename.\n");
    }

    /*-----------------------------------------------------------------------------*/
    /* Вычислим значение хэша входных данных по алгоритму, */
    /* специфицированному переменной hash_alg*/
    if (hash) {
        BYTE hash_val[64];
        DWORD hash_len = 64;
        DWORD len = sizeof (DWORD);

        if (infilename == NULL)
            HandleErrorFL ("No data to be hashed\n");

        /*-----------------------------------------------------------------------------*/
        /* Создание дескриптора хэша*/
        if (CPlevel)
            ret = MyCreateHash(hProv, hash_alg, 0, 0, &hHash);
        else{
#ifndef UNIX
            ret = CryptCreateHash(hProv, hash_alg, 0, 0, &hHash);
#endif /* UNIX */
        }
        if (!ret)
            HandleErrorFL("Error during CryptCreateHash.");

        /*-----------------------------------------------------------------------------*/
        /* Хэширование данных*/
        if (CPlevel)
            ret = MyHashData(hProv, hHash, in_data, in_data_len, 0);
        else{
#ifndef UNIX
            ret = CryptHashData(hHash, in_data, in_data_len, 0);
#endif /* UNIX */
        }
        if (!ret)
            HandleErrorFL("Error during CryptHashData.");

        printf("Hash object created with alg: %s %X\n", ptr_hash_alg, hash_alg);

        /*-----------------------------------------------------------------------------*/
        /* Определение требуемого размера памяти для возврата значения хэша*/
        /* и вернем значение*/
        if (CPlevel) {
            ret = MyGetHashParam(hProv, hHash, HP_HASHSIZE, (BYTE*)&hash_len, &len, 0);
            if (!ret)
                HandleErrorFL("Error during CryptGetHashParam.");

            ret = MyGetHashParam(hProv, hHash, HP_HASHVAL, hash_val, &hash_len, 0);
            MyDestroyHash (hProv, hHash);
        }
        else {
#ifndef UNIX
            ret = CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&hash_len, &len, 0);
            if (!ret)
                HandleErrorFL("Error during CryptGetHashParam.");

            ret = CryptGetHashParam(hHash, HP_HASHVAL, hash_val, &hash_len, 0);
            CryptDestroyHash (hHash);
#endif /* UNIX */
        }
        if (!ret)
            HandleErrorFL("Error during CryptGetHashParam.");

        /*-----------------------------------------------------------------------------*/
        /* Если задано, сохраним значение хэша в файле*/
        if (ret && hashfile) {
            write_file (hashfile, hash_len, hash_val);
            printf ("Hash value (%d bytes) saved file %s\n", hash_len, hashfile);
        }
    }
    /*-----------------------------------------------------------------------------*/
    /* Формирование и проверка ЭЦП */
    if (sign || verify) {
        if (infilename == NULL)
            HandleErrorFL ("No data to be signed\n");

        /*-----------------------------------------------------------------------------*/
        /* Создадим дескриптор хеша*/
        if (CPlevel)
            ret = MyCreateHash(hProv, my_alg, 0, 0, &hHash);
        else{
#ifndef UNIX
            ret = CryptCreateHash(hProv, my_alg, 0, 0, &hHash);
#endif /* UNIX */
        }

        if (ret) {
            printf("Hash object created with alg: %s %X\n", my_hash_alg, my_alg);
        }
        else
        {
            HandleErrorFL("Error during CryptCreateHash.");
        }
        /*-----------------------------------------------------------------------------*/
        /* Вычислим значение хэша*/
        if (CPlevel)
            ret = MyHashData(hProv, hHash, in_data, in_data_len, 0);
        else{
#ifndef UNIX
            ret = CryptHashData(hHash, in_data, in_data_len, 0);
#endif /* UNIX */
        }
        if (ret)
            printf("The data buffer has been hashed.\n");
        else
            HandleErrorFL("Error during CryptHashData.");
    }
    release_file_data_pointer (in_data);
    /*-----------------------------------------------------------------------------*/
    /* Формирование ЭЦП*/
    if (sign) {
        DWORD dwSigLen= 0;
        BYTE *pbSignature = NULL;
        int kt;

        if (!hHash)
            HandleErrorFL("No HASH");
        /*-----------------------------------------------------------------------------*/
        /* Определим тип ключа, используемый для формирования ЭЦП*/
        hSignatureKey = (keyType == AT_SIGNATURE) ? hKeyS : hKeyE;
        kt = (keyType == AT_SIGNATURE) ? keyType : AT_KEYEXCHANGE;
        /* Определим размер памяти, требуемый для значения ЭЦП*/
        ret=UniSignHash(hProv,hHash,kt,NULL,0,NULL,&dwSigLen);
        if (ret)
            printf("Signature length %d found.\n",dwSigLen);
        else
            HandleErrorFL("Error during CryptSignHash.");
        /* Резервируем память*/
        pbSignature = (BYTE *)malloc(dwSigLen);
        if (!pbSignature)
            HandleErrorFL("Out of memory.");
        /*-----------------------------------------------------------------------------*/
        /* Подпишем значение хеша*/

        ret = UniSignHash(hProv, hHash, kt,NULL, 0, pbSignature, &dwSigLen);
        if (ret) {
            printf("Signature was done.\n");
            if (outfilename) {
                write_file (outfilename, dwSigLen, pbSignature);
                printf ("Signature was saved into file %s\n", outfilename);
            }
        }
        else
            HandleErrorFL("Error during CryptSignHash.");
        printf ("\n");
    }

    /*-----------------------------------------------------------------------------*/
    /* Проверка ЭЦП. Проводится только на ключе импорта, прочитанного из файла.*/
    if (verify) {
        BYTE *signature = NULL;
        size_t signature_len = 0;

        if (!hHash)
            HandleErrorFL("No HASH");
        if (! hImportedKey)
            HandleErrorFL("No Imported Key");
        if (! signaturefilename)
            HandleErrorFL("No signature file was specified");
        ret = get_file_data_pointer (signaturefilename, &signature_len, &signature);
        if (! ret)
            HandleErrorFL("Cannot read signature file");

        /*-----------------------------------------------------------------------------*/
        /* Проверка ЭЦП. */
        ret = UniVerifySignature (hProv, hHash,signature,(DWORD)signature_len,hImportedKey,NULL,0);
        if (ret)
            printf ("Signature was verified OK\n");
        else
            HandleErrorFL("Bad Signature");
        release_file_data_pointer (signature);
        printf ("\n");
    }

    if( !hash && szCopyContainer && !(dwFlags & CRYPT_VERIFYCONTEXT) )
    {
        HCRYPTPROV hDestProv = 0;
        if (CPlevel)
            bResult = MyAcquireContext (&hDestProv, szCopyContainer,
            dwFlags | CRYPT_NEWKEYSET, &vTable );
#ifndef UNIX
        else
            bResult = CryptAcquireContext (&hDestProv, szCopyContainer, szProvider,
                dwProvType, dwFlags | CRYPT_NEWKEYSET );
#endif /* UNIX */
        if (bResult) {
            printf ("CryptAcquireContext succeeded.HCRYPTPROV: %lu\n", hProv);
        } else {
            HandleErrorFL ("Error during CryptAcquireContext.\n");
            goto bad;
        }
        bResult = CopyContainerParam( hProv, hDestProv );
        if (!bResult)
            goto bad;
        if( keyType & AT_KEYEXCHANGE )
        {
            bResult = CopyPrivateKey( hProv, hDestProv, hKeyE );
            if (!bResult)
                goto bad;
        }
        if( keyType & AT_SIGNATURE )
        {
            bResult = CopyPrivateKey( hProv, hDestProv, hKeyS );
            if (!bResult)
                goto bad;
        }
    }
    /*-----------------------------------------------------------------------------*/
    /* Очистка памяти и удаление дескрипторов. */
    if( !hash && (keyType & AT_SIGNATURE) && !(dwFlags & CRYPT_VERIFYCONTEXT) )
    {
        bResult = UniDestroyKey (hProv, hKeyS);
        if (!bResult) {
            HandleErrorFL ("Error during CryptDestroyKey.\n");
            goto bad;
        }
    }
    if( !hash && (keyType & AT_KEYEXCHANGE) && !(dwFlags & CRYPT_VERIFYCONTEXT) )
    {
        bResult = UniDestroyKey (hProv, hKeyE);
        if (!bResult) {
            HandleErrorFL ("Error during CryptDestroyKey.\n");
            goto bad;
        }
    }

    bResult = UniReleaseContext (hProv, 0);
    if (!bResult) {
        HandleErrorFL ("Error during CryptReleaseContext.\n");
        goto bad;
    }
    if( reboot )
        cpcsp_reboot( hCSPDLL );
    hProv = 0;
    printf ("Everything is OK.\nA ");
    if( !hash && !(dwFlags & CRYPT_VERIFYCONTEXT) )
    {
        if( keyType & AT_SIGNATURE )
            printf ("signature key pair ");
        if( (keyType & AT_SIGNATURE) && (keyType & AT_KEYEXCHANGE) )
            printf ("and ");
        if( keyType & AT_KEYEXCHANGE )
            printf ("an exchange key");
        if( keyType == 0 )
            printf ("No keys" );
        printf ("\nexist in the \"%s\" key container.\n", pbProvContainer);
    }
    ret = 1;
bad:

    if (print_help) {
        printf ("%s -keyset [options]\n", prog);
        printf (OFFICIAL_PROGRAM_NAME " key set manipulation options:\n");
        printf ("  -cplevel              load CSP dll and use CP functions instead Crypt\n");
        printf ("  -provider name        specify provider name or next abbriviation:\n");
        printf ("                       ");
        printf ("   cpDef\n");
        printf ("                       ");
        printf ("   msDef ");
        printf ("msEnhanced ");
#ifdef MS_STRONG_PROV
        printf ("msStrong ");
#endif /* MS_STRONG_PROV */
        printf ("\n                       ");
        printf ("   msDefRsaSig ");
        printf ("msDefRsaSchannel ");
#ifdef MS_ENHANCED_RSA_SCHANNEL_PROV
        printf ("msEnhancedRsaSchannel ");
#endif /* MS_ENHANCED_RSA_SCHANNEL_PROV */
        printf ("msDefDss ");
        printf ("\n                       ");
        printf ("   msDefDssDh ");
#ifdef MS_ENH_DSS_DH_PROV
        printf ("msEnhDssDh ");
#endif /* MS_ENH_DSS_DH_PROV */
#ifdef MS_DEF_DH_SCHANNEL_PROV
        printf ("msDefDhSchannel ");
#endif /* MS_DEF_DH_SCHANNEL_PROV */
#ifdef MS_SCARD_PROV
        printf ("msScard ");
#endif /* MS_SCARD_PROV */
        printf ("\n");
        printf ("  -provtype type        specify provider type or next abbriviation:\n");
        printf ("                       ");
        printf ("   CProCSP\n");
        printf ("                       ");
        printf ("   RsaFull ");
        printf ("RsaSig ");
        printf ("Dss ");
        printf ("Fortezza ");
        printf ("MsExchange ");
        printf ("Ssl ");
        printf ("\n                       ");
        printf ("   RsaSchannel ");
        printf ("DssDh ");
        printf ("EcEcdsaSig ");
        printf ("EcEcnraSig ");
        printf ("EcEcdsaFull ");
        printf ("\n                       ");
        printf ("   EcEcnraFull ");
#ifdef PROV_DH_SCHANNEL
        printf ("DhSchannel ");
#endif /* PROV_DH_SCHANNEL */
        printf ("SpyrusLynks ");
#ifdef PROV_RNG
        printf ("Rng ");
#endif /* PROV_RNG */
#ifdef PROV_INTEL_SEC
        printf ("IntelSec ");
#endif /* PROV_INTEL_SEC */
        printf ("\n");
        printf ("  -container name       specify container name\n");
        printf ("  -verifycontext        open context for verification only\n");
        printf ("  -newkeyset            create new key set\n");
        printf ("  -machinekeyset        open HKLM\n");
        printf ("  -deletekeyset         delete key set\n");
        printf ("  -exported             generated key need to be exported\n");
        printf ("  -info                 show provider's info\n");
        printf ("  -keytype type         public key type to be used for signing or exporting\n");
        printf ("                        (signature, exchange,none)\n");
        printf ("  -export filename      filename contained public keytype key\n");
        printf ("  -import filename      filename contained public key, if keytype EQ exchange,\n");
        printf ("                        user exchange secret key will be used with import as\n");
        printf ("                        hPubKey\n");
        printf ("  -hash hashalg         hash in file data with hash (SHA1, MD5, MD2,\n");
        printf ("                        GOST - default)\n");
        printf ("  -hashout filename     out hash value into filename\n");
        printf ("  -sign hashalg         sign in file with keyType and hash (SHA1, MD5, MD2,\n");
        printf ("                        GOST - default)\n");
        printf ("  -verify hashalg       verify in file with signature file on imported key\n");
        printf ("                        with hash (SHA1, MD5, MD2, GOST - default)\n");
        printf ("  -in filename          data filename to be signed or verified\n");
        printf ("  -out filename         save signature in file\n");
        printf ("  -signature filename   in/out signature file name\n");
        printf ("  -pubkey filename      additional public key to be used with CpImportKey\n");
        printf ("                        function as hPubKey, if public key not specified and\n");
        printf ("                        keytype EQ exchange user secret key wiil be used as\n");
        printf ("                        hPubKey\n");
        printf ("  -alg ALG_ID           obtain alghorithm info by alg_id\n");
        printf ("  -enum_containers      enumerate containers\n");
        printf ("  -unique               output unique container name instead name\n");
#ifdef UNIX
        printf ("  -stress               CP{Acquire/Relase}Context\n");
#endif /* UNIX */
        printf ("  -passwd password      use password on container\n");
        printf ("  -chpasswd password    change password on container\n");
        printf ("  -qchpasswd            windowing change password on container\n");
        printf ("  -enchpasswd container change password to encryption container\n" );
        printf ("  -enc_passwd container set encryption container\n" );
        printf ("  -hard_rng             use hardware RNG\n");

#if(_WIN32_WINNT >= 0x0500)
        printf ("  -silent               do not display any user interface\n");
#endif /*(_WIN32_WINNT >= 0x0500)*/
        printf ("  -length keylength     set key length to 1024 / 512 bits\n" );
        printf ("  -enum_param type      enumerate algothm's parameters hash/cipher/dh/sign\n" );
        printf ("  -set_param type       set default algothm's parameters hash/cipher/dh/sign\n" );
        printf ("  -get_param type       get default algothm's parameters hash/cipher/dh/sign\n" );
        printf ("  -help                 print this help\n");
    }
#ifndef UNIX
    if( hCSPDLL ) FreeLibrary( hCSPDLL );
#endif /* UNIX */

    return ret;
}

/*----------------------------------------------------------------------*/
/* Функия вывода информации по алгоритмам, реализуемым криптопровайдером*/
int show_info (HCRYPTPROV hProv, HCRYPTKEY hKeyS, HCRYPTKEY hKeyE)
{
    int ret = 0;
    PROV_ENUMALGS_EX *pbData = NULL;
    DWORD pdwDataLen = 1000;
    CHAR *pszAlgType = NULL;
    BYTE *dataS = NULL;
    DWORD dlS;
    BYTE *dataE = NULL;
    DWORD dlE;

    if (! hProv ) goto err;

    pbData = (PROV_ENUMALGS_EX*) malloc (1000);

    UniGetProvParam (hProv, PP_ENUMALGS_EX, (BYTE*)pbData, &pdwDataLen, CRYPT_FIRST);
    do {
      switch(GET_ALG_CLASS(pbData->aiAlgid)) {
      case ALG_CLASS_DATA_ENCRYPT: pszAlgType = "Encrypt  ";    break;
      case ALG_CLASS_HASH:       pszAlgType = "Hash     ";      break;
      case ALG_CLASS_KEY_EXCHANGE: pszAlgType = "Exchange ";    break;
      case ALG_CLASS_SIGNATURE:  pszAlgType = "Signature";      break;
      default:                   pszAlgType = "Unknown  ";
      }

      printf("\n\nName:%-14s Type:%s  DefaultLen:%-4d MinLen:%-4d \nMaxLen:%-4d Prot:%-4d Name:'%s'(%d) Long:'%s'(%d) Algid:%8.8lu\n",
             pbData->szLongName, pszAlgType,
             pbData->dwDefaultLen,
             pbData->dwMinLen,
             pbData->dwMaxLen,
             pbData->dwProtocols,
             pbData->szName,
             pbData->dwNameLen,
             pbData->szLongName,
             pbData->dwLongNameLen,
             pbData->aiAlgid);

    } while (UniGetProvParam(hProv, PP_ENUMALGS_EX, (BYTE*)pbData, &pdwDataLen, 0));

    printf ("\n");

#ifndef UNIX
    /*----------------------------------------------------------------------*/
    /* Определение длин констант (ключей) для ключей ЭЦП и обмена*/
    if (hKeyS) {
        /* ============== P*/
        if (CryptGetKeyParam(hKeyS, KP_P, NULL, &dlS, 0)) {
            dataS = (BYTE*) malloc (dlS);
            printf ("Signature P Len  : %d %d\n", dlS, dlS*8);
            CryptGetKeyParam(hKeyS, KP_P, dataS, &dlS, 0);
        }

        /* ============== Q*/
        if (CryptGetKeyParam(hKeyS, KP_Q, NULL, &dlS, 0)) {
            dataS = (BYTE*) malloc (dlS);
            printf ("Signature Q Len  : %d %d\n", dlS, dlS*8);
            CryptGetKeyParam(hKeyS, KP_Q, dataS, &dlS, 0);
        }

        /* ============== G*/
        if (CryptGetKeyParam(hKeyS, KP_G, NULL, &dlS, 0)) {
            dataS = (BYTE*) malloc (dlS);
            printf ("Signature G Len  : %d %d\n", dlS, dlS*8);
            CryptGetKeyParam(hKeyS, KP_G, dataS, &dlS, 0);
        }
    }
    if (hKeyE) {
        /* ============== P*/
        if (CryptGetKeyParam(hKeyE, KP_P, NULL, &dlE, 0)) {
            dataE = (BYTE*) malloc (dlE);
            printf ("DH Exchange P Len: %d %d\n", dlE, dlE*8);
            CryptGetKeyParam(hKeyE, KP_P, dataE, &dlE, 0);
        }

        /* ============== Q*/
        if (CryptGetKeyParam(hKeyE, KP_Q, NULL, &dlE, 0)) {
            dataE = (BYTE*) malloc (dlE);
            printf ("DH Exchange Q Len: %d %d\n", dlE, dlE*8);
            CryptGetKeyParam(hKeyE, KP_Q, dataE, &dlE, 0);
        }

        /* ============== G*/
        if (CryptGetKeyParam(hKeyE, KP_G, NULL, &dlE, 0)) {
            dataE = (BYTE*) malloc (dlE);
            printf ("DH Exchange G Len: %d %d\n", dlE, dlE*8);
            CryptGetKeyParam(hKeyE, KP_G, dataE, &dlE, 0);
        }
        printf ("\n");
    }
#endif /* UNIX */

err:
    if( pbData )
        free( pbData );
    return ret;
}

/*--------------------------------------------------------------------*/
/* Функция загрузки криптопровайдера по заданному типу*/
#if !defined(UNIX)
HANDLE
#else
void *
#endif /* !defined(UNIX) */
load_CSP_library (DWORD dwProvType, const char *szDllName) {

#if !defined(UNIX)
    char CSPDLLName [1024];
    HKEY hKey = NULL;

    if (NULL != szDllName) {
        strncpy(CSPDLLName, szDllName, sizeof(CSPDLLName));
        CSPDLLName[sizeof(CSPDLLName)-1] = '\0';
    } else {
            /* Определяем имя DLL по типу CSP */
        char CSPName [1024];
        DWORD dwDataSize;
        char type[1024];
        char   num[32];

            /* Все криптопровайдеры зарегистрированы по следующему ключу registry*/
#       define PROVIDER_REGKEY_FULLPATH_A "SOFTWARE\\Microsoft\\Cryptography\\Defaults"

        strcpy (type, (const char*) PROVIDER_REGKEY_FULLPATH_A);
        strcat (type, "\\Provider Types");
        sprintf (num, "\\Type %03d", dwProvType);
        strcat (type, num);

        if (ERROR_SUCCESS != RegOpenKeyEx (
            HKEY_LOCAL_MACHINE,
            type,
            0,
            KEY_QUERY_VALUE,
            &hKey)) {
            goto ReleaseResource;
        }
        dwDataSize = sizeof(CSPName);
        if (ERROR_SUCCESS != RegQueryValueEx (
            hKey,
            "Name",
            NULL,
            NULL,
            (LPBYTE)CSPName,
            &dwDataSize)) {
            goto ReleaseResource;
        }
        if (hKey) {
            RegCloseKey(hKey);
        }
        /* Определим имя DLL, для провайдера соответствующего типа*/
        strcpy (type, (const char*) PROVIDER_REGKEY_FULLPATH_A);
        strcat (type, "\\Provider\\");
        strcat (type, CSPName);

        if (ERROR_SUCCESS != RegOpenKeyEx (
            HKEY_LOCAL_MACHINE,
            type,
            0,
            KEY_QUERY_VALUE,
            &hKey)) {
            goto ReleaseResource;
        }
        dwDataSize = sizeof(CSPName);
        if (ERROR_SUCCESS != RegQueryValueEx (
            hKey,
            "Image Path",
            NULL,
            NULL,
            (LPBYTE)CSPDLLName,
            &dwDataSize)) {
            goto ReleaseResource;
        }
        if (hKey) {
            RegCloseKey(hKey);
        }
    }
    /* Загрузим DLL*/
    return (LoadLibrary(CSPDLLName));

ReleaseResource:
    if (hKey) RegCloseKey(hKey);

    return 0;   /* Ошибка */
#else

    if (PROV_GOST_94_DH != dwProvType) {
        /* ???? I think about PROV_GOST_2001_DH ???? */
        return 0;
    }

    return dlopen(szDllName, RTLD_LAZY);
#endif /* !defined(UNIX) */
}

static BOOL CopyKeyParam( HCRYPTPROV hSrcProv, HCRYPTPROV hDestProv,
    DWORD param, HCRYPTKEY hSrcKey, HCRYPTKEY hDestKey )
{
    DWORD dwBlobLen = 0;
    BYTE *pbKeyBlob = NULL;
    const char *err_fun = NULL;
#if defined( BOURGEOIS )
    CRYPT_DATA_BLOB Blob;
    BYTE *CopyKeyParamBlob = (BYTE*)&Blob;
#else /* defined( BOURGEOIS ) */
#define CopyKeyParamBlob pbKeyBlob
#endif /* defined( BOURGEOIS ) */

        /* -- передача параметра G из исходного контейнера; */
    if( !UniGetKeyParam( hSrcProv, hSrcKey, param,
        NULL, &dwBlobLen, 0 ) )
    {
        err_fun = "CryptGetKeyParam";
        goto err;
    }
    pbKeyBlob = (BYTE*)malloc( dwBlobLen );
    if( !pbKeyBlob )
    {
        err_fun = "malloc";
        goto err;
    }
    if( !UniGetKeyParam( hSrcProv, hSrcKey, param,
        pbKeyBlob, &dwBlobLen, 0 ) )
    {
        err_fun = "CryptGetKeyParam";
        goto err;
    }
#if defined( BOURGEOIS )
    Blob.cbData = dwBlobLen;
    Blob.pbData = pbKeyBlob;
#endif /* defined( BOURGEOIS ) */
    if( !UniSetKeyParam( hDestProv, hDestKey, param,
        CopyKeyParamBlob, 0 ) )
    {
        err_fun = "CryptSetKeyParam";
        goto err;
    }
err:
    if( pbKeyBlob )
        free( pbKeyBlob );
    if( err_fun )
    {
        printf( "%s fail. LastError:0x%x\n", err_fun, GetLastError() );
        return FALSE;
    }
    return TRUE;
}
#if !defined( BOURGEOIS )
#undef CopyKeyParamBlob
#endif /* !defined( BOURGEOIS ) */

static BOOL CopyPrivateKey( HCRYPTPROV hSrcProv, HCRYPTPROV hDestProv,
    HCRYPTKEY hSrcKey )
{
    HCRYPTKEY hDestEphemKey = 0;
    HCRYPTKEY hSrcEphemKey = 0;
    HCRYPTKEY hDestAgreeKey = 0;
    HCRYPTKEY hSrcAgreeKey = 0;
    HCRYPTKEY hDestKey = 0;
    DWORD dwBlobLen = 0;
    BYTE *pbKeyBlob = NULL;
    const char *err_fun = NULL;
#if defined( BOURGEOIS )
    DWORD algid_export = CYLINK_MEK;
    DWORD nsigned algid_ephem = CALG_DH_EPHEM;
    DWORD kp1 = KP_G;
    DWORD kp2 = KP_P;
#else
    DWORD algid_export = CALG_PRO_EXPORT;
    DWORD algid_ephem = CALG_DH_EX_EPHEM;
    DWORD kp1 = KP_HASHOID;
    DWORD kp2 = KP_DHOID;
#endif /* defined( BOURGEOIS ) */
    /* Генерация эфимерных ключей: */
        /* -- в исходном контейнере */
    if( !UniGenKey( hSrcProv, algid_ephem, CRYPT_EXPORTABLE,
        &hSrcEphemKey ) )
    {
        err_fun = "CryptGenKey";
        goto err;
    }
        /* -- в результирующем контейнере. */
    if( !UniGenKey( hDestProv, algid_ephem, CRYPT_EXPORTABLE | CRYPT_PREGEN,
        &hDestEphemKey ) )
    {
        err_fun = "CryptGenKey";
        goto err;
    }
        /* -- передача параметра G из исходного контейнера; */
    if( !CopyKeyParam( hSrcProv, hDestProv, kp1, hSrcEphemKey,
        hDestEphemKey ) )
    {
        err_fun = "CopyKeyParam";
        goto err;
    }
        /* -- передача параметра P из исходного контейнера; */
    if( !CopyKeyParam( hSrcProv, hDestProv, kp2, hSrcEphemKey,
        hDestEphemKey ) )
    {
        err_fun = "CopyKeyParam";
        goto err;
    }
        /* -- генерация параметра X; */
    if( !UniSetKeyParam( hDestProv, hDestEphemKey, KP_X, NULL, 0 ) )
    {
        err_fun = "CryptSetKeyParam";
        goto err;
    }
    /* Получение agree key в результирующем контейнере: */
        /* -- экспорт из исходного контейнера; */
    if( !UniExportKey( hSrcProv, hSrcEphemKey, 0, PUBLICKEYBLOB, 0,
        NULL, &dwBlobLen ) )
    {
        err_fun = "CryptExportKey";
        goto err;
    }
    pbKeyBlob = (BYTE*)malloc( dwBlobLen );
    if( !pbKeyBlob )
    {
        err_fun = "malloc";
        goto err;
    }
    if( !UniExportKey( hSrcProv, hSrcEphemKey, 0, PUBLICKEYBLOB, 0,
        pbKeyBlob, &dwBlobLen ) )
    {
        err_fun = "CryptExportKey";
        goto err;
    }
        /* -- импорт в результирующий; */
    if( !UniImportKey( hDestProv, pbKeyBlob, dwBlobLen,
        hDestEphemKey, 0, &hDestAgreeKey ) )
    {
        err_fun = "CryptImportKey";
        goto err;
    }
    free( pbKeyBlob ); pbKeyBlob = NULL; dwBlobLen = 0;
    /* Получение agree key в исходном контейнере: */
        /* -- экспорт из результирующего контейнера; */
    if( !UniExportKey( hDestProv, hDestEphemKey, 0, PUBLICKEYBLOB, 0,
        NULL, &dwBlobLen ) )
    {
        err_fun = "CryptExportKey";
        goto err;
    }
    pbKeyBlob = (BYTE*)malloc( dwBlobLen );
    if( !pbKeyBlob )
    {
        err_fun = "malloc";
        goto err;
    }
    if( !UniExportKey( hDestProv, hDestEphemKey, 0, PUBLICKEYBLOB, 0,
        pbKeyBlob, &dwBlobLen ) )
    {
        err_fun = "CryptExportKey";
        goto err;
    }
        /* -- импорт в исходный; */
    if( !UniImportKey( hSrcProv, pbKeyBlob, dwBlobLen,
        hSrcEphemKey, 0, &hSrcAgreeKey ) )
    {
        err_fun = "CryptImportKey";
        goto err;
    }
    free( pbKeyBlob ); pbKeyBlob = NULL; dwBlobLen = 0;
    /* Конвертирование agree key в сессионный */
        /* -- в исходном контейнере; */
    if( !UniSetKeyParam( hSrcProv, hSrcAgreeKey, KP_ALGID,
        (BYTE*)&algid_export,
        0 ) )
    {
        err_fun = "CryptSetKeyParam";
        goto err;
    }
        /* -- в результирующем контейнере; */
    if( !UniSetKeyParam( hDestProv, hDestAgreeKey, KP_ALGID,
        (BYTE*)&algid_export,
        0 ) )
    {
        err_fun = "CryptSetKeyParam";
        goto err;
    }
    /* Экспорт пользовательского ключа на сессионном. */
    if( !UniExportKey( hSrcProv, hSrcKey, hSrcAgreeKey, PRIVATEKEYBLOB,
        0, NULL, &dwBlobLen ) )
    {
        err_fun = "CryptExportKey";
        goto err;
    }
    pbKeyBlob = (BYTE*)malloc( dwBlobLen );
    if( !pbKeyBlob )
    {
        err_fun = "malloc";
        goto err;
    }
#if defined( TEST_EPHEM )
    if( !UniExportKey( hSrcProv, hSrcEphemKey, hSrcAgreeKey, PRIVATEKEYBLOB,
        0, pbKeyBlob, &dwBlobLen ) )
    {
        err_fun = "CryptExportKey";
        goto err;
    }
    if( !UniImportKey( hDestProv, pbKeyBlob, dwBlobLen, hDestAgreeKey,
        CRYPT_EXPORTABLE, &hDestKey ) )
    {
        err_fun = "CryptImportKey";
        goto err;
    }
#else
    if( !UniExportKey( hSrcProv, hSrcKey, hSrcAgreeKey, PRIVATEKEYBLOB,
        0, pbKeyBlob, &dwBlobLen ) )
    {
        err_fun = "CryptExportKey";
        goto err;
    }
    /* Импотр пользовательского ключа. */
    if( !UniImportKey( hDestProv, pbKeyBlob, dwBlobLen, hDestAgreeKey,
        CRYPT_EXPORTABLE, &hDestKey ) )
    {
        err_fun = "CryptImportKey";
        goto err;
    }
    if( !CopyKeyParam( hSrcProv, hDestProv, KP_CERTIFICATE, hSrcKey,
        hDestKey ) )
    {
        printf( "Certificate not found fail.\n" );
    }
#endif
err:
    if( hDestEphemKey ) UniDestroyKey( hDestProv, hDestEphemKey );
    if( hSrcEphemKey )  UniDestroyKey( hSrcProv, hSrcEphemKey );
    if( hDestAgreeKey ) UniDestroyKey( hDestProv, hDestAgreeKey );
    if( hSrcAgreeKey )  UniDestroyKey( hSrcProv, hSrcAgreeKey );
    if( hDestKey )      UniDestroyKey( hDestProv, hDestKey );
    if( pbKeyBlob )
        free( pbKeyBlob );
    if( err_fun )
    {
        printf( "%s fail. LastError:0x%x\n", err_fun, GetLastError() );
        return FALSE;
    }
    return TRUE;
}

BOOL CopyContainerParam1( HCRYPTPROV hSrc, HCRYPTPROV hDest, DWORD pp )
{
    DWORD data_len = 0;
    BYTE *oid = NULL;
    const char *err_fun = NULL;

    if( !UniGetProvParam( hSrc, pp, NULL, &data_len, 0 ) )
    {
        err_fun = "CryptGetProvParam";
        goto err;
    }
    oid = malloc( data_len );
    if( !oid )
    {
        err_fun = "malloc";
        goto err;
    }
    if( !UniGetProvParam( hSrc, pp, oid, &data_len, 0 ) )
    {
        err_fun = "CryptGetProvParam";
        goto err;
    }
    if( !UniSetProvParam( hDest, pp, oid, 0 ) )
    {
        err_fun = "CryptGetProvParam";
        goto err;
    }

err:
    if( oid )
        free( oid );
    if( err_fun )
    {
        printf( "%s fail. LastError:0x%x\n", err_fun, GetLastError() );
        return FALSE;
    }
    return TRUE;
}

BOOL CopyContainerParam( HCRYPTPROV hSrc, HCRYPTPROV hDest )
{
    if( !CopyContainerParam1( hSrc, hDest, PP_HASHOID ) )
        return FALSE;
    if( !CopyContainerParam1( hSrc, hDest, PP_CIPHEROID ) )
        return FALSE;
    return TRUE;
}

char *GetContainerName( int cplevel, PVTABLEPROVSTRUC pvTable,
    char * szProvider, DWORD dwProvType )
{
    HCRYPTPROV hProv;
    BOOL res;
    TCHAR *select;
    DWORD select_length = 64;

    if( cplevel )
        res = MyAcquireContext( &hProv, NULL, CRYPT_VERIFYCONTEXT, pvTable );
#ifndef UNIX
    else
        res = CryptAcquireContext( &hProv, NULL, szProvider, dwProvType,
        CRYPT_VERIFYCONTEXT );
#endif UNIX
    if( !res )
        return NULL;
    select = malloc( 64 );
    if( !select )
    {
        UniReleaseContext( hProv, 0 );
        return NULL;
    }
    if( !UniGetProvParam( hProv, PP_SELECT_CONTAINER, (BYTE*)select,
        &select_length, 0 ) )
    {
        UniReleaseContext( hProv, 0 );
        free( select );
        return NULL;
    }
    UniReleaseContext( hProv, 0 );
    return select;
}

static const unsigned short TABLE[256] = {
    0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
    0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
    0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
    0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
    0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
    0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
    0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
    0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
    0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
    0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
    0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
    0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
    0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
    0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
    0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
    0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
    0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
    0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
    0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
    0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
    0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
    0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
    0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
    0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
    0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
    0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
    0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
    0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
    0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
    0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
    0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
    0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
};

void crc16( const char *text, unsigned char *CRC )
{
    while( *text )
        *(unsigned short*)CRC = (unsigned short)(
        TABLE[CRC[0] ^ tolower( *text++ )] ^ CRC[1] );
}

#if !defined(lint) && !defined(NO_RCSID) && !defined(OK_MODULE_VERSION)
static volatile const char rcsid[] = "\n$Id: ctkey.c,v 1.68.4.5 2002/08/22 13:59:51 lse Exp $";
#endif


Main Index

КриптоПро CSP Описание

Последние изменения: 25 окт 2002


CryptAcquireContext

Смотри документацию Microsoft CryptoAPI 2.0 в MSDN CryptAcquireContext.


CryptCreateHash

Смотри документацию Microsoft CryptoAPI 2.0 в MSDN CryptCreateHash


CryptDecrypt

Смотри документацию Microsoft CryptoAPI 2.0 в MSDN CryptDecrypt


CryptDeriveKey

Смотри документацию Microsoft CryptoAPI 2.0 в MSDN CryptDeriveKey


CryptDestroyHash

Смотри документацию Microsoft CryptoAPI 2.0 в MSDN CryptDestroyHash


CryptDestroyKey

Смотри документацию Microsoft CryptoAPI 2.0 в MSDN CryptDestroyKey


CryptDuplicateHash

Смотри документацию Microsoft CryptoAPI 2.0 в MSDN CryptDuplicateHash


CryptDuplicateKey

Смотри документацию Microsoft CryptoAPI 2.0 в MSDN CryptDuplicateKey


CryptEncrypt

Смотри документацию Microsoft CryptoAPI 2.0 в MSDN CryptEncrypt


CryptExportKey

Смотри документацию Microsoft CryptoAPI 2.0 в MSDN CryptExportKey


CryptGenKey

Смотри документацию Microsoft CryptoAPI 2.0 в MSDN CryptGenKey


CryptGetHashParam

Смотри документацию Microsoft CryptoAPI 2.0 в MSDN CryptGetHashParam


CryptGetKeyParam

Смотри документацию Microsoft CryptoAPI 2.0 в MSDN CryptGetKeyParam


CryptGetProvParam

Смотри документацию Microsoft CryptoAPI 2.0 в MSDN CryptGetProvParam.


CryptGetUserKey

Смотри документацию Microsoft CryptoAPI 2.0 в MSDN CryptGetUserKey


CryptHashData

Смотри документацию Microsoft CryptoAPI 2.0 в MSDN CryptHashData


CryptHashSessionKey

Смотри документацию Microsoft CryptoAPI 2.0 в MSDN CryptHashSessionKey


CryptImportKey

Смотри документацию Microsoft CryptoAPI 2.0 в MSDN CryptImportKey


CryptReleaseContext

Смотри документацию Microsoft CryptoAPI 2.0 в MSDN CryptReleaseContext


CryptSetHashParam

Смотри документацию Microsoft CryptoAPI 2.0 в MSDN CryptSetHashParam


CryptSetKeyParam

Смотри документацию Microsoft CryptoAPI 2.0 в MSDN CryptSetKeyParam


CryptSetProvParam

Смотри документацию Microsoft CryptoAPI 2.0 в MSDN CryptSetProvParam


CryptSignHash

Смотри документацию Microsoft CryptoAPI 2.0 в MSDN CryptSignHash


CryptVerifySignature

Смотри документацию Microsoft CryptoAPI 2.0 в MSDN CryptVerifySignature


CPAcquireContext

Смотри документацию Microsoft CSP в MSDN CPAcquireContext


CPCreateHash

Смотри документацию Microsoft CSP в MSDN CPCreateHash


CPDecrypt

Смотри документацию Microsoft CSP в MSDN CPDecrypt


CPDeriveKey

Смотри документацию Microsoft CSP в MSDN CPDeriveKey


CPDestroyHash

Смотри документацию Microsoft CSP в MSDN CPDestroyHash


CPDestroyKey

Смотри документацию Microsoft CSP в MSDN CPDestroyKey


CPDuplicateHash

Смотри документацию Microsoft CSP в MSDN CPDuplicateHash


CPDuplicateKey

Смотри документацию Microsoft CSP в MSDN CPDuplicateKey


CPEncrypt

Смотри документацию Microsoft CSP в MSDN CPEncrypt


CPExportKey

Смотри документацию Microsoft CSP в MSDN CPExportKey


CPGenKey

Смотри документацию Microsoft CSP в MSDN CPGenKey


CPGetHashParam

Смотри документацию Microsoft CSP в MSDN CPGetHashParam


CPGetKeyParam

Смотри документацию Microsoft CSP в MSDN CPGetKeyParam


CPGetProvParam

Смотри документацию Microsoft CSP в MSDN CPGetProvParam


CPGetUserKey

Смотри документацию Microsoft CSP в MSDN CPGetUserKey


CPHashData

Смотри документацию Microsoft CSP в MSDN CPHashData


CPHashSessionKey

Смотри документацию Microsoft CSP в MSDN CPHashSessionKey


CPImportKey

Смотри документацию Microsoft CSP в MSDN CPImportKey


CPReleaseContext

Смотри документацию Microsoft CSP в MSDN CPReleaseContext


CPSetHashParam

Смотри документацию Microsoft CSP в MSDN CPSetHashParam


CPSetKeyParam

Смотри документацию Microsoft CSP в MSDN CPSetKeyParam


CPSetProvParam

Смотри документацию Microsoft CSP в MSDN CPSetProvParam


CPSignHash

Смотри документацию Microsoft CSP в MSDN CPSignHash


CPVerifySignature

Смотри документацию Microsoft CSP в MSDN CPVerifySignature


CPAcquireContext

Функция CPAcquireContext().

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

BOOL WINAPI CPAcquireContext (
  HCRYPTPROV * phProv,
  CHAR * pszContainer,
  DWORD dwFlags,
  PVTABLEPROVSTRUC pVTable
);

Параметры:

phProv
[out] Адрес, по которому функция копирует дескриптор криптопровайдера.
pszContainer
[in] Имя ключевого контейнера. Это указатель на строку, длиной не больше, чем MAX_PATH знаков, включая признак конца строки. Если данный параметр - NULL, то криптопровайдер будет использовать в качестве имени контейнера имя пользователя, вошедшего в систему. Пользователь может получить имя используемого контейнера функцией CPGetProvParam(). Подробнее см. LPSZ_CONTAINER_NAME.
dwFlags
[in] Параметр имеет нулевое или одно из следующих значений:
Значение dwFlags | Описание
CRYPT_VERIFYCONTEXT | Приложение не имеет доступа к секретным ключам ключевого контейнера. Флаг предназначен для использования с приложениями, для которых требуется проверка цифровой подписи. Операции, обычно необходимые в этом случае, – получение дескрипторов открытых ключей, хэширование и проверка подписи. При вызове функции CryptAcquireContext() криптопровайдер не требует от пользователя ввода ключевой информации.
CRYPT_NEWKEYSET | Если флаг установлен, то будет создан новый ключевой контейнер с именем, соответствующим pszContainer. Если pszContainer - NULL, то в качестве имени контейнера используется имя пользователя, вошедшего в систему.
CRYPT_MACHINE_KEYSET | Флаг может использоваться при вызове функции CryptAcquireContext() c CRYPT_NEW_KEYSET или флагом CRYPT_DELETE_KEYSET. В этом случае ключи будут сохранены в ключе HKEY_LOCAL_MACHINE системного реестра. Флаг предназначен для использования криптопровайдера в составе системных приложений.
CRYPT_DELETEKEYSET | Ключевой контейнер, соответствующий pszContainer, удаляется. Если pszContainer - NULL, то удаляется ключевой контейнер с именем, заданным по умолчанию. Все ключевые пары в ключевом контейнере также уничтожаются. Когда флаг CRYPT_DELETEKEYSET установлен, значение, возвращенное в phProv, не определено и функция CPReleaseContext() не должна вызываться повторно.
CRYPT_SILENT | Приложение запрещает "КриптоПро CSP" использовать какой либо пользовательский интерфейс (UI) при выполнении операций с данным контекстом. Если для выполнения операции "КриптоПро CSP" необходимо использовать UI, то он будет возвращать ошибку NTE_SILENT_CONTEXT, как код LastError.
pVTable
[in] Указатель на структуру _VTABLEPROVSTRUC, которая содержит список callback функций, представляемых операционной системой для использования криптопровайдером.

Возвращает:

При успешном завершении функция возвращает TRUE, в противном случае возвращается FALSE. Если возвращается FALSE, соответствующий код ошибки (см. таблицу) может быть получен через функцию GetLastError().
Возвращаемые значения | Описание
ERROR_BUSY | Ключевой контейнер с данным именем был создан иным процессом и в настоящее время не может использоваться данным процессом. Если эта ошибка возникает при обработке контейнера в одном процессе, разрешить коллизию можно вызовом функции CPReleaseContext().
NTE_BAD_FLAGS | Параметр dwFlags имеет запрещенное значение.
NTE_BAD_KEYSET | Ключевой контейнер не был открыт, и, возможно, не существует.
NTE_BAD_KEYSET_PARAM | Параметр pszContainer установлен в запрещенное значение.
NTE_BAD_SIGNATURE | Не прошла проверка цифровой подписи DLL криптопровайдера. DLL или цифровая подпись искажены.
NTE_EXISTS | Параметр dwFlags установлен в CRYPT_NEWKEYSET, а ключевой контейнер уже существует.
NTE_KEYSET_ENTRY_BAD | Ключевой контейнер, соответствующий pszContainer найден, но искажен.
NTE_KEYSET_NOT_DEF | Ключевой контейнер, соответствующий pszContainer, не существует.
NTE_NO_MEMORY | Криптопровайдер во время операции исчерпал память.
SCARD_W_CANCELLED_BY_USER | Пользователь прервал операцию, нажатием клавиши Cancel
SCARD_W_WRONG_CHV | Пользователь ввел неправильный пароль или пароль, установленный функцией SetProvParam, неправильный
SCARD_E_INVALID_CHV | Пользователь ввел пароль с нарушением формата или пароль, установленный функцией SetProvParam, имеет неправильный формат. Например, пароль имеет недопустимую длину или содержит недопустимые символы.
SCARD_W_CHV_BLOCKED | Ввод Pin-кода был заблокирован смарт-картой, т.к. исчерпалось количество попыток, разрешенное картой для ввода.
NTE_TOKEN_KEYSET_STORAGE_FULL | Недостаточно места на носителе для сохранения информации.

Требования:

Windows NT/2000/XP: Необходимо Windows NT 4.0 SP5 или старше с Internet Explorer 5.0 или старше.
Windows 98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле Wincrypt.h.
Solaris: Прототип описан в файле CSP_Wincrypt.h.
Ядро ОС: При использовании в ядре ОС CPAcquireContext допустимо вызывать только с флагами CRYPT_VERIFYCONTEXT|CRYPT_SILENT.

См. также:

CPReleaseContext() , CPAcquireContext() в MS CSP , CryptAcquireContext() в MS CryptoAPI 2.0 , CryptSetProvParam() в MS CryptoAPI 2.0

Примеры:

ctkey.c.


CPReleaseContext

Функция CPReleaseContext().

Используется для удаления дескриптора криптопровайдера, созданного функцией CPAcquireContext().

BOOL WINAPI CPReleaseContext (
  HCRYPTPROV hProv,
  DWORD dwFlags
);

Параметры:

hProv
[in] Дескриптор криптопровайдера. Получается через запрос функции CPAcquireContext().
dwFlags
[in] Значения флагов. Параметр зарезервирован для будущего использования и должен быть 0.

Возвращает:

При успешном завершении функция возвращает TRUE, в противном случае возвращается FALSE. Если возвращается FALSE, соответствующий код ошибки (см. таблицу) может быть получен через функцию GetLastError().
Возвращаемые значения | Описание
NTE_BAD_FLAGS | Параметр dwFlags имеет ненулевое значение.

Примечание:

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

Требования:

Windows NT/2000/XP: Необходимо Windows NT 4.0 SP5 или старше с Internet Explorer 5.0 или старше.
Windows 98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле Wincrypt.h.
Solaris: Прототип описан в файле CSP_Wincrypt.h.

См. также:

CPAcquireContext() , CPReleaseContext() в MS CSP , CryptReleaseContext() в MS CryptoAPI 2.0

Примеры:

ctkey.c.


CPVerifySignature

Функция CPVerifySignature().

Осуществляет проверку цифровой подписи, соответствующей объекту функции хэширования.

BOOL WINAPI CPVerifySignature (
  HCRYPTPROV hProv,
  HCRYPTHASH hHash,
  BYTE * pbSignature,
  DWORD dwSigLen,
  HCRYPTKEY hPubKey,
  LPCWSTR sDescription,
  DWORD dwFlags
);

Параметры:

hProv
[in] Дескриптор криптопровайдера. Получается через запрос функции CPAcquireContext().
hHash
[in] Дескриптор объекта функции хэширования, подпись которого проверяется.
pbSignature
[in] Буфер, содержащий значение проверяемой подписи.
dwSigLen
[in] Длина (в байтах) значения подписи.
sDescription
[in] Описание подписанных данных идентичное описанию, использованному при создании подписи. Это должна быть точно та же самая последовательность, которая использовалась в функции CPSignHash() при создании подписи. Если эта последовательность не соответствует использованной в функции CPSignHash(), проверка подписи сообщит, что подпись не верна.
dwFlags
[in] Значения флагов. Параметр зарезервирован для будущего использования и должен быть 0.

Возвращает:

При успешном завершении функция возвращает TRUE, в противном случае возвращается FALSE. Если возвращается FALSE, соответствующий код ошибки (см. таблицу) может быть получен через функцию GetLastError.
Возвращаемые значения | Описание
NTE_BAD_ALGID | Дескриптор hHash определяет алгоритм, который этот криптопровайдер не поддерживает.
NTE_BAD_FLAGS | dwFlags параметр отличен от нуля, либо параметр dwKeySpec содержит ошибочную величину.
NTE_BAD_KEY | hPubKey параметр содержит дескриптор на недопустимый открытый ключ.
NTE_BAD_SIGNATURE | Проверка подписи не прошла. Это могло случиться потому, что изменились сами данные, последовательность описания не соответствует, или открытый ключ был определен ошибочно параметром hPubKey. Эта ошибка может быть возвращена также, если алгоритмы хэширования или подписи не соответствуют тем, с помощью которых вычислялась подпись.
NTE_NO_MEMORY | Криптопровайдер во время операции исчерпал память.
NTE_FAIL | Нарушение целостности ключей в ОЗУ.
RPE_CORRUPT_KEYPAIR_INFO | Нарушение целостности ключей.

Примечание:

Функция CPVerifySignature выполняет следующие внутренне шаги:

  • если параметр описания sDescription поддержан, он добавляется к объекту функции хэширования;
  • объект функции хэширования "закрывается" и значение функции хэширования извлекается;
  • значение функции хэширования дополняется, как это требуется алгоритмом подписи;
  • осуществляется проверка подписи c использованием открытого ключа hPubKey;
  • если подпись, переданная через буфер pbSignature, и вычисленное значение подписи не совпадают, возвращается код ошибки NTE_BAD_SIGNATURE.

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

Требования:

Windows NT/2000/XP: Необходимо Windows NT 4.0 SP5 или старше с Internet Explorer 5.0 или старше.
Windows 98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле Wincrypt.h.
Solaris: Прототип описан в файле CSP_Wincrypt.h.
Ядро ОС: В ядре ОС эта функция не поддерживается.

См. также:

CPCreateHash() , CPHashData() , CPSignHash() , CPVerifySignature() в MS CSP , CryptVerifySignature() в MS CryptoAPI 2.0

Примеры:

ctkey.c.


Возвращение данных неопределенной длины

Многие функции криптопровайдера и CryptoAPI возвращают неопределенное количество данных по адресу, предоставленному через параметр функции. Во всех таких случаях операция производится в следующем порядке. Параметр, который содержит указатель на возвращаемые данные, записываетcя с префиксом "pb" или "pv" с последующим именем параметра. Другой параметр функции имеет префикс "pcb" с последующим именем параметра. Данный параметр определяет длину в байтах данных, которые будут возвращены в адреса, описанные переменными с префиксами "pb" или "pv". Следующий пример показывает спецификацию функции такого типа:

BOOL WINAPI SomeFunction(
  PCCRL_CONTEXT pCrlContext,  // in
  DWORD dwPropId,             // in
  BYTE *pbData,               // out
  DWORD *pcbData              // in/out
);

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

Примечание 1. Префикс параметров, содержащих возвращаемые данные, может иногда отличаться от "pcb", например "p" или "pv". Соответствующий параметр, определяющий длину данных тоже может иметь другой префикс, например для "pwsz" он может быть "pcch", где "pcch" определяет длину символов в кодировке Unicode или ASCII возвращаемых данных.

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

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

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

Примечание 3.Использование двухпроходной схемы (NULL указывается в качестве значения параметра pbData) может приводить к снижению производительности для некоторых функций. К таким функциям в первую очередь относятся функции создания сообщений, относящийся к классам Low Level Message Functions и Simplified Message Functions, так как для определения размера сообщения производится его полное формирование, включая генерацию сеансовых ключей. Для приложений, в которых критерий производительности является определяющим, можно рекомендовать заранее резервировать буфер для выходных данных определенной длины и обрабатывать код возврата функции.

Последующие примеры показывают реализация обеих схем.

Процедура с учетом производительности

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

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

//--------------------------------------------------------------------
// Assume SomeFunction (from the previous example) is called
// repetitively by an application, and that a buffer size of
// 50 bytes will handle the output for all but a few cases.

//--------------------------------------------------------------------
// Set up SomeFunction variables.

PCCRL_CONTEXT pCrlContext; // Initialized elsewhere.
DWORD dwPropId;            // Initialized elsewhere.

//--------------------------------------------------------------------
// Preallocate a 50 byte buffer, and
// use that buffer in a call to SomeFunction that produces the
// desired output data most of the time.
// However, the case where more than 50 bytes are required for the
// output data must be handled as well. For that case, use the cb
// returned by the failed call to SomeFunction to allocate a bigger
// buffer.
// After the allocation of additional bytes for the buffer, a second
// call to SomeFunction using the larger buffer is then made.

//--------------------------------------------------------------------
//   Assume variables pCrlContext and dwPropId have been declared and
//   initialized elsewhere.

DWORD dwTries = 0; // the number of times the function has been tried
BOOL fMore=TRUE;   // flag indicating the function needs to be tried
DWORD cbData = 50;
BYTE  *pbData;

//--------------------------------------------------------------------
//  Begin processing. This loop is executed at most twice.

while (fMore)
{
if (pbData = (BYTE *)malloc(cbData))
{
     printf("Memory has been allocated.\n");
}
else
{
     HandleError("Memory allocation error.");
}
//--------------------------------------------------------------------
//  Memory has been allocated. Try the function.
   if (SomeFunction(pCrlContext, dwPropId, pbData, &cbData))
       // The function succeeded. Exit the loop.
   {
            printf("The function succeeded. Exit the loop.\n");
            fMore=FALSE;
   }
   else
   {
         // The function failed. Free the space allocated.
          free(pbData);  // Free the buffer on failure.

        // If the error was not that the buffer was not big enough,
        // exit the loop having failed.

         if(GetLastError() != ERROR_MORE_DATA )
         {
              HandleError("General function failure.");
         }
         // If the error was that there was that there was not enough
         // space in the buffer, try a second but not a third time.
         if( ++dwtries > 1 )
          {
              HandleError("Function call failed twice ");
          }
}  // ends loop

//--------------------------------------------------------------------
//  If the loop runs to completion, the function succeeded either the
//  the first or the second time through. In either case, cbData is
//  updated with the actual size of the data returned.
//  Use this size when processing pbData.

//--------------------------------------------------------------------
//  Process pbData here as needed.

//--------------------------------------------------------------------
//  Clean up after processing.

free(pbData); // Free the data buffer
              // after the data has been processed.

Увеличение производительности может быть получено также за счет использования alloc для отведения памяти в стеке вместо использования malloc для отведения памяти в хипе (heap). Из за того, что буфер находится в стеке, нет необходимости вызова free при завершении работы с буфером. При использовании alloc, данные буфера должны быть использованы локально, так как по завершению функции, буфер автоматически освобождается очисткой стека. Вместе с этим, вызов alloc уменьшает размер стека, что может провести к его переполнению..

Процедура с предварительным определением длины буфера

Следующий пример показывает способ определения требуемой длины буфера для возвращаемых данных:

//--------------------------------------------------------------------
//   In this and all other sample and example code,
//   use the #define and #include statements listed
//   under #includes and #defines.

#include <stdio.h>
#include <windows.h>
#include <wincrypt.h>
#define MY_ENCODING_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)

void HandleError(char *s);

void main()
{
//--------------------------------------------------------------------
// Set up SomeFunction variables.

PCCRL_CONTEXT pCrlContext; // Initialized elsewhere.
DWORD dwPropId;            // Initialized elsewhere.
DWORD cbData;
BYTE  *pbData;

//--------------------------------------------------------------------
// Call SomeFunction to set cbData, the size of
// the buffer needed for pbData.

if(SomeFunction(
     pCrlContext,
     dwPropId,
     NULL,
     &cbData))
{
       printf("The function succeeded.\n");
}
else
{
// The function call failed. Handle the error.
       HandleError("Function call failed.");
}

//--------------------------------------------------------------------
// The call succeeded; the size for the needed buffer, in bytes,
// now resides in cbData.

//--------------------------------------------------------------------
// Malloc memory for the size of the message.

if(pbData = (BYTE*)malloc(cbData))
{
   printf("Memory has been allocated.\n");
}
else
{
   // The allocation failed. Write an error message and exit.
   HandleError("Malloc operation failed. ");
}

//--------------------------------------------------------------------
// The space for the buffer has been allocated.
// Call SomeFunction to fill the buffer with the data.

if(SomeFunction(
      pCrlContext,
      dwPropId,
      pbData,
      &cbData))
{
       printf("The function succeeded.\n");
}
else
{
   // The second function call failed. Handle the error.
   HandleError("The second call to the function failed.");
}
//*******************************************************************
// The function succeeded; the data is now in the buffer
// pointed to by pbData. Note that cbData is
// updated with the actual size of the data returned. Use this size
// to process bytes of pbData.
} // End of main

//--------------------------------------------------------------------
//  This example uses the function HandleError, a simple error
//  handling function, to print an error message to the standard error
//  (stderr) file and exit the program.
//  For most applications, replace this function with one
//  that does more extensive error reporting.

void HandleError(char *s)
{
    fprintf(stderr,"An error occurred in running the program.\n");
    fprintf(stderr,"%s\n",s);
    fprintf(stderr,"Error number %x.\n",GetLastError());
    fprintf(stderr,"Program terminating.\n");
    exit(1);
}


PCRYPT_SIMPLEBLOB

Псевдоструктура CRYPT_SIMPLEBLOB.

Полностью описывает ключевой блоб типа SIMPLEBLOB для ключей "КриптоПро CSP". Все поля этой псевдоструктуры выравнены по границе байта и находятся в сетевом порядке байт (ASN1 DER).

typedef struct CRYPT_SIMPLEBLOB * PCRYPT_SIMPLEBLOB;

Требования:

Windows NT/2000: Необходимо Windows NT 4.0 или старше с Internet Explorer 5.0 или старше.
Windows 95/98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле CSPKernel.h.

См. также:

CRYPT_SIMPLEBLOB_HEADER , CPExportKey() , CPGetKeyParam()


CRYPT_PUBKEYPARAM

Структура CRYPT_PUBKEYPARAM.

Содержит признак ключей по ГОСТ Р 34.10-94 или ГОСТ Р 34.10-2001.

typedef struct _CRYPT_PUBKEYPARAM_  CRYPT_PUBKEYPARAM;

Требования:

Windows NT/2000: Необходимо Windows NT 4.0 или старше с Internet Explorer 5.0 или старше.
Windows 95/98/ME: Необходимо Windows 95 OSR2 или старше с Internet Explorer 5.0 или старше.
Файл описания: Прототип описан в файле CSPKernel.h.

См. также:

CRYPT_PUBKEY_INFO_HEADER , CPExportKey() , CPGetKeyParam()


CRYPT_CHANGE_PIN_SOURCE

Структура передачи пароля, pin-кода, имени контейнера, HANDLE контейнера при смене пароля.

typedef union CRYPT_CHANGE_PIN_SOURCE_  CRYPT_CHANGE_PIN_SOURCE;


PVTABLEPROVSTRUC

Структура _VTABLEPROVSTRUC.

Cодержит указатели на callback функции, которые могут быть использованы функциями криптопровайдера (CSP).

typedef struct _VTABLEPROVSTRUC * PVTABLEPROVSTRUC;

Примечание:

Указатель на структуру _VTABLEPROVSTRUC доступен только во врема вызова функции CPAcquireContext(). Если члены структуры необходимы для дальнейшей работы, необходимо произвести копирование значений. Скопированные указатели на функции, содержащиеся в струкруре и сами функции, могут быть использованы до тех пор пока не закрылась сессия с криптопровайдером. Все дополнительные модули (DLL), которые использует криптопровайдер могут быть подписаны, как и основной модуль. Перд загрузкой дополнительны модулей с использованием функции LoadLib, можно проверить подпись дополнительных модулей. Криптопровайдер может производить такую проверку, используя указатель на функцию FuncVerifyImage(), как показано в следующем примере:

 BOOL (FARPROC *ProvVerifyImage)(LPCSTR lpszImage, BYTE *pSigData);
 BYTE bSignature[72];

 // "ProvVerifyImage" has been set to "pVTable->FuncVerifyImage"
 // within the CPAcquireContext function.

 // Load the C:\Winnt40\System32\signature.sig file into the
 // bSignature buffer. During development, this file is created
 // with the Sign.exe utility.
 ...

 // Verify the signature on the C:\Winnt40\System32\Signature.dll file.
 if(RCRYPT_FAILED(ProvVerifyImage("c:\\winnt40\\system32\\signature.dll",
                                  bSignature)) {
     SetLastError(NTE_BAD_SIGNATURE);
    return CRYPT_FAILED;
 }

 // Load the DLL with the LoadLib function, then acquire pointers to
 // the member functions with the GetProcAddress function.
 ...