КриптоПро CSP 3.0

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

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

КриптоПро CSP

Версия 3.0

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

ЖТЯИ.00015-01 90 03

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


Введение

КриптоПро CSP 3.0

ЖТЯИ.00015-01 90 03

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

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

КриптоПро CSP 3.0

КриптоПро CSP

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

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

Данный документ описывает программный интерфейс СКЗИ КриптоПро CSP, реализованный для следующих операционных систем:

  • Windows 2000/XP/2003;
  • Solaris 9 Update 4;
  • FreeBSD 5;
  • Red Hat Linux 7, 9.

Для перечисленных операционных систем также реализована библиотека на уровне ядра ОС.

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

Для UNIX-платформ рекомендуется использовать либо данный программный интерфейс, либо CAPILite.

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

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

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

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

  • Центр Сертификации - Microsoft Certification Authority
  • Электронная почта - Microsoft Outlook
  • Электронная почта - Microsoft Outlook Express
  • Средства контроля целостности ПО - Microsoft Authenticode
  • Защита соединений в Интернете (протокол TLS/SSL)
  • Электронно-цифровая подпись в Word, Excel - Office XP, 2003
  • Электронно-цифровая подпись XML, в том числе, InfoPath из состава Office 2003

Аннотация

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

Архитектура

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

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

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

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

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


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

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

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

  • Центр Сертификации - Microsoft Certification Authority, входящий в состав OS Windows 2000 Server, Advanced Server World Wide Web link ;
  • Электронная почта - Microsoft Outlook 98, 2000, XP World Wide Web link ;
  • Электронная почта - Microsoft Outlook Express, входящая в состав Internet Explorer версии 5.0 или выше World Wide Web link ;
  • Средства контроля целостности ПО, распространяемого по сети - Microsoft Authenticode World Wide Web link ;
  • Защита TCP/IP соединений в сети Интернет - протокол TLS/SSL при взаимодействии Internet Explorer - Web сервер IIS 5.0(4.0) World Wide Web link ;

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

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

Для работы с любым отладчиком контроль целостности в драйвере должен быть отключен. Для этого следует в реестре значение HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\CProIntegrity\CheckMode установить в 0. После этого для Windows XP, 2003 необходимо перестартовать сервис, а для Windows 2000 перегрузить машину.

Подключение на уровне 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.

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

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

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

На сервере Крипто-Про ведется Форум World Wide Web link по вопросам использования криптографических функций и сертификатов открытых ключей. Соответствующие конференции по отдельным темам ведутся на сервере Microsoft:

  • вопросы использования CryptoAPI World Wide Web link
  • вопросы использования технологии Authenticode World Wide Web link
  • вопросы использования CAPICOM World Wide Web link

Rezume

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

Крипто-Про CSP Версия: 3.0 Сборка 3293


Средство криптографической защиты информации КриптоПро CSP версия 3.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 с использованием устройств Аккорд-АМДЗ, электронный замок "Соболь",устройство чтения таблеток 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;
  • опциональное использование пароля (пин-кода) для дополнительной защиты ключевой информации;
  • реализация мер защиты от НСД ключевой информации пользователя.

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

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Ядро Windows NT: IRQL < DISPATCH_LEVEL

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

  • Microsoft Security Bulletin MS02-048. Flaw in Certificate Enrollment Control Could Allow Deletion of Digital Certificates (Q323172). August 28, 2002 World Wide Web link
  • Microsoft Security Bulletin MS02-050. Certificate Validation Flaw Could Enable Identity Spoofing (Q328145). September 09, 2002 World Wide Web link

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

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

Примечание 3. При выборе ОС необходимо учитывать следующие сроки поддержки и окончания эксплуатации операционных систем по данным фирмы Microsoft на 03.07.2002 г. (Windows Desktop Product Life Cycle Support and Availability Policies for Businesses World Wide Web link ):
ОС | Поддержка | Окончание эксплуатации
Microsoft Windows 2000 | 31 марта 2005 г. | 31 марта 2007 г.
Microsoft Windows XP | 31 декабря 2006 г. | 31 декабря 2008 г.
Microsoft Windows 2003 | 30 июня 2008 г. | 30 июня 2010 г.

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

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

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

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

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

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

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

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

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


Интерфейс криптопровайдера "КриптоПро CSP"

Функции, структуры, параметры внешнего интерфейса криптопровайдера "КриптоПро CSP".

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


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

Данный раздел содержит определения идентификаторов и параметров, используемых в криптопровайдере "КриптоПро CSP".

  • Идентификаторы алгоритмов криптопровайдера
  • Режимы шифрования
  • Параметры криптопровайдера
  • Параметры дополнительных ключевых блобов
  • Дополнительные параметры объекта хеширования
  • Дополнительные параметры ключей
  • Групповые идентификаторы криптографических параметров алгоритмов
  • Идентификаторы криптографических параметров алгоритмов
  • Имя контейнера
  • Возвращение данных неопределенной длины


Крипто-Про CSP

Идентификатор | Описание идентификатора
CALG_GR3411 | Идентификатор алгоритма хеширования по ГОСТ Р 34.11-94.
CALG_G28147_MAC | Идентификатор алгоритма имитозащиты по ГОСТ 28147-89.
CALG_G28147_IMIT | То же самое, что и CALG_G28147_MAC (устаревшая версия).
CALG_GR3410 | Идентификатор алгоритма ЭЦП по ГОСТ Р 34.10-94.
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-89.
CALG_TLS1_MASTER_HASH | Идентификатор алгоритма выработки объекта MASTER_HASH протокола TLS 1.0.
CALG_TLS1_MAC_KEY | Идентификатор алгоритма выработки ключа имитозащиты протокола TLS 1.0.
CALG_TLS1_ENC_KEY | Идентификатор алгоритма выработки ключа шифрования протокола TLS 1.0.
CALG_PRO_DIVERS | Идентификатор алгоритма КриптоПро диверсификации ключа.
CALG_RIC_DIVERS | Идентификатор алгоритма РИК диверсификации ключа.


Крипто-Про CSP

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


Крипто-Про CSP

Параметр | Значение параметра
PP_ENUMOIDS_EX | Получает перечень идентификаторов объектов, используемых в криптопровайдере
PP_HASHOID | Получает и/или устанавливает заданный в контейнере OID узла замены функции хеширования ГОСТ Р 34.11-94 для наследования криптографическими объектами
PP_CIPHEROID | Получает и/или устанавливает заданный в контейнере OID узла замены алгоритма шифрования ГОСТ 28147-89 для наследования криптографическими объектами
PP_SIGNATUREOID | Получает и/или устанавливает заданный в контейнере OID параметров цифровой подписи для наследования криптографическими объектами
PP_DHOID | Получает и/или устанавливает заданный в контейнере OID параметров алгоритма Диффи-Хеллмана для наследования криптографическими объектами
PP_CHECKPUBLIC | Флаг контроля открытого ключа. Если флаг установлен, осуществляется проверка алгебраических свойств открытого ключа
PP_RANDOM | Получает и/или устанавливает блоб типа SIMPLEBLOB для инициализации ДСЧ в драйвере шифрования
PP_DRVCONTAINER | Получает указатель (handle) контейнера в драйвере
PP_MUTEX_ARG | Инициализирует синхронизацию потоков криптопровайдера в драйверном исполнении
PP_ENUM_HASHOID | Получает перечень идентификаторов криптографических объектов, связанных с функцией хеширования
PP_ENUM_CIPHEROID | Получает перечень идентификаторов криптографических объектов, связанных с функцией шифрования
PP_ENUM_SIGNATUREOID | Получает перечень идентификаторов криптографических объектов, связанных с функцией цифровой подписи
PP_ENUM_DHOID | Получает перечень идентификаторов криптографических объектов, связанных с алгоритмом Диффи-Хеллмана


Крипто-Про CSP

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


Крипто-Про CSP

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


Крипто-Про CSP

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


Крипто-Про CSP

Параметр | Индекс | Значение параметра
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" | Подпись содержимого сервера Интернет


Крипто-Про CSP

Параметр | Индекс | Значение параметра
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.


Крипто-Про CSP

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

Возможные значения имени контейнера:

Значение | Описание
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
DS9097E_[COM], DS9097U_[COM], DS1410E_[LPT] | считыватель Touch-Memory, где [COM] ([LPT]) имя COM (LPT) порта, например для считывателя Touch-Memory DS9097E посоединенного ко второму COM порту его имя будет DS9097E_COM1
ACCORD | считыватель Touch-Memory через ACCORD
SABLE | считыватель Touch-Memory через Соболь
REGISTRY | считыватель ключей из реестра.
HDIMAGE | считыватель ключей с диска.
[PCSC считыватель] | считыватель смарт-карт через интерфейс PCSC, где [PCSC считыватель] имя считывателя так как он зарегистрирован, например для первого зарегистрированного считывателя GCR410 имя будет "GEMPLUS GCR410P 0"

Поддерживаемые носители

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

Вид уникального номера

Вид уникального номера (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-ричных цифр уникального номера электронного ключа
HDIMAGE | не поддерживается | не поддерживается
реестр | не поддерживается | не поддерживается

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

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

См. также:

CPAcquireContext() ,CPGetProvParam() ,CPSetProvParam() ,CPAcquireContext в MS CSP World Wide Web link ,CPGetProvParam в MS CSP World Wide Web link ,CPSetProvParam в MS CSP World Wide Web link ,CryptAcquireContext в MS CryptoAPI 2.0 World Wide Web link ,CryptGetProvParam в MS CryptoAPI 2.0 World Wide Web link ,CryptSetProvParam в MS CryptoAPI 2.0 World Wide Web link


Крипто-Про CSP

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

Многие функции криптопровайдера и 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, так как для определения размера сообщения производится его полное формирование, включая генерацию сеансовых ключей. Для приложений, в которых критерий производительности является определяющим, можно рекомендовать заранее резервировать буфер для выходных данных определенной длины и обрабатывать код возврата функции.

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

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

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

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

 //--------------------------------------------------------------------
 // Функция SomeFunction (из предыдущего примера) вызывается приложением
 // в цикле. Размер буфера для выходных данных устанавливается
 // значением 50 байт.

 //--------------------------------------------------------------------
 // Определение переменных функции SomeFunction.

 PCCRL_CONTEXT pCrlContext; // Инициализируется в другом месте.
 DWORD dwPropId;            // Инициализируется в другом месте.

 //--------------------------------------------------------------------
 // Изначально под буфер выделяется 50 байт. Затем этот буфер используется
 // при вызове функции SomeFunction, которая в большинстве случаев
 // осуществляет обработку и вывод некоторых желаемых данных.
 // Даже если для выходных данных требуется больше 50 байт, изначально
 // выделяется именно 50 байт. В этом случае первый вызов функции
 // будет неудачным, но возвращенное им значение cbData будет использоваться
 // для выделения большей памяти под буфер. Таким образом второй вызов
 // функции SomeFunction будет использовать буфер большей длины.

 //--------------------------------------------------------------------
 //   Считается, что переменные pCrlContext и dwPropId были определены
 //   и проинициализированы в другом месте.

 DWORD dwTries = 0; // количество вызовов функции
 BOOL fMore=TRUE;   // флаг, определяющий, следует ли осуществлять вызов
                      // функции
 DWORD cbData = 50;
 BYTE  *pbData;

 //--------------------------------------------------------------------
 //  Начало обработки. Этот цикл выполняется не более двух раз.

 while (fMore)
 {
 if (pbData = (BYTE *)malloc(cbData))
 {
      printf("Memory has been allocated.\n");
 }
 else
 {
      HandleError("Memory allocation error.");
 }
 //--------------------------------------------------------------------
 //  Память выделена. Вызов функции.

    if (SomeFunction(pCrlContext, dwPropId, pbData, &cbData))
        // Вызов функции был успешным. Выход из цикла.
    {
             printf("The function succeeded. Exit the loop.\n");
             fMore=FALSE;
    }
    else
    {
          // Вызов функции был неудачным. Освобождение выделенной памяти.
           free(pbData);  // Освобождение буфера в случае неудачного исхода.

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

          if(GetLastError() != ERROR_MORE_DATA )
          {
               HandleError("General function failure.");
          }
          // Если ошибка заключается в том, что под буфер выделено
          // недостаточное количество памяти, то осуществляется вторая,
            // но не третья попытка.
          if( ++dwtries > 1 )
           {
               HandleError("Function call failed twice ");
           }
 }  // Конец цикла

 //--------------------------------------------------------------------
 //  Если цикл завершился, то вызов функции был успешным либо во время
 //  первой, либо во время второй итерации цикла. В обоих случаях в процессе
 //  выполнения значение cbData заменяется фактическим размером
 //  возвращаемых данных. Для обработки байт в буфере, на который указывает
 //  pbData, следует пользоваться этим размером.

 //--------------------------------------------------------------------
 //  В данном месте осуществляется обработка pbData.

 //--------------------------------------------------------------------
 //  Очистка после обработки.

 free(pbData); // Освобождение буфера данных
               // после того, как данные были обработаны.

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

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

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

 #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()
 {
 //--------------------------------------------------------------------
 // Определение переменных функции SomeFunction.

 PCCRL_CONTEXT pCrlContext; // Инициализируется в другом месте.
 DWORD dwPropId;            // Инициализируется в другом месте.
 DWORD cbData;
 BYTE  *pbData;

 //--------------------------------------------------------------------
 // Вызов функции SomeFunction для определения необходимого размера
 // буфера pbData. Это значение устанавливается в cbData.

 if(SomeFunction(
      pCrlContext,
      dwPropId,
      NULL,
      &cbData))
 {
        printf("The function succeeded.\n");
 }
 else
 {
 // Вызов функции завершился неудачей. Обработка ошибки.
        HandleError("Function call failed.");
 }

 //--------------------------------------------------------------------
 // Вызов функции был успешным. На данный момент cbData содержит
 // необходимый размер буфера в байтах.

 //--------------------------------------------------------------------
 // Выделение памяти в соответствии с размером сообщения.

 if(pbData = (BYTE*)malloc(cbData))
 {
    printf("Memory has been allocated.\n");
 }
 else
 {
    // Приложение потерпело неудачу. Вывод сообщения об ошибке и
    // выход из программы.
    HandleError("Malloc operation failed. ");
 }

 //--------------------------------------------------------------------
 // Память под буфер была выделена. Вызов функции SomeFunction
 // для заполнения буфера данными.

 if(SomeFunction(
       pCrlContext,
       dwPropId,
       pbData,
       &cbData))
 {
        printf("The function succeeded.\n");
 }
 else
 {
    // Повторный вызов функции завершился неудачей. Обработка ошибки.
    HandleError("The second call to the function failed.");
 }
 //*******************************************************************
 // Функия выполнилась успешно. На данный момент данные находятся в
 // буфере, на который указывает pbData. Необходимо помнить, что
 // в процессе выполнения значение cbData заменяется фактическим размером
 // возвращаемых данных. Для обработки байт в буфере, на который указывает
 // pbData, следует пользоваться этим размером.

 } // Конец main

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

 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);
 }


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

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

Функции | Описание
CPAcquireContext | Функция CPAcquireContext() используется для создания дескриптора криптопровайдера с именем ключевого контейнера, определённым параметром pszContainer .
CPReleaseContext | Функция CPReleaseContext() используется для удаления дескриптора криптопровайдера, созданного CPAcquireContext().
CPGetProvParam | Функция CPGetProvParam() получает параметры криптопровайдера.
CPSetProvParam | Функция CPSetProvParam() устанавливает параметры криптопровайдера.


CPAcquireContext

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

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

Аргументы

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

Возвращаемые значения:

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

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Файл описания: Прототип описан в файле wincsp.h.
Ядро Windows NT: IRQL < DISPATCH_LEVEL
Ядро ОС: При использовании в ядре ОС CPAcquireContext допустимо вызывать только с флагами CRYPT_VERIFYCONTEXT|CRYPT_SILENT.

См. также:

CPReleaseContext() ,CPAcquireContext в MS CSP World Wide Web link ,CryptAcquireContext в MS CryptoAPI 2.0 World Wide Web link ,CryptSetProvParam в MS CryptoAPI 2.0 World Wide Web link


CPReleaseContext

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

BOOL WINAPI CPReleaseContext(
  HCRYPTPROV hProv,
  DWORD dwFlags
);

Аргументы

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

Возвращаемые значения:

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

Примечания

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

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Файл описания: Прототип описан в файле wincsp.h.
Ядро Windows NT: IRQL < DISPATCH_LEVEL

См. также:

CPAcquireContext() ,CPReleaseContext в MS CSP World Wide Web link ,CryptReleaseContext в MS CryptoAPI 2.0 World Wide Web link


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). Строка, заканчивающаяся нулем, содержащая имя текущего ключевого контейнера. Подробнее см. Дополнительные параметры и определения .
PP_UNIQUE_CONTAINER | Уникальное имя ключевого контейнера, которое включает тип ключевого носителя и может иметь вид: MEDIA\FOLDER, MEDIA\UNIQUE\FOLDER или MEDIA\UNIQUE. Строка, заканчивающаяся нулем, содержащая имя текущего ключевого контейнера. Подробнее см. Дополнительные параметры и определения .
PP_ENUMALGS | Поддерживаемые алгоритмы. Подробнее см. CryptGetProvParam в MS CryptoAPI 2.0 World Wide Web link .
PP_ENUMALGS_EX | Поддерживаемые алгоритмы. Подробнее см. CryptGetProvParam в MS CryptoAPI 2.0 World Wide Web link .
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 | Тип ключа (всегда либо AT_KEYEXCHANGE, либо AT_SIGNATURE). Возвращается в виде переменной типа DWORD.
PP_KEYX_KEYSIZE_INC | Размер модуля открытого ключа обмена AT_KEYEXCHANGE. Возвращается в виде переменной типа DWORD. Размер модуля ключа равен 1024 (для ГОСТ Р 34.10-94) либо 512 (для ГОСТ Р 34.10-2001).
PP_SIG_KEYSIZE_INC | Размер модуля открытого ключа ЭЦП AT_SIGNATURE. Возвращается в виде переменной типа DWORD. Размер модуля ключа равен 1024 (для ГОСТ Р 34.10-94) либо 512 (для ГОСТ Р 34.10-2001).
PP_KEYSET_SEC_DESCR | Возвращает дескриптор безопасности раздела реестра Windows, где хранятся ключи пользователя. Функция не поддерживается. Возвращает FALSE.
PP_ENUMOIDS_EX | Поддерживаемые идентификаторы криптографических параметров алгоритмов. Перечисляются строковые величины - OID криптографических параметров алгоритмов.
PP_HASHOID | OID текущих параметров алгоритма функции хеширования.
PP_SIGNATUREOID | OID текущих параметров алгоритма подписи.
PP_DHOID | OID текущих параметров алгоритма Диффи-Хеллмана.
PP_CIPHEROID | OID текущих параметров алгоритма шифрования.
PP_CHECKPUBLIC | Передаёт в pbData значение флага проверки открытого ключа.
PP_RANDOM | Возвращает в pbData последовательность случайных чисел для установки программного ДСЧ криптопровайдера уровня ядра ОС. Если контекст криптопровайдера hProv открыт в режиме CRYPT_VERIFYCONTEXT, то предварительно будут получены случайные числа с физического или клавиатурного ДСЧ. См. описание параметра PP_USE_HARDWARE_RNG CPSetProvParam().
PP_LAST_ERROR | Код последней ошибки криптопровайдера. В pbData буфер будет помещена величина DWORD - код последней ошибки, возвращённой одной из функций криптопровайдера. Коды ошибок даны в файле WinCryptEx.h.
PP_MUTEX_ARG | Только для использования в ядре ОС и в UNIX. Возвращает значение последнего аргумента функции mutex_init (указатель на обработчик прерывания) для всех mutex, используемых при работе CSP.
PP_DRVCONTAINER | Получает указатель (handle) контейнера в драйвере.
PP_ENUM_HASHOID | Получает перечень идентификаторов криптографических объектов, связанных с функцией хеширования.
PP_ENUM_CIPHEROID | Получает перечень идентификаторов криптографических объектов, связанных с функцией шифрования.
PP_ENUM_SIGNATUREOID | Получает перечень идентификаторов криптографических объектов, связанных с функцией цифровой подписи.
PP_ENUM_DHOID | Получает перечень идентификаторов криптографических объектов, связанных с алгоритмом Диффи-Хеллмана.
PP_HCRYPTPROV | Загружает контейнер в память и возвращает DWORD идентифицирующий контейнер.
PP_SELECT_CONTAINER | Выводит диалоговое окно выбора контейнера и возвращает имя выбраного пользователем контейнера. Если dwFlags & CRYPT_FQCN , то имя контейнера возвращается в формате FQCN (см. PP_FQCN). Имя контейнера возвращается в текущей кодировке. Возвращаемая строка заканчивается нулем.
PP_FQCN | Возвращает FQCN (Fully Qualified Container Name) конетйнера: \\.\<Reader>\<Name> , где <Reader> имя считывателя, на котором находится контейнер, <Name> имя контейнера в текущей кодировке. Возвращаемая строка заканчивается нулем.
PP_ENUMREADERS | Имя одного из считывателей ключевых контейнеров, которые могут быть использованы криптопровайдером, возвращаемое в форме строки, заканчивающейся нулем. Прикладные программы могут вызывать функцию с данным параметром последоватьльно для перечисления всех ключевых контейнеров, поддерживаемых криптопровайдером. Эта функция не является многопоточной, и поэтому при использовании ее в многопоточном контексте есть вероятность, что не все поддерживаемые считыватели будут перечислены.
PP_INFO | Вовращает структуру, содержащую значение таймера криптографического модуля, для недрайвера дополнительно содержит количество ДСРФ, свободное место на файловой системе /var, количество попыток выпусть ключ УЛ, количество успешных смен карт канала "К", количество карт канала выпущенных при последней смене, количество операций подписи
PP_PIN_INFO | Возвращает структуру пароля для текущего контейнера в виде структуры #CRYPT_PIN_INFO
PP_PASSWD_TERM | Получает термин пароль ("пароль" / "pin-code") для текущего носителя. Возвращаемое значение содержит строку текущей кодировке заканчивающуюся нулем.
PP_SAME_MEDIA | Функция проверяет наличие носителя, соответствующего данному контейнеру, в считывателе.
PP_VERSION_TIMESTAMP | Получение даты и времени завершения компиляции в формате "day month year" "hh:mm:ss".
PP_SECURITY_LEVEL | Возвращает DWORD уровня сертификации данного криптографического модуля KC1: 1, KC2: 2, KC3: 3, KB1: 4, KB2: 5, KA1: 6
PP_FAST_CODE

Параметр предназначен для определения, какой код - быстрый или медленный - используется в провайдере на компьютерах, оснащенных процессором Intel Pentium 4. В pbData структура типа CSP_FAST_CODE . Параметр dwFlags должен содержать хотя бы один из флагов, указанных ниже.
Флаги для определения списка проверяемых функций.
CRYPT_FAST_CODE_ALL_KERNEL_FUNCTIONS - запрос кода функций провайдера уровня ядра ОС.
CRYPT_FAST_CODE_ALL_USER_FUNCTIONS - запрос кода функций провайдера уровня пользователя.
CRYPT_FAST_CODE_ALL_FUNCTIONS - запрос кода всех функций провайдера.
CRYPT_FAST_CODE_GET_SETFN - запроса результата работы функции определения процессора.

PP_ENUM_CONTAINER_EXTENSION | Имя одного из расширений ключевого контейнера, возвращаемое в форме структуры #CONTAINER_EXTENSION строки. Прикладные программы могут вызывать функцию с данным параметром последоватьльно для перечисления всех расширений ключевого контейнера. Эта функция не является многопоточной, и поэтому при использовании ее в многопоточном контексте есть вероятность, что не все поддерживаемые считыватели будут перечислены.
pbData
[out] Указатель на буфер, содержащий данные параметра. Функция копирует соответствующие параметру данные в буфер. Формат этих данных зависит от значения dwParam . Если аргумент функции - NULL, то данные не копируются. Требуемый размер буфера в байтах возвращается в pdwDataLen . Подробнее см. Возвращение данных неопределенной длины. Как отмечено в CryptGetProvParam в MS CryptoAPI 2.0 World Wide Web link , когда читается один из параметров перечисления, возвращенное в pdwDataLen значение будет равно размеру самого большого элемента в списке перечисления.
pdwDataLen
[in/out] Указатель на буфер, содержащий длину данных параметра. При вызове функции указанный аргумент содержит размер передаваемого буфера pbData в байтах. После возврата из неё 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_UNIQUE | Используется совместно с параметром PP_ENUMCONTAINERS. При использовании этого флага первыми по приоритету перед обычными именами возвращаются уникальные имена контейнеров. Если под уникальный номер выделено достаточно памяти, после уникального номера копируется обычное имя контейнера.
CRYPT_MACHINE_KEYSET | Используется совместно с параметром PP_ENUMCONTAINERS для перечисления ключевых контейнеров в разделе 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-кода был заблокирован смарт-картой, т.к. исчерпалось количество попыток, разрешенное картой для ввода.
NTE_SILENT_CONTEXT | Операция не может быть выполнена без пользовательского интерфейса.
SCARD_W_REMOVED_CARD | Носитель контейнера был удален из считывателя.

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Файл описания: Прототип описан в файле wincsp.h.
Ядро Windows NT: IRQL < DISPATCH_LEVEL

См. также:

CPAcquireContext() ,CPSetProvParam() ,CPGetProvParam в MS CSP World Wide Web link ,CryptGetProvParam в MS CryptoAPI 2.0 World Wide Web link


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 . Функция не поддерживается. Возвращает TRUE.
PP_HASHOID | Устанавливает идентификатор алгоритма функции хеширования.
PP_CIPHEROID | Устанавливает идентификатор алгоритма шифрования.
PP_SIGNATUREOID | Устанавливает идентификатор алгоритма подписи.
PP_DHOID | Устанавливает идентификатор алгоритма Диффи-Хеллмана.
PP_KEYEXCHANGE_PIN Задаёт пароль (PIN) для доступа к ключам AT_SIGNATURE и AT_KEYEXCHANGE. Если пароль не задан этой функцией или задан этой функцией неверно, то он запрашивается у пользователя посредством UI перед первым обращением к носителю (если не был установлен флаг CRYPT_SILENT, см. CPAcquireContext()). Если pbData - NULL, то существующий пароль для этого контейнера забывается и для доступа к ключу потребуется повторный ввод пароля.

В КриптоПро CSP используется единый пароль (PIN) для доступа к ключам AT_SIGNATURE и AT_KEYEXCHANGE. Параметры PP_KEYEXCHANGE_PIN и PP_SIGNATURE_PIN эквивалентны.
PP_SIGNATURE_PIN Задаёт пароль (PIN) для доступа к ключам AT_SIGNATURE и AT_KEYEXCHANGE. Если пароль не задан этой функцией или задан этой функцией неверно, то он запрашивается у пользователя посредством UI перед первым обращением к носителю (если не был установлен флаг CRYPT_SILENT, см. CPAcquireContext()). Если pbData - NULL, то запомненный ранее пароль для этого контейнера забывается и для доступа к ключу потребуется повторный ввод пароля.

В КриптоПро CSP используется единый пароль (PIN) для доступа к ключам AT_SIGNATURE и AT_KEYEXCHANGE. Параметры PP_KEYEXCHANGE_PIN и PP_SIGNATURE_PIN эквивалентны.
PP_CHANGE_PIN | Задаёт новый пароль для контейнера hProv.
PP_SET_PIN | Устанавливает пароль на контейнер hProv в случае зашифрования его на другом контейнере или на нескольких контейнерах для схемы n из k. Этот пароль будет использован при последующем открытии контейнера hProv на чтение. Если контейнер hProv был создан при помощи функции CPAcquireContext() с флагом CRYPT_NEWKEYSET, то пароль, устанавливаемый на него, также будет установлен на доступ к ключу этого контейнера. Если функция CPSetProvParam() не вызывалась, то при доступе к ключу выдается UI (если не был установлен флаг CRYPT_SILENT, см. CPAcquireContext()). При открытии контейнера в SILENT-режиме возвращается ошибка.
PP_USE_HARDWARE_RNG Иницирует добавление к ДСЧ контекста криптопровайдера hProv значения с физического или БиоДСЧ. В случае, если в данной системе поддерживается только БиоДСЧ, то выдаётся UI для ввода событий мыши и/или клавиатуры (если не был установлен флаг CRYPT_SILENT, см. CPAcquireContext()).

При вызове функции CPSetProvParam() с параметром PP_USE_HARDWARE_RNG параметр pbData не используется.

Обычно, при отсуствии в системе физического ДСЧ, данные с БиоДСЧ добавляются в обязательном порядке к контексту криптопровайдера (в контейнер ключевой информации) только при создании постоянных ключей AT_KEYEXCHANGE или AT_SIGNAUTURE функцией CPGenKey().
PP_RANDOM | Устанавливает в pbData ключевой блоб типа SIMPLEBLOB (см. CRYPT_SIMPLEBLOB ), содержащий последовательность случайных чисел, необходимую для установки программного ДСЧ уровня ядра ОС. См. описание параметра PP_RANDOM функции CPGetProvParam().
PP_CHECKPUBLIC | Получает из pbData значение флага проверки открытого ключа. Если значение pbData равно 1, при импорте открытого ключа проверяется его корректность, если 0, проверка производится, если флаг установлен по параметру PP_ADMIN_CHECKPUBLIC. Открытый ключ, соответствующий ГОСТ 34.10-2001, проверяется всегда.
PP_ADMIN_CHECKPUBLIC | Получает из pbData значение флага проверки открытого ключа и устанавливает его в реестр. Если значение установленного в реестре флага равно 1, при импорте открытого ключа проверяется его корректность независимо от установки пользователя по параметру PP_CHECKPUBLIC, если установленного в реестре флага равно 0, проверка производится в зависимости от установки по параметру PP_CHECKPUBLIC. Открытый ключ, соответствующий ГОСТ 34.10-2001, проверяется всегда.
PP_MUTEX_ARG | Только для использования в ядре ОС и в UNIX. Устанавливает значение последнего аргумента функции mutex_init (указатель на обработчик прерывания) для всех mutex, используемых при работе CSP. Этот параметр необходимо установить до первого вызова CPAcquireContext(). Значение hProv при этом должно быть установлено в NULL.
PP_FAST_CODE | Параметр предназначен для управления подключением быстрых функций на компьютерах, оснащенных процессором Intel Pentium 4. Применяется для установки функций захвата и освобождения регистров расширений MMX, SSE2. Определен только в KC1. В pbData структура типа CSP_FAST_CODE .
PP_NK_SYNC | Производит запись одной из частей контейнера разделенного по схеме K из N. В качестве pbData должен быть передан DWORD полученный функцией GetProvParam с параметром PP_HCRYPTPROV. Функция используется для содания контейнера разделеноого на части без выдачи окон.
PP_DELETE_KEYSET | Удаляет текущий контейнер с носителя. Функция используется для удаления контейнеров, требующих для очистки пароля, в SILENT режиме. Контейнер после успешного завершения данной операции больше не может быть использован ни в одной функции провайдера, исключая CPReleaseContext (CryptReleaseContext).
PP_DELETE_SAVED_PASSWD | Удаляет сохраненные на диске пароли для заданного параметром контейнера или для всех контейнеров. Если в качестве pbData передан NULL, то функция производит удаление всех сохраненных паролей. Если в качестве pbData передано имя контейнера, то функция удаляет сохраненный пароль для этого контейнера. Имя контейнера должно быть задано в текущей кодировке и заканчиваться нулем. При удалении сохраненного пароля так же производится удаление связки между именем контейнера и уникальным именем контейнера.
PP_CONTAINER_EXTENSION | Устанавливает extension для контейнера. Если extension уже был задан в контейнере, то функция заменяет этот extension в контейнере. В качестве pbData должен быть передан etxnsion в формате #CERT_EXTENSION.
PP_CONTAINER_EXTENSION_DEL | Удаляет из контейнера extension, заданный строковым представлением OID.
PP_CONTAINER_DEFAULT | Устанавливает текущий контейнер - контейнером по умолчанию на текущем носителе.
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 | Недостаточно места на носителе для сохранения информации.
NTE_SILENT_CONTEXT | Операция не может быть выполнена без пользовательского интерфейса.
SCARD_W_REMOVED_CARD | Носитель контейнера был удален из считывателя

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Файл описания: Прототип описан в файле wincsp.h.
Ядро Windows NT: IRQL < DISPATCH_LEVEL

См. также:

CPAcquireContext() ,CPGetProvParam() ,CPSetProvParam в MS CSP World Wide Web link ,CryptSetProvParam в MS CryptoAPI 2.0 World Wide Web link


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

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

Функции | Описание
CPGenKey | Функция CPGenKey() генерит случайные криптографические ключи или ключевую пару (закрытый/открытый ключи).
CPDestroyKey | Функция CPDestroyKey() удаляет ключ, передаваемый через параметр hKey . После удаления ключ (дескриптор ключа) не может использоваться.
CPDeriveKey | Функция CPDeriveKey() производит криптографические ключи сессии на основе значения хеш-функции, вычисленной по другим ключам, паролям или любым другим данным пользователя.
CPDuplicateKey | Функция CPDuplicateKey() создает точную копию заданного ключа, включая все его переменные, определяющие внутреннее состояние ключа (например, вектор IV).
CPExportKey | Функция CPExportKey() используется для экспорта криптографических ключей из ключевого контейнера криптопровайдера, сохраняя их в защищённом виде.
CPGenRandom | Функция CPGenRandom() заполняет буфер случайными байтами.
CPGetKeyParam | Функция CPGetKeyParam() возвращает параметры ключа.
CPGetUserKey | Функция CPGetUserKey() возвращает дескриптор одной из долговременных ключевых пар в ключевом контейнере.
CPImportKey | Функция CPImportKey() используется для импорта криптографического ключа из ключевого блоба в контейнер криптопровайдера.
CPSetKeyParam | Функция CPSetKeyParam() устанавливает параметры ключа.


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, сохраняемая в ключевом контейнере. Предназначена для ЭЦП. Используется в криптопровайдере "КриптоПро ГОСТ Р 34.10-94 CSP" и эквивалентна AT_SIGNATURE.
    CALG_GR3410EL | Производится ключевая пара согласно ГОСТ Р 34.10-2001, сохраняемая в ключевом контейнере. Предназначена для ЭЦП.Используется в криптопровайдере "КриптоПро ГОСТ Р 34.10-2001 CSP" и эквивалентна AT_SIGNATURE.
dwFlags
[in] Флаги определяют признаки производимого ключа. Размеры ключей подписи и ключей обмена могут быть установлены при выработке ключа. Размер ключа устанавливается в старших 16 битах параметра dwFlags, эти 16 бит представляют размер модуля в битах. Размер модуля ключа равен 1024 (для ГОСТ Р 34.10-94) либо 512 (для ГОСТ Р 34.10-2001). В настоящее время определенны следующие флаги:
Значение dwFlags | Описание
CRYPT_EXPORTABLE Если этот флаг установлен, то произведённый ключ может быть передан из криптопровайдера в ключевой блоб через функцию CPExportKey(). Если этот флаг не установлен, ключ не будет экспортируемым и будет доступен только в пределах текущей сессии приложению, которое создало этот ключ. Действие этого флага не распространяются на открытые ключи ключевых пар.

Экспорт закрытых ключей ключевых пар возможен только на эфемерных ключах и ключах с алгоритмом CALG_PRO_EXPORT.
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 | Ошибка при считывании данных из системного реестра. см. Дополнительные параметры и определения .
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 | Недостаточно места на носителе для сохранения информации.
NTE_SILENT_CONTEXT | Операция не может быть выполнена без пользовательского интерфейса.
SCARD_W_REMOVED_CARD | Носитель контейнера был удален из считывателя

Примечания

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

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

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

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

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Файл описания: Прототип описан в файле wincsp.h.
Ядро Windows NT: IRQL < DISPATCH_LEVEL
Ядро ОС: При использовании в ядре ОС CPGenKey допустимо вызывать только для производства ключей сессии.

См. также:

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


CPDestroyKey

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

BOOL WINAPI CPDestroyKey(
  HCRYPTPROV hProv,
  HCRYPTKEY hKey
);

Аргументы

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

Возвращаемые значения:

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

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Файл описания: Прототип описан в файле wincsp.h.
Ядро Windows NT: IRQL < DISPATCH_LEVEL

См. также:

CPDeriveKey() ,CPGenKey() ,CPGetUserKey() ,CPDestroyKey в MS CSP World Wide Web link ,CryptDestroyKey в MS CryptoAPI 2.0 World Wide Web link


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 | Ошибка при считывании данных из системного реестра. см. Дополнительные параметры и определения .

Примечания

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

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Файл описания: Прототип описан в файле wincsp.h.
Ядро Windows NT: IRQL < DISPATCH_LEVEL

См. также:

CPDestroyKey() ,CPGenKey() ,CPDeriveKey в MS CSP World Wide Web link ,CryptDeriveKey в MS CryptoAPI 2.0 World Wide Web link


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 (см. CryptGetProvParam в MS CryptoAPI 2.0 World Wide Web link ).
pdwReserved
[in] Параметр зарезервирован для будущего использования и должен быть NULL.
dwFlags
[in] Параметр зарезервирован для будущего использования и должен быть нулевым.
phKey
[out] Адрес, по которому функция возвращает дескриптор скопированного ключа.

Возвращаемые значения:

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

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Файл описания: Прототип описан в файле wincsp.h.
Ядро Windows NT: IRQL < DISPATCH_LEVEL

См. также:

CPDestroyKey() ,CPDuplicateKey в MS CSP World Wide Web link ,CryptDuplicateKey в MS CryptoAPI 2.0 World Wide Web link


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] Значения флагов. Параметр зарезервирован для будущего использования и должен быть нулевым.
pbData
[in] Указатель на буфер данных, в который функция копирует ключевой блоб. Если значение этого параметра NULL, функция устанавливает по адресу pdwDataLen значение необходимой длины буфера и возвращает TRUE.
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 | Ошибка при считывании данных из системного реестра. см. Дополнительные параметры и определения .
SCARD_W_CANCELLED_BY_USER | Пользователь прервал операцию.

Примечания

Обычно для согласования (экспорта/импорта) сессионного ключа применяют алгоритм Диффи-Хеллмана. В этом случае ключ парной связи (ключ экспорта/импорта сессионного ключа) порождается операцией импорта (см. 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 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Файл описания: Прототип описан в файле wincsp.h.
Ядро Windows NT: IRQL < DISPATCH_LEVEL
Ядро ОС: Поддерживается только типы SIMPLEBLOB и DIVERSKEYBLOB.

См. также:

CPImportKey() ,CPExportKey в MS CSP World Wide Web link ,CryptExportKey в MS CryptoAPI 2.0 World Wide Web link


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^(-16).
NTE_FAIL RPE_FAIL_TESTBUFFER | Неудовлетворительная постоянно действующая статистика датчика случайных чисел. Эта ошибка носит вероятностный характер. Для корректно работающей программы вероятность возникновения ошибки не превышает 10^(-16).
NTE_KEYSET_ENTRY_BAD | Данные неверно считаны из системного реестра.

Примечания

Функция CPGenRandom() получает случайные числа с програмного ДСЧ контекста криптопровайдера hProv , который инициализируется при выполнении функции CPAcquireContext() c накопленного в контейнере ключевого носителя состояния ДСЧ и установленного в системе физического ДСЧ.

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

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Файл описания: Прототип описан в файле wincsp.h.
Ядро Windows NT: IRQL < DISPATCH_LEVEL
Ядро ОС: Перед получением случайных чисел требуется инициализировать ДСЧ контекста криптопровайдера hProv с помощью параметра PP_RANDOM функции CPSetProvParam().

См. также:

CPSetProvParam() ,CPGenRandom в MS CSP World Wide Web link ,CryptGenRandom в MS CryptoAPI 2.0 World Wide Web link


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_CERTIFICATE | Получение сертификата из контейнера (из носителя).
KP_MODE Режим алгоритма шифрования. Возвращается в виде переменной типа DWORD. Используются режимы шифрования:
  • CRYPT_MODE_ECB - блочный шифр простой замены ГОСТ 28147-89;
  • CRYPT_MODE_CNT - шифрование гаммированием ГОСТ 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. Для ключей шифрования в параметре pbData возвращается длина ключа, для ключевых пар возвращается длина открытого ключа.
KP_BLOCKLEN | Длина блока шифрования, обрабатываемого криптопровайдером. Возвращается в виде переменной типа DWORD. В случае сессионного ключа если для ключа установлен режим блочного шифрованя (CRYPT_MODE_ЕСB, CRYPT_MODE_CBС), в параметре pbData устанавливается размер блока алгоритма ГОСТ 28147-89, если установлен режим поточного шифрования (CRYPT_MODE_CNT, CRYPT_MODE_CFB), в параметре pbData устанавливается значение оптимального с точки зрения скорости шифрования размера блока, принимаемого от приложения (в настоящее время 8Кбит). В случае ключевой пары в параметре pbData устанавливается число бит модуля q как для ключей на экспонециальной логике (ГОСТ 34.10-94), так и для ключей на базе эллиптической кривой (ГОСТ 34.10-2001).
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] Значения флагов. Параметр зарезервирован для будущего использования и должен быть нулевым.

Возвращаемые значения:

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

Примечания

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

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Файл описания: Прототип описан в файле wincsp.h.
Ядро Windows NT: IRQL < DISPATCH_LEVEL

См. также:

CPSetKeyParam() ,CPGetKeyParam в MS CSP World Wide Web link ,CryptGetKeyParam в MS CryptoAPI 2.0 World Wide Web link


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-кода был заблокирован смарт-картой, т.к. исчерпалось количество попыток разрешенное картой для ввода.
NTE_SILENT_CONTEXT | Операция не может быть выполнена без пользовательского интерфейса.
SCARD_W_REMOVED_CARD | Носитель контейнера был удален из считывателя

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Файл описания: Прототип описан в файле wincsp.h.
Ядро Windows NT: IRQL < DISPATCH_LEVEL

См. также:

CPExportKey() ,CPGenKey() ,CPGetUserKey в MS CSP World Wide Web link ,CryptGetUserKey в MS CryptoAPI 2.0 World Wide Web link


CPImportKey

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

BOOL WINAPI CPImportKey(
  HCRYPTPROV hProv,
  WINCSP_CONST 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 в MS CryptoAPI 2.0 World Wide Web link с дескриптором ключа будут терпеть неудачу.
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 | Нарушение целостности ключей в ОЗУ. см. Дополнительные параметры и определения .
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 | Недостаточно места на носителе для сохранения информации.
NTE_SILENT_CONTEXT | Операция не может быть выполнена без пользовательского интерфейса.
SCARD_W_REMOVED_CARD | Носитель контейнера был удален из считывателя

Примечания

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

  • Импорт блоба открытого ключа отправителя на своей ключевой паре;
  • Импорт сессионого ключа на ключе парной связи.

      ...
      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 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Файл описания: Прототип описан в файле wincsp.h.
Ядро Windows NT: IRQL < DISPATCH_LEVEL
Ядро ОС: Поддерживается только типы SIMPLEBLOB и DIVERSKEYBLOB.

См. также:

CPExportKey() ,CPGenKey() ,CPImportKey в MS CSP World Wide Web link ,CryptImportKey в MS CryptoAPI 2.0 World Wide Web link


CPSetKeyParam

Функция CPSetKeyParam() устанавливает параметры ключа.

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_CERTIFICATE | Установка сертификата в контейнер (на носитель).
KP_PADDING Способ дополнения. Величина DWORD, содержащая метод дополнения, используемый шифром ключа, передаётся функции через буфер pbData. В настоящее время определены следующие способы дополнения:
  • PKCS5_PADDING - PKCS#5.(См ПРИМЕЧАНИЕ в данном разделе и ПРИМЕЧАНИЕ к CryptSetKeyParam в MS CryptoAPI 2.0 World Wide Web link )
  • ZERO_PADDING - дополнение нулевыми байтами,
  • RANDOM_PADDING - дополнение случайными байтами.
KP_MODE Режим шифра. Переменная типа DWORD. Передаётся функции через буфер pbData. В следующем списке приведены режимы шифрования, доступные в настоящее время:
  • CRYPT_MODE_ECB - блочный шифр простой замены ГОСТ 28147-89;
  • CRYPT_MODE_CNT - шифрование гаммированием ГОСТ 28147-89;
  • CRYPT_MODE_CFB - шифрование гаммированием с обратной связью ГОСТ 28147-89;
  • CRYPT_MODE_CBC - блочный шифр с обратной связью на базе ГОСТ 28147-89.
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] Значения флагов. Параметр зарезервирован для будущего использования и должен быть нулевым.

Возвращаемые значения:

При успешном завершении функция возвращает 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 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Файл описания: Прототип описан в файле wincsp.h.
Ядро Windows NT: IRQL < DISPATCH_LEVEL

См. также:

CPGenKey() ,CPGetKeyParam() ,CPSetKeyParam в MS CSP World Wide Web link ,CryptSetKeyParam в MS CryptoAPI 2.0 World Wide Web link


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

Функции шифрования/расшифрования данных предназначены для выполнения операций, шифрования и расшифрования данных.

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


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] Значения флагов. Параметр зарезервирован для будущего использования и должен быть нулевым.
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 | Нарушение целостности ключей в ОЗУ. см. Дополнительные параметры и определения .

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Файл описания: Прототип описан в файле wincsp.h.
Ядро Windows NT: IRQL < DISPATCH_LEVEL

См. также:

CPDecrypt() ,CPGenKey() ,CPEncrypt в MS CSP World Wide Web link ,CryptEncrypt в MS CryptoAPI 2.0 World Wide Web link


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] Значения флагов. Параметр зарезервирован для будущего использования и должен быть нулевым.
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 | Нарушение целостности ключей в ОЗУ. см. Дополнительные параметры и определения .

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Файл описания: Прототип описан в файле wincsp.h.
Ядро Windows NT: IRQL < DISPATCH_LEVEL

См. также:

CPEncrypt() ,CPGenKey() ,CPDecrypt в MS CSP World Wide Web link ,CryptDecrypt в MS CryptoAPI 2.0 World Wide Web link


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

Функции хеширования и ЭЦП предназначены для вычисления значения хеш функции и формирования/проверки ЭЦП данных.

Функции | Описание
CPCreateHash | Функция CPCreateHash() инициализирует дескриптор нового объекта функции хеширования потока данных.
CPDestroyHash | Функция CPDestroyHash() удаляет объект функции хеширования.
CPDuplicateHash | Функция CPDuplicateHash() создает точную копию объекта функции хеширования, включая все его переменные, определяющие внутреннее состояние объекта функции хеширования.
CPGetHashParam | Функция CPGetHashParam() возвращает параметры объекта функции хеширования и значение функции хеширования.
CPHashData | Функция CPHashData() передаёт данные указанному объекту функции хеширования.
CPHashSessionKey | Функция CPHashSessionKey() передаёт криптографический ключ указанному объекту функции хеширования. Это позволяет хешировать ключи сессии без передачи ключа приложению.
CPSetHashParam | Функция CPSetHashParam() устанавливает параметры объекта хеширования.
CPSignHash | Функция CPSignHash() возвращает значение электронной цифровой подписи от значения функции хеширования.
CPVerifySignature | Функция 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] Значения флагов. Параметр зарезервирован для будущего использования и должен быть нулевым.
phHash
[out] Адрес по которому функция копирует дескриптор нового объекта функции хеширования.

Возвращаемые значения:

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

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Файл описания: Прототип описан в файле wincsp.h.
Ядро Windows NT: IRQL < DISPATCH_LEVEL

См. также:

CPDestroyHash() ,CPHashData() ,CPCreateHash в MS CSP World Wide Web link ,CryptCreateHash в MS CryptoAPI 2.0 World Wide Web link


CPDestroyHash

Функция CPDestroyHash() удаляет объект функции хеширования.

BOOL WINAPI CPDestroyHash(
  HCRYPTPROV hProv,
  HCRYPTHASH hHash
);

Аргументы

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

Возвращаемые значения:

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

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Файл описания: Прототип описан в файле wincsp.h.
Ядро Windows NT: IRQL < DISPATCH_LEVEL

См. также:

CPCreateHash() ,CPDestroyHash в MS CSP World Wide Web link ,CryptDestroyHash в MS CryptoAPI 2.0 World Wide Web link


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] Парамустановленного в реестре флага равноетр зарезервирован для будущего использования и должен быть нулевым.
phHash
[out] Адрес,установленного в реестре флага равно по которому функция копирует дескриптор нового объекта функции хеширования.

Возвращаемые значения:

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

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Файл описания: Прототип описан в файле wincsp.h.
Ядро Windows NT: IRQL < DISPATCH_LEVEL

См. также:

CPDestroyHash() ,CPDuplicateHash в MS CSP World Wide Web link ,CryptDuplicateHash в MS CryptoAPI 2.0 World Wide Web link


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 .
*pbData
[out] Указатель на буфер данных параметра. Функция копирует соответствующие параметру данные в буфер. Формат этих данных зависит от значения dwParam. Если параметр - NULL, то данные не копируются. Требуемый размер буфера в байтах возвращается в pdwDataLen . Подробнее см. Возвращение данных неопределенной длины.
*pdwDataLen
[in/out] Указатель на буфер, содержащий длину данных параметра. При вызове функции указанный параметр содержит число байтов в буфере pbData . После её исполнения параметр будет установлен числом байтов данных параметра, скопированных в буфер pbData . Если буфер, соответствующий pbData, недостаточно большой, чтобы в него копировать запрошенные данные, будет возвращен код ошибки ERROR_MORE_DATA через функцию SetLastError(). В этом случае требуемый размер буфера возвращается в pdwDataLen . Если функция завершается с кодом ошибки, отличным от ERROR_MORE_DATA, в этом параметре возвращается ноль.
dwFlags
[in] Значения флагов. установленного в реестре флага равноПараметр зарезервирован для будущего использования и должен быть нулевым.

Возвращаемые значения:

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

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Файл описания: Прототип описан в файле wincsp.h.
Ядро Windows NT: IRQL < DISPATCH_LEVEL

См. также:

CPCreateHash() ,CPGetKeyParam() ,CPSetHashParam() ,CPGetHashParam в MS CSP World Wide Web link ,CryptGetHashParam в MS CryptoAPI 2.0 World Wide Web link


CPHashData

Функция CPHashData() передаёт данные указанному объекту функции хеширования.

установленного в реестре флага равно *

BOOL WINAPI CPHashData(
  HCRYPTPROV hProv,
  HCRYPTHASH hHash,
  WINCSP_CONST 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 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Файл описания: Прототип описан в файле wincsp.h.
Ядро Windows NT: IRQL < DISPATCH_LEVEL

См. также:

CPCreateHash() ,CPHashSessionKey() ,CPHashData в MS CSP World Wide Web link ,CryptHashData в MS CryptoAPI 2.0 World Wide Web link


CPHashSessionKey

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

установленного в реестре флага равно

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

Аргументы

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

Возвращаемые значения:

При успешном завершении функция возвращает 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 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Файл описания: Прототип описан в файле wincsp.h.
Ядро Windows NT: IRQL < DISPATCH_LEVEL

См. также:

CPCreateHash() ,CPGenKey() ,CPHashData() ,CPHashSessionKey в MS CSP World Wide Web link ,CryptHashSessionKey в MS CryptoAPI 2.0 World Wide Web link


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_HASHSIZE | Устанавливается для объекта функции хеширования типа CALG_G28147_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.
HP_OPEN | Устанавливается для объектов функции хеширования типа CALG_GR3411 и CALG_G28147_IMIT в случае, если они закрыты. Если через параметр pbData передаётся величина FALSE типа DWORD, осуществляется инициализация объекта функции хеширования, в противном случае объект функции хеширования открывается эжя дальнейщего хеширования жанных.
pbData
[in] Указатель на буфер данных параметра. При вызове функции буфер содержит данные, соответствующие значению параметра в dwParam . Формат данных зависит от типа параметра dwParam .
dwFlags
[in] Значения флагов. Параметр зарезервирован для будущего использования и должен быть нулевым.

Возвращаемые значения:

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

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Файл описания: Прототип описан в файле wincsp.h.
Ядро Windows NT: IRQL < DISPATCH_LEVEL

См. также:

CPCreateHash() ,CPGetHashParam() ,CPSignHash() ,CPSetHashParam в MS CSP World Wide Web link ,CryptSetHashParam в MS CryptoAPI 2.0 World Wide Web link


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] Значения флагов. Параметр зарезервирован для будущего использования и должен быть нулем.
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 | Нарушение целостности ключей в ОЗУ. см. Дополнительные параметры и определения .
SCARD_W_CANCELLED_BY_USER | Пользователь прервал операцию нажатием клавиши Cancel
SCARD_W_WRONG_CHV | Пользователь ввел неправильный пароль или пароль, установленный функцией SetProvParam(), неправильный
SCARD_E_INVALID_CHV | Пользователь ввел пароль с нарушением формата или пароль, установленный функцией SetProvParam(), имеет неправильный формат. Например, пароль имеет недопустимую длину или содержит недопустимые символы.
SCARD_W_CHV_BLOCKED | Ввод Pin-кода был заблокирован смарт-картой, т.к. исчерпалось количество попыток, разрешенное картой для ввода.
NTE_SILENT_CONTEXT | Операция не может быть выполнена без пользовательского интерфейса.
SCARD_W_REMOVED_CARD | Носитель контейнера был удален из считывателя

Примечания

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

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

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

    После того, как объект функции хеширования подписан, приложение не может добавлять к нему новые данные. Поэтому вызовы функций CPHashData() или CPHashSessionKey() приведут к ошибке. Однако, дополнительные вызовы функций CPDeriveKey(), CPGetHashParam(), CPSignHash() и CPVerifySignature() будут успешными. Эти функции будут работать с подписанным объектом функции хеширования. Приложение должно удалить объект функции хеширования при помощи функции CPDestroyHash().

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Файл описания: Прототип описан в файле wincsp.h.
Ядро Windows NT: IRQL < DISPATCH_LEVEL
Ядро ОС: В ядре ОС эта функция не поддерживается.

См. также:

CPCreateHash() ,CPDestroyHash() ,CPHashData() ,CPHashSessionKey() ,CPVerifySignature() ,CPSignHash в MS CSP World Wide Web link ,CryptSignHash в MS CryptoAPI 2.0 World Wide Web link


CPVerifySignature

Функция CPVerifySignature() осуществляет проверку цифровой подписи.

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

Аргументы

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

Возвращаемые значения:

При успешном завершении функция возвращает TRUE, в противном случае возвращается FALSE. Если возвращается FALSE, соответствующий код ошибки (см. таблицу) может быть получен через функцию GetLastError.
Коды возврата | Описание
NTE_BAD_ALGID | Дескриптор hHash определяет алгоритм, который этот криптопровайдер не поддерживает.
NTE_BAD_FLAGS | dwFlags параметр отличен от нуля.
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.

    После того, как объект функции хеширования подписан, приложение не может добавлять к нему новые данные. Поэтому вызовы функций CPHashData() или CPHashSessionKey() приведут к ошибке. Однако, дополнительные вызовы функций CPDeriveKey(), CPGetHashParam(), CPSignHash() и CPVerifySignature() будут успешными. Эти функции будут работать с подписанным объектом функции хеширования. Приложение должно удалить объект функции хеширования при помощи функции CPDestroyHash().

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Файл описания: Прототип описан в файле wincsp.h.
Ядро Windows NT: IRQL < DISPATCH_LEVEL
Ядро ОС: "Ядро ОС:" В ядре ОС эта функция не поддерживается.

См. также:

CPCreateHash() ,CPHashData() ,CPSignHash() ,CPVerifySignature в MS CSP World Wide Web link ,CryptVerifySignature в MS CryptoAPI 2.0 World Wide Web link


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

Предназначены для взаимодействия с программами пользователя, непосредственно использующими "КриптоПро CSP".

Структуры | Описание
_PUBLICKEYSTRUC | Структура PUBLICKEYSTRUC, так же известная, как структура BLOBHEADER, указывает тип ключевого блоба и алгоритм ключа находящегося в нём. Экземпляр этой структуры находится в начале поля pbData каждого ключевого блоба.
CRYPT_SIMPLEBLOB_HEADER_ | Структура CRYPT_SIMPLEBLOB_HEADER является расширением структуры BLOBHEADER и находится в начале поля pbData ключевого блоба типа SIMPLEBLOB для ключей "КриптоПро CSP".
CRYPT_SIMPLEBLOB_ | Псевдоструктура (т. е. недоопределенная структура) CRYPT_SIMPLEBLOB полностью описывает ключевой блоб типа SIMPLEBLOB для ключей "КриптоПро CSP". Все поля этой псевдоструктуры выравнены по границе байта и находятся в сетевом порядке байт (ASN1 DER). Сетевой порядок байт означает, что число 0x12345678 будет записано в виде 0x12 0x34 0x56 0x78 в отличии от Intell порядка байт в памяти: 0x78 0x56 0x34 0x12.
_CRYPT_PUBKEYPARAM_ | Структура CRYPT_PUBKEYPARAM содержит признак ключей по ГОСТ Р 34.10-94 или ГОСТ Р 34.10-2001.
CRYPT_PUBKEY_INFO_HEADER_ | Структура CRYPT_PUBKEY_INFO_HEADER содержит заголовок блоба открытого ключа или блоба ключевой пары по ГОСТ Р 34.10-94 или ГОСТ Р 34.10-2001.
CRYPT_PUBLICKEYBLOB_ | Псевдоструктура CRYPT_PUBLICKEYBLOB полностью описывает ключевой блоб типа PUBLICKEYBLOB для ключей "КриптоПро CSP". Все поля этой псевдоструктуры выравнены по границе байта и находятся в сетевом порядке байт (ASN1 DER). Сетевой порядок байт означает, что число 0x12345678 будет записано в виде 0x12 0x34 0x56 0x78 в отличии от Intell порядка байт в памяти: 0x78 0x56 0x34 0x12.
CRYPT_PRIVATEKEYBLOB_ | Псевдоструктура CRYPT_PRIVATEKEYBLOB полностью описывает ключевой блоб типа PRIVATEKEYBLOB для ключей "КриптоПро CSP". Все поля этой псевдоструктуры выравнены по границе байта и находятся в сетевом порядке байт (ASN1 DER). Сетевой порядок байт означает, что число 0x12345678 будет записано в виде 0x12 0x34 0x56 0x78 в отличии от Intell порядка байт в памяти: 0x78 0x56 0x34 0x12.
_CRYPT_DIVERSBLOBHEADER | Структура CRYPT_DIVERSBLOB описывает блоб типа DIVERSBLOB для процедуры диверсификации ключей КриптоПро CSP. Все поля этой псевдоструктуры выравнены по границе байта и находятся в сетевом порядке байт (ASN1 DER). Сетевой порядок байт означает, что число 0x12345678 будет записано в виде 0x12 0x34 0x56 0x78 в отличии от Intell порядка байт в памяти: 0x78 0x56 0x34 0x12.
CRYPT_PIN_NK_PARAM_ | Структура передачи информации для слияния частей контейнера.
CRYPT_PIN_PARAM_ | Структура передачи информации для: 1) смены пароля контейнера, 2) указания способа доступа к контейнеру (имя, handle, пароль), на ключе которого зашифровано содержимое другого контейнера.
CRYPT_NK_INFO_PARAM_ | Структура получения информации о контейнере разделенного на части.
CRYPT_PASSWD_INFO_PARAM_ | Структура получения информации о пароле на контейнер.
CSP_FAST_CODE_ | Структура получения функций захвата и освобождения SSE2.
Макросы | Описание
CRYPT_MODE_CNT | Режим шифрования "гаммированием" по ГОСТ 28147-89.
SECRET_KEY_LEN | Длина в байтах ключа ГОСТ 28147-89 и секретных ключей ГОСТ Р 34.10-94 и ГОСТ Р 28147-89.
G28147_KEYLEN | Длина в байтах ключа ГОСТ 28147-89. SECRET_KEY_LEN .
EXPORT_IMIT_SIZE | Длина в байтах имитовставки при импорте/экспорте.
SEANCE_VECTOR_LEN | Длина в байтах вектора инциализации алгоритма.
GR3410_1_MAGIC | Признак ключей ГОСТ Р 34.10-94 и ГОСТ Р 34.10-2001.
G28147_MAGIC | Признак ключей ГОСТ 28147-89 и мастер ключей TLS.
DIVERS_MAGIC | Признак ключевого блоба функции диверсификации ключа.
BLOB_VERSION | Текущее значение версии ключевого блоба.
CSP_FAST_CODE_DEFAULT | Параметр структуры CSP_FAST_CODE . Используется для задания переключателей по умолчанию. На процессоре Intel Pentium 4 в случае установки данного параметра будет задействован более быстрый алгоритм шифрования. Однако, в режиме ядра ОС на операционных системах Linux, FreeBSD, Solaris установка данного параметра будет означать отключение быстрых алгоритмов, так как штатный захват блока FPU в режиме ядра существует только в ОС Windows.
CSP_FAST_CODE_NO | Параметр структуры CSP_FAST_CODE . Используется для выключения кода для расширения SSE2.
CSP_FAST_CODE_USER | Параметр структуры CSP_FAST_CODE . Используется для задания пользовательского захвата FPU. Применим только в режиме ядра ОС. В случае его установки в режиме ядра ОС два других поля структуры CSP_FAST_CODE должны содержать адреса функций захвата и освобождения сопроцессора FPU процессора Intel Pentium 4. На других процессорах установка данного параметра не влияет на работу драйвера провайдера.
CSP_FAST_CODE_GET_FN | Параметр структуры CSP_FAST_CODE . Используется для определения полноты набора установленных быстрых функций.
CSP_FAST_CODE_GET_SETFN | Параметр структуры CSP_FAST_CODE . Используется для определения, может ли провайдер . исполнять быстрый код на данной машине.
CSP_FAST_CODE_E_ECB | Параметр структуры CSP_FAST_CODE . Используется как флаг, для проверки, какой код применяется в функции зашифрования по ECB Равен 1 в случае быстрого кода данной функции, и 0 иначе.
CSP_FAST_CODE_E_CBC | Параметр структуры CSP_FAST_CODE . Используется как флаг, для проверки, какой код применяется в функции зашифрования по CBC Равен 1 в случае быстрого кода данной функции, и 0 иначе.
CSP_FAST_CODE_E_OFB | Параметр структуры CSP_FAST_CODE . Используется как флаг, для проверки, какой код применяется в функции зашифрования по OFB Равен 1 в случае быстрого кода данной функции, и 0 иначе.
CSP_FAST_CODE_D_OFB | Параметр структуры CSP_FAST_CODE . Используется как флаг, для проверки, какой код применяется в функции расшифрования по OFB Равен 1 в случае быстрого кода данной функции, и 0 иначе.
CSP_FAST_CODE_E_CFB | Параметр структуры CSP_FAST_CODE . Используется как флаг, для проверки, какой код применяется в функции зашифрования по CFB Равен 1 в случае быстрого кода данной функции, и 0 иначе.
CSP_FAST_CODE_D_ECB | Параметр структуры CSP_FAST_CODE . Используется как флаг, для проверки, какой код применяется в функции расшифрования по ECB Равен 1 в случае быстрого кода данной функции, и 0 иначе.
CSP_FAST_CODE_D_CBC | Параметр структуры CSP_FAST_CODE . Используется как флаг, для проверки, какой код применяется в функции расшифрования по CBC Равен 1 в случае быстрого кода данной функции, и 0 иначе.
CSP_FAST_CODE_D_CFB | Параметр структуры CSP_FAST_CODE . Используется как флаг, для проверки, какой код применяется в функции расшифрования по CFB Равен 1 в случае быстрого кода данной функции, и 0 иначе.
CSP_FAST_CODE_MD_ECB | Параметр структуры CSP_FAST_CODE . Используется как флаг, для проверки, какой код применяется в функции маскирования ключа Равен 1 в случае быстрого кода данной функции, и 0 иначе.
CSP_FAST_CODE_GR3411SP | Параметр структуры CSP_FAST_CODE . Используется как флаг, для проверки, какой код применяется в упрощенной функции хэширования. Флаг устанавливается только в режиме ядра ОС. Равен 1 в случае быстрого кода данной функции, и 0 иначе.
CSP_FAST_CODE_GR3411H | Параметр структуры CSP_FAST_CODE . Используется как флаг, для проверки, какой код применяется в функции хэширования. Флаг устанавливается только в режиме ядра ОС. Равен 1 в случае быстрого кода данной функции, и 0 иначе.
CSP_FAST_CODE_GR3411HV | Параметр структуры CSP_FAST_CODE . Используется как флаг, для проверки, какой код применяется в функции проверки хэша. Флаг устанавливается только в режиме ядра ОС. Равен 1 в случае быстрого кода данной функции, и 0 иначе.
CSP_FAST_CODE_HASH | Параметр структуры CSP_FAST_CODE . Используется как флаг, для проверки, какой код применяется в функции хэш-преобразования. Равен 1 в случае быстрого кода данной функции, и 0 иначе.
CSP_FAST_CODE_IMIT | Параметр структуры CSP_FAST_CODE . Используется как флаг, для проверки, какой код применяется в функции выработки имитовставки. Равен 1 в случае быстрого кода данной функции, и 0 иначе.
CSP_FAST_CODE_MULT | Параметр структуры CSP_FAST_CODE . Используется как флаг, для проверки, какой код применяется в функции умножения. Равен 1 в случае быстрого кода данной функции, и 0 иначе.
CSP_FAST_CODE_MULT_ATT | Параметр структуры CSP_FAST_CODE . Используется как флаг, для проверки, какой код применяется в функциях умножения в UNIX-оподобных системах. Равен 1 в случае быстрого кода данной функции, и 0 иначе.
CSP_FAST_CODE_ALL_ENCRYPT | Параметр структуры CSP_FAST_CODE . Группирует все флаги функций зашифрования.
CSP_FAST_CODE_ALL_DECRYPT | Параметр структуры CSP_FAST_CODE . Группирует все флаги функций расшифрования.
CSP_FAST_CODE_ALL_HASH | Параметр структуры CSP_FAST_CODE . Группирует все флаги функций хэширования.
CSP_FAST_CODE_ALL_MULT | Параметр структуры CSP_FAST_CODE . Группирует все флаги функций умножения.
CSP_FAST_CODE_ALL_CRYPT | Параметр структуры CSP_FAST_CODE . Группирует все флаги функций шифрования.
CSP_FAST_CODE_ALL_FUNCTIONS | Параметр структуры CSP_FAST_CODE . Группирует все флаги переключаемых функций криптопровайдера.
CSP_FAST_CODE_ALL_KERNEL_FUNCTIONS | Параметр структуры CSP_FAST_CODE . Группирует все флаги переключаемых функций криптопровайдера режима ядра ОС.
CSP_FAST_CODE_ALL_USER_FUNCTIONS | Параметр структуры CSP_FAST_CODE . Группирует все флаги переключаемых функций криптопровайдера пользовательского режима.


CRYPT_MODE_CNT

Режим шифрования "гаммированием" по ГОСТ 28147-89.
#define CRYPT_MODE_CNT CRYPT_MODE_OFB


SECRET_KEY_LEN

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


G28147_KEYLEN

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


EXPORT_IMIT_SIZE

Длина в байтах имитовставки при импорте/экспорте.
#define EXPORT_IMIT_SIZE 4


SEANCE_VECTOR_LEN

Длина в байтах вектора инциализации алгоритма.
#define SEANCE_VECTOR_LEN 8


GR3410_1_MAGIC

Признак ключей ГОСТ Р 34.10-94 и ГОСТ Р 34.10-2001.
#define GR3410_1_MAGIC 0x3147414D


G28147_MAGIC

Признак ключей ГОСТ 28147-89 и мастер ключей TLS.
#define G28147_MAGIC 0x374a51fd


DIVERS_MAGIC

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


BLOB_VERSION

Текущее значение версии ключевого блоба.
#define BLOB_VERSION (BYTE)0x20


CSP_FAST_CODE_DEFAULT

Параметр структуры CSP_FAST_CODE . Используется для задания переключателей по умолчанию. На процессоре Intel Pentium 4 в случае установки данного параметра будет задействован более быстрый алгоритм шифрования. Однако, в режиме ядра ОС на операционных системах Linux, FreeBSD, Solaris установка данного параметра будет означать отключение быстрых алгоритмов, так как штатный захват блока FPU в режиме ядра существует только в ОС Windows.
#define CSP_FAST_CODE_DEFAULT (1U<<31)


CSP_FAST_CODE_NO

Параметр структуры CSP_FAST_CODE . Используется для выключения кода для расширения SSE2.
#define CSP_FAST_CODE_NO (1<<30)


CSP_FAST_CODE_USER

Параметр структуры CSP_FAST_CODE . Используется для задания пользовательского захвата FPU. Применим только в режиме ядра ОС. В случае его установки в режиме ядра ОС два других поля структуры CSP_FAST_CODE должны содержать адреса функций захвата и освобождения сопроцессора FPU процессора Intel Pentium 4. На других процессорах установка данного параметра не влияет на работу драйвера провайдера.
#define CSP_FAST_CODE_USER (1<<29)


CSP_FAST_CODE_GET_FN

Параметр структуры CSP_FAST_CODE . Используется для определения полноты набора установленных быстрых функций.
#define CSP_FAST_CODE_GET_FN (1<<28)


CSP_FAST_CODE_GET_SETFN

Параметр структуры CSP_FAST_CODE . Используется для определения, может ли провайдер . исполнять быстрый код на данной машине.
#define CSP_FAST_CODE_GET_SETFN (1<<27)


CSP_FAST_CODE_E_ECB

Параметр структуры CSP_FAST_CODE . Используется как флаг, для проверки, какой код применяется в функции зашифрования по ECB Равен 1 в случае быстрого кода данной функции, и 0 иначе.
#define CSP_FAST_CODE_E_ECB (1)


CSP_FAST_CODE_E_CBC

Параметр структуры CSP_FAST_CODE . Используется как флаг, для проверки, какой код применяется в функции зашифрования по CBC Равен 1 в случае быстрого кода данной функции, и 0 иначе.
#define CSP_FAST_CODE_E_CBC (1<<1)


CSP_FAST_CODE_E_OFB

Параметр структуры CSP_FAST_CODE . Используется как флаг, для проверки, какой код применяется в функции зашифрования по OFB Равен 1 в случае быстрого кода данной функции, и 0 иначе.
#define CSP_FAST_CODE_E_OFB (1<<2)


CSP_FAST_CODE_D_OFB

Параметр структуры CSP_FAST_CODE . Используется как флаг, для проверки, какой код применяется в функции расшифрования по OFB Равен 1 в случае быстрого кода данной функции, и 0 иначе.
#define CSP_FAST_CODE_D_OFB (1<<2)


CSP_FAST_CODE_E_CFB

Параметр структуры CSP_FAST_CODE . Используется как флаг, для проверки, какой код применяется в функции зашифрования по CFB Равен 1 в случае быстрого кода данной функции, и 0 иначе.
#define CSP_FAST_CODE_E_CFB (1<<3)


CSP_FAST_CODE_D_ECB

Параметр структуры CSP_FAST_CODE . Используется как флаг, для проверки, какой код применяется в функции расшифрования по ECB Равен 1 в случае быстрого кода данной функции, и 0 иначе.
#define CSP_FAST_CODE_D_ECB (1<<4)


CSP_FAST_CODE_D_CBC

Параметр структуры CSP_FAST_CODE . Используется как флаг, для проверки, какой код применяется в функции расшифрования по CBC Равен 1 в случае быстрого кода данной функции, и 0 иначе.
#define CSP_FAST_CODE_D_CBC (1<<5)


CSP_FAST_CODE_D_CFB

Параметр структуры CSP_FAST_CODE . Используется как флаг, для проверки, какой код применяется в функции расшифрования по CFB Равен 1 в случае быстрого кода данной функции, и 0 иначе.
#define CSP_FAST_CODE_D_CFB (1<<6)


CSP_FAST_CODE_MD_ECB

Параметр структуры CSP_FAST_CODE . Используется как флаг, для проверки, какой код применяется в функции маскирования ключа Равен 1 в случае быстрого кода данной функции, и 0 иначе.
#define CSP_FAST_CODE_MD_ECB (1<<7)


CSP_FAST_CODE_GR3411SP

Параметр структуры CSP_FAST_CODE . Используется как флаг, для проверки, какой код применяется в упрощенной функции хэширования. Флаг устанавливается только в режиме ядра ОС. Равен 1 в случае быстрого кода данной функции, и 0 иначе.
#define CSP_FAST_CODE_GR3411SP (1<<8)


CSP_FAST_CODE_GR3411H

Параметр структуры CSP_FAST_CODE . Используется как флаг, для проверки, какой код применяется в функции хэширования. Флаг устанавливается только в режиме ядра ОС. Равен 1 в случае быстрого кода данной функции, и 0 иначе.
#define CSP_FAST_CODE_GR3411H (1<<9)


CSP_FAST_CODE_GR3411HV

Параметр структуры CSP_FAST_CODE . Используется как флаг, для проверки, какой код применяется в функции проверки хэша. Флаг устанавливается только в режиме ядра ОС. Равен 1 в случае быстрого кода данной функции, и 0 иначе.
#define CSP_FAST_CODE_GR3411HV (1<<10)


CSP_FAST_CODE_HASH

Параметр структуры CSP_FAST_CODE . Используется как флаг, для проверки, какой код применяется в функции хэш-преобразования. Равен 1 в случае быстрого кода данной функции, и 0 иначе.
#define CSP_FAST_CODE_HASH (1<<11)


CSP_FAST_CODE_IMIT

Параметр структуры CSP_FAST_CODE . Используется как флаг, для проверки, какой код применяется в функции выработки имитовставки. Равен 1 в случае быстрого кода данной функции, и 0 иначе.
#define CSP_FAST_CODE_IMIT (1<<12)


CSP_FAST_CODE_MULT

Параметр структуры CSP_FAST_CODE . Используется как флаг, для проверки, какой код применяется в функции умножения. Равен 1 в случае быстрого кода данной функции, и 0 иначе.
#define CSP_FAST_CODE_MULT (1<<13)


CSP_FAST_CODE_MULT_ATT

Параметр структуры CSP_FAST_CODE . Используется как флаг, для проверки, какой код применяется в функциях умножения в UNIX-оподобных системах. Равен 1 в случае быстрого кода данной функции, и 0 иначе.
#define CSP_FAST_CODE_MULT_ATT (1<<14)


CSP_FAST_CODE_ALL_ENCRYPT

Параметр структуры CSP_FAST_CODE . Группирует все флаги функций зашифрования.
#define CSP_FAST_CODE_ALL_ENCRYPT (CSP_FAST_CODE_E_ECB|CSP_FAST_CODE_E_CBC|CSP_FAST_CODE_E_OFB|CSP_FAST_CODE_E_CFB)


CSP_FAST_CODE_ALL_DECRYPT

Параметр структуры CSP_FAST_CODE . Группирует все флаги функций расшифрования.
#define CSP_FAST_CODE_ALL_DECRYPT (CSP_FAST_CODE_D_ECB|CSP_FAST_CODE_D_CBC|CSP_FAST_CODE_D_OFB|CSP_FAST_CODE_D_CFB)


CSP_FAST_CODE_ALL_HASH

Параметр структуры CSP_FAST_CODE . Группирует все флаги функций хэширования.
#define CSP_FAST_CODE_ALL_HASH (CSP_FAST_CODE_HASH|CSP_FAST_CODE_GR3411SP|CSP_FAST_CODE_GR3411H|CSP_FAST_CODE_GR3411HV)


CSP_FAST_CODE_ALL_MULT

Параметр структуры CSP_FAST_CODE . Группирует все флаги функций умножения.
#define CSP_FAST_CODE_ALL_MULT (CSP_FAST_CODE_MULT|CSP_FAST_CODE_MULT_ATT)


CSP_FAST_CODE_ALL_CRYPT

Параметр структуры CSP_FAST_CODE . Группирует все флаги функций шифрования.
#define CSP_FAST_CODE_ALL_CRYPT (CSP_FAST_CODE_ALL_ENCRYPT|CSP_FAST_CODE_ALL_DECRYPT|CSP_FAST_CODE_MD_ECB|CSP_FAST_CODE_IMIT)


CSP_FAST_CODE_ALL_FUNCTIONS

Параметр структуры CSP_FAST_CODE . Группирует все флаги переключаемых функций криптопровайдера.
#define CSP_FAST_CODE_ALL_FUNCTIONS (CSP_FAST_CODE_ALL_CRYPT|CSP_FAST_CODE_ALL_HASH|CSP_FAST_CODE_ALL_MULT)


CSP_FAST_CODE_ALL_KERNEL_FUNCTIONS

Параметр структуры CSP_FAST_CODE . Группирует все флаги переключаемых функций криптопровайдера режима ядра ОС.
#define CSP_FAST_CODE_ALL_KERNEL_FUNCTIONS (CSP_FAST_CODE_ALL_CRYPT|CSP_FAST_CODE_ALL_HASH)


CSP_FAST_CODE_ALL_USER_FUNCTIONS

Параметр структуры CSP_FAST_CODE . Группирует все флаги переключаемых функций криптопровайдера пользовательского режима.
#define CSP_FAST_CODE_ALL_USER_FUNCTIONS (CSP_FAST_CODE_ALL_CRYPT|CSP_FAST_CODE_HASH|CSP_FAST_CODE_ALL_MULT)


_PUBLICKEYSTRUC

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

typedef struct _PUBLICKEYSTRUC {
  BYTE bType;
  BYTE bVersion;
  WORD reserved;
  ALG_ID aiKeyAlg;
} BLOBHEADER, PUBLICKEYSTRUC;

Члены

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

Требования:

Windows NT/2000: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows 95/98/ME: CSP 3.0 не поддерживает (см. ?).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше.
Linux: RedHat 7.3, RedHad 9.0.
Ядро Windows NT: IRQL < DISPATCH_LEVEL
Файл описания: Windows прототип описан в файле Wincrypt.h, Solaris - CSP_Wincrypt.h

См. также:

CRYPT_PUBKEY_INFO_HEADER ,CRYPT_SIMPLEBLOB_HEADER ,CRYPT_PUBLICKEYBLOB ,CRYPT_PRIVATEKEYBLOB ,CRYPT_SIMPLEBLOB


CRYPT_SIMPLEBLOB_HEADER_

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

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

Члены

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

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Файл описания: Прототип описан в файле WinCryptEx.h.
Ядро Windows NT: IRQL < DISPATCH_LEVEL

См. также:

_PUBLICKEYSTRUC ,PCRYPT_SIMPLEBLOB ,CPExportKey ,CPGetKeyParam


CRYPT_SIMPLEBLOB_

Псевдоструктура (т. е. недоопределенная структура) CRYPT_SIMPLEBLOB полностью описывает ключевой блоб типа SIMPLEBLOB для ключей "КриптоПро CSP". Все поля этой псевдоструктуры выравнены по границе байта и находятся в сетевом порядке байт (ASN1 DER). Сетевой порядок байт означает, что число 0x12345678 будет записано в виде 0x12 0x34 0x56 0x78 в отличии от Intell порядка байт в памяти: 0x78 0x56 0x34 0x12.

typedef struct CRYPT_SIMPLEBLOB_ {
  CRYPT_SIMPLEBLOB_HEADER tSimpleBlobHeader;
  BYTE bSV[SEANCE_VECTOR_LEN];
  BYTE bEncryptedKey[G28147_KEYLEN];
  BYTE bMacKey[EXPORT_IMIT_SIZE];
  BYTE bEncryptionParamSet[1];
} CRYPT_SIMPLEBLOB, *PCRYPT_SIMPLEBLOB;

Члены

tSimpleBlobHeader
Общий заголовок ключевого блоба типа SIMPLEBLOB "КриптоПро CSP".
bSV
Вектор инциализации для алгоритма CALG_PRO_EXPORT. См. SEANCE_VECTOR_LEN .
bEncryptedKey
Зашифрованный ключ ГОСТ 28147-89. См. G28147_KEYLEN .
bMacKey
Имитовставка по ГОСТ 28147-89 на ключ. Рассчитывается до зашифрования и проверяется после расшифрования. См. EXPORT_IMIT_SIZE .
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

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Файл описания: Прототип описан в файле WinCryptEx.h.
Ядро Windows NT: IRQL < DISPATCH_LEVEL

См. также:

CRYPT_SIMPLEBLOB_HEADER ,CPExportKey ,CPGetKeyParam


_CRYPT_PUBKEYPARAM_

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

typedef struct _CRYPT_PUBKEYPARAM_ {
  DWORD Magic;
  DWORD BitLen;
} CRYPT_PUBKEYPARAM, *LPCRYPT_PUBKEYPARAM;

Члены

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

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Файл описания: Прототип описан в файле WinCryptEx.h.
Ядро Windows NT: IRQL < DISPATCH_LEVEL

См. также:

CRYPT_PUBKEY_INFO_HEADER ,CPExportKey ,CPGetKeyParam


CRYPT_PUBKEY_INFO_HEADER_

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

typedef struct CRYPT_PUBKEY_INFO_HEADER_ {
  BLOBHEADER BlobHeader;
  CRYPT_PUBKEYPARAM KeyParam;
} CRYPT_PUBKEY_INFO_HEADER;

Члены

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

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Файл описания: Прототип описан в файле WinCryptEx.h.
Ядро Windows NT: IRQL < DISPATCH_LEVEL

См. также:

_PUBLICKEYSTRUC ,CRYPT_PUBKEYPARAM ,CPExportKey ,CPGetKeyParam


CRYPT_PUBLICKEYBLOB_

Псевдоструктура CRYPT_PUBLICKEYBLOB полностью описывает ключевой блоб типа PUBLICKEYBLOB для ключей "КриптоПро CSP". Все поля этой псевдоструктуры выравнены по границе байта и находятся в сетевом порядке байт (ASN1 DER). Сетевой порядок байт означает, что число 0x12345678 будет записано в виде 0x12 0x34 0x56 0x78 в отличии от Intell порядка байт в памяти: 0x78 0x56 0x34 0x12.

typedef struct CRYPT_PUBLICKEYBLOB_ {
  CRYPT_PUBKEY_INFO_HEADER tPublicKeyParam;
  BYTE bASN1GostR3410_94_PublicKeyParameters[1];
  BYTE bPublicKey[1];
} CRYPT_PUBLICKEYBLOB, *PCRYPT_PUBLICKEYBLOB;

Члены

tPublicKeyParam
Общий заголовок ключевого блоба типа PUBLICKEYBLOB "КриптоПро CSP".
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.

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Файл описания: Прототип описан в файле WinCryptEx.h.
Ядро Windows NT: IRQL < DISPATCH_LEVEL

См. также:

CRYPT_PUBKEY_INFO_HEADER ,CPExportKey ,CPGetKeyParam


CRYPT_PRIVATEKEYBLOB_

Псевдоструктура CRYPT_PRIVATEKEYBLOB полностью описывает ключевой блоб типа PRIVATEKEYBLOB для ключей "КриптоПро CSP". Все поля этой псевдоструктуры выравнены по границе байта и находятся в сетевом порядке байт (ASN1 DER). Сетевой порядок байт означает, что число 0x12345678 будет записано в виде 0x12 0x34 0x56 0x78 в отличии от Intell порядка байт в памяти: 0x78 0x56 0x34 0x12.

typedef struct CRYPT_PRIVATEKEYBLOB_ {
  CRYPT_PUBKEY_INFO_HEADER tPublicKeyParam;
  BYTE bExportedKeys[1];
} CRYPT_PRIVATEKEYBLOB, *PCRYPT_PRIVATEKEYBLOB;

Члены

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

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Файл описания: Прототип описан в файле WinCryptEx.h.
Ядро Windows NT: IRQL < DISPATCH_LEVEL

См. также:

CRYPT_PUBKEY_INFO_HEADER ,CPExportKey ,CPGetKeyParam


_CRYPT_DIVERSBLOBHEADER

Структура CRYPT_DIVERSBLOB описывает блоб типа DIVERSBLOB для процедуры диверсификации ключей КриптоПро CSP. Все поля этой псевдоструктуры выравнены по границе байта и находятся в сетевом порядке байт (ASN1 DER). Сетевой порядок байт означает, что число 0x12345678 будет записано в виде 0x12 0x34 0x56 0x78 в отличии от Intell порядка байт в памяти: 0x78 0x56 0x34 0x12.

typedef struct _CRYPT_DIVERSBLOBHEADER {
  BLOBHEADER BlobHeader;
  ALG_ID aiDiversAlgId;
  DWORD dwDiversMagic;
  DWORD cbDiversData;
} CRYPT_DIVERSBLOBHEADER, *LPCRYPT_DIVERSBLOBHEADER;

Члены

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

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Файл описания: Прототип описан в файле WinCryptEx.h.
Ядро Windows NT: IRQL < DISPATCH_LEVEL

См. также:

CPImportKey


CRYPT_PIN_NK_PARAM_

Структура передачи информации для слияния частей контейнера.

typedef struct CRYPT_PIN_NK_PARAM_ {
  short n;
  short k;
  HCRYPTPROV * parts;
} CRYPT_PIN_NK_PARAM;

Члены

n
Количество передаваемых частей.
k
Количество частей для загрузки.
parts
HANDLE частей контейнера.

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Файл описания: Прототип описан в файле WinCryptEx.h.
Ядро Windows NT: IRQL < DISPATCH_LEVEL

См. также:

CPSetProvParam


CRYPT_PIN_PARAM_

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

typedef struct CRYPT_PIN_PARAM_ {
  BYTE type;
  CRYPT_PIN_SOURCE dest;
} CRYPT_PIN_PARAM;

Члены

type
Тип данных. CRYPT_PIN_PASSWD - пароль или PIN, CRYPT_PIN_ENCRYPTION - HANDLE контейнера зашифрования. CRYPT_PIN_QUERY - тип и значение выбираются в окне, CRYPT_PIN_CLEAR - очистить пароль. CRYPT_PIN_NK - разбить на части k из n
dest
Данные соответствующего типа

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Файл описания: Прототип описан в файле WinCryptEx.h.
Ядро Windows NT: IRQL < DISPATCH_LEVEL

См. также:

CPSetProvParam


CRYPT_NK_INFO_PARAM_

Структура получения информации о контейнере разделенного на части.

typedef struct CRYPT_NK_INFO_PARAM_ {
  short n;
  short k;
  char parts[1];
} CRYPT_NK_INFO_PARAM;

Члены

n
Количество частей, на которые разделен контейнер.
k
Количество частей, достаточных для получения колюча.
parts
Последовательность n ASCIIZ строк.

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Файл описания: Прототип описан в файле WinCryptEx.h.
Ядро Windows NT: IRQL < DISPATCH_LEVEL

См. также:

CPSetProvParam


CRYPT_PASSWD_INFO_PARAM_

Структура получения информации о пароле на контейнер.

typedef struct CRYPT_PASSWD_INFO_PARAM_ {
  unsigned min_passwd_length;
  unsigned max_passwd_length;
  unsigned passwd_type;
} CRYPT_PASSWD_INFO_PARAM;

Члены

min_passwd_length
Минимальный допустимый размер пароля.
max_passwd_length
Максимальный допустимый размер пароля.
passwd_type
Тип пароля.

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Файл описания: Прототип описан в файле WinCryptEx.h.
Ядро Windows NT: IRQL < DISPATCH_LEVEL

См. также:

CPSetProvParam


CSP_FAST_CODE_

Структура получения функций захвата и освобождения SSE2.

typedef struct CSP_FAST_CODE_ {
  DWORD UsesFunctions;
  int(* kernel_fpu_begin)(char *buf, size_t sz, unsigned int bl_len);
  int(* kernel_fpu_end)(char *, size_t);
} CSP_FAST_CODE;

Члены

UsesFunctions
Обязательный параметр, может быть равен CSP_FAST_CODE_DEFAULT , CSP_FAST_CODE_NO , CSP_FAST_CODE_USER при вызове функции CPSetProvParam . В первых двух случаях считывание указателей не производится, в последнем считываются новые указатели на функции переключения. CSP_FAST_CODE_USER применяется только в режиме ядра ОС! При использовании в функции CPGetProvParam , в параметре возвращаются флаги, определяющие набор провереных на включенный код функций. Указание, какие функции проверять на включенный код, передается во флагах dwFlags . Если в режиме ядра пользовательские функции захвата были установлены, не забудьте снять их перед завершением работы Вашего драйвера! В противном случае драйвер провайдера будет по-прежнему пытаться обращаться по старым адресам при выполнении криптографических операций. При остановке Вашего драйвера следует вызвать CPSetProvParam с параметром PP_FAST_CODE, установив в структуре UsesFunctions=CSP_FAST_CODE_DEFAULT . Если применен флаг CRYPT_FAST_CODE_GET_SETFN, при выходе CSP_FAST_CODE_GET_SETFN будет установлен в 1, если провайдер может использовать быстрый код, и 0 - иначе. Если установлен флаг CRYPT_FAST_CODE_ALL_FUNCTIONS , будут проверяться все функции, и на выходе будут установлены все флаги CSP_FAST_CODE_E_ECB , CSP_FAST_CODE_E_CBC , CSP_FAST_CODE_E_OFB , CSP_FAST_CODE_E_CFB , CSP_FAST_CODE_D_ECB , CSP_FAST_CODE_D_CBC , CSP_FAST_CODE_D_OFB , CSP_FAST_CODE_D_CFB , CSP_FAST_CODE_MD_ECB , CSP_FAST_CODE_GR3411SP , CSP_FAST_CODE_GR3411H , CSP_FAST_CODE_GR3411HV , CSP_FAST_CODE_HASH , CSP_FAST_CODE_IMIT , CSP_FAST_CODE_MULT , в 1, если соответствующая функция использует быстрый код, и 0 - иначе. В режиме пользователя следует вместо флага CRYPT_FAST_CODE_ALL_FUNCTIONS использовать CRYPT_FAST_CODE_ALL_USER_FUNCTIONS, а в режиме ядра ОС - CRYPT_FAST_CODE_ALL_KERNEL_FUNCTIONS. На выходе флаг CSP_FAST_CODE_ALL_FUNCTIONS равен 1, если быстрый код работает во всех выбранных функциях, и 0 если хотя бы одна из выбранных функций не сработала. Поведение невыбранных флагов неопределено.
kernel_fpu_begin
Указатель на функцию захвата SSE2. Используется только в режиме ядра ОС! Функция должна возвращать 1, если захват удался, 0, если захват не удался. На вход функции будет подаваться указатель на буфер, необходимый для сохранения значений регистров, управляющих флагов, и другой информации. Размер буфера передается во втором параметре. Стандартно он не превышает 512 байт. Третий параметр - условное значение, равное числу байт, передаваемых для быстрого шифрования. Третий параметр нужен для вычисления, выгодно ли захватывать SSE2.
kernel_fpu_end
Указатель на функцию освобождения SSE2. Используется только в режиме ядра ОС! Первые два параметра как у kernel_fpu_begin. Функция возвращает 1, если удалось освободить SSE2, и 0 в противном случае. Если функция kernel_fpu_begin вернула 0, то kernel_fpu_end вызываться не будет!

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
Solaris: 9 Update 4 или выше.
FreeBSD: FreeBSD 5.2 или выше
Linux: RedHat 7.3, RedHad 9.0.
Файл описания: Прототип описан в файле WinCryptEx.h.
Ядро Windows NT: IRQL < DISPATCH_LEVEL

См. также:

CPSetProvParam ,CPGetProvParam


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

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

Для уменьшения размера кода примеров следующие 4 строки в них не приводятся:

 #include <stdio.h>
 #include <windows.h>
 #include <wincrypt.h>
 #include <wincryptex.h>

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

Определение функции HandleError не приведено в примераx. Оно приводится ниже:

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

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

Примечания

Использование функций криптопровайдера возможно различными способами. Рекомендуется перед определением уровня встраивания ознакомиться с разделом "Архитектура криптографических функций в Windows".


Примеры работы с криптографическими сессиями и ключами

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

  • Пример на создание ключевого контейнера и генерацию ключей
  • Пример использования функции CryptAcquireContext
  • Пример на перечисление криптопровайдеров
  • Пример на получение сессионного ключа из пароля
  • Пример на дублирование сессионного ключа
  • Пример на установку и получение сессионного ключа
  • Пример на экспортирование сессионного ключа с использованием структуры BLOB
  • Пример на экспортирование сессионного ключа с использованием сертификатами
  • Пример на закодирование и раскодирование данных
  • Пример на копирование закрытого ключа
  • Пример на работу в режиме SILENT, без окон
  • Непосредственный вызов функций криптопровайдера


Крипто-Про CSP

Этот пример демонстрирует использование следующих функций
  • CryptAcquireContext в MS CryptoAPI 2.0 World Wide Web link
  • CryptDestroyKey в MS CryptoAPI 2.0 World Wide Web link
  • CryptGenKey в MS CryptoAPI 2.0 World Wide Web link
  • CryptGetProvParam в MS CryptoAPI 2.0 World Wide Web link
  • CryptGetUserKey в MS CryptoAPI 2.0 World Wide Web link
  • CryptReleaseContext в MS CryptoAPI 2.0 World Wide Web link

//--------------------------------------------------------------------
// Пример создания ключевого контейнера с именем, передаваемым в качестве
// параметра командной строки. Если параметр не указан, то будет создан
// контейнер с именем по умолчанию. В контейнере созданиются два ключа
// (ключ обмена и ключ подписи).

#define MY_ENCODING_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
void HandleError(char *s);

int main(int argc, char *argv[])
{
//--------------------------------------------------------------------
// Объявление и инициализация переменных.

HCRYPTPROV hCryptProv;        // Дескриптор контекста
                              // критографического провайдера.
HCRYPTKEY hKey;               // Дескриптор открытого/закрытого ключа.
CHAR szUserName[100];         // Буфер для хранения имени
                              // ключевого контейнера.
DWORD dwUserNameLen = 100;    // Длина буфера.
LPCSTR UserName= NULL;        // Добавленное по выбору имя пользователя
                              // здесь будет использовано как имя
                              // ключевого контейнера (ограничение на 100
                                                          // символов).
//--------------------------------------------------------------------
// Начало выполнения. Получение имени создаваемого контейнера.

if(argv[1]!=NULL)
{
    UserName = argv[1];
}

//  Для создания нового ключевого контейнера строка второго параметра
//  заменяется на NULL здесь и при следующем вызове функции
//  CryptAcquireContext.

if(CryptAcquireContext(
   &hCryptProv,               // Дескриптор CSP
   UserName,                  // Имя контейнера
   NULL,                      // Использование провайдера по умолчанию
   75,         // Тип провайдера
   0))                        // Значения флагов
{
    printf("A crypto context with the %s key container \n", UserName);
    printf("has been acquired.\n\n");
}
else
{
//--------------------------------------------------------------------
// Некоторая разновидность ошибок, возникающих при получении контекста.
// Создание нового контейнера.

   if(CryptAcquireContext(
      &hCryptProv,
      UserName,
      NULL,
      75,
      CRYPT_NEWKEYSET))
   {
      printf("A new key container has been created.\n");
   }
   else
   {
      HandleError("Could not create a new key container.\n");
    }
} // Конец else
//--------------------------------------------------------------------
// Криптографический контекст с ключевым контейнером доступен. Получение
// имени ключевого контейнера.
if(CryptGetProvParam(
    hCryptProv,               // Дескриптор CSP
    PP_CONTAINER,             // Получение имени ключевого контейнера
    (BYTE *)szUserName,       // Указатель на имя ключевого контейнера
    &dwUserNameLen,           // Длина имени, ограниченная до 100
    0))
{
    printf("A crypto context has been acquired and \n");
    printf("The name on the key container is %s\n\n",szUserName);
}
else
{
    // Ошибка получении имени ключевого контейнера
    HandleError("A context was acquired or created, but\
      an error occurred getting the key container name.\n");
}

//--------------------------------------------------------------------
// Контекст с ключевым контейнером доступен,
// попытка получения дескриптора ключа обмена.

if(CryptGetUserKey(
   hCryptProv,                     // Дескриптор CSP
   AT_SIGNATURE,                   // Спецификация ключа
   &hKey))                         // Дескриптор ключа
{
    printf("A signature key is available.\n");
}
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");
       if(CryptGenKey(
          hCryptProv,
          AT_SIGNATURE,
          0,
          &hKey))
       {
          printf("Created a signature key pair.\n");
       }
       else
       {
          HandleError("Error occurred creating a signature key.\n");
       }
    }
    else
    {
        HandleError("An error other than NTE_NO_KEY getting signature\
            key.\n");
    }
} // Конец if

printf("A signature key pair existed, or one was created.\n\n");
CryptDestroyKey(hKey);

// Следующее, проверка ключа обмена.
if(CryptGetUserKey(
   hCryptProv,
   AT_KEYEXCHANGE,
   &hKey))
{
   printf("An exchange key exists. \n");
}
else
{
     printf("No 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");
       if(CryptGenKey(
           hCryptProv,
           AT_KEYEXCHANGE,
           0,
           &hKey))
       {
           printf("Exchange key pair created.\n");
       }
       else
       {
          HandleError("Error occurred attempting to create \
             an exchange key.\n");
       }
    }
    else
    {
       HandleError("An error other than NTE_NO_KEY occurred.\n");
     }
}

printf("An exchange key pair existed, or one was created.\n\n");
CryptDestroyKey(hKey);
CryptReleaseContext(hCryptProv,0);
printf("Everything is okay. A signature key\n");
printf("pair and an exchange key exist in\n");
printf("the %s key container.\n",UserName);
return 0;
} // Конец main

    Требования:

    Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
    Solaris: 9 Update 4 или выше.
    FreeBSD: FreeBSD 5.2 или выше
    Linux: RedHat 7.3, RedHad 9.0.
    Ядро Windows NT: не поддерживает.


Крипто-Про CSP

Этот пример демонстрирует использование следующих функций
  • CryptAcquireContext в MS CryptoAPI 2.0 World Wide Web link
  • CryptReleaseContext в MS CryptoAPI 2.0 World Wide Web link
  • CryptGetProvParam в MS CryptoAPI 2.0 World Wide Web link

//--------------------------------------------------------------------
//  Пример кода, использующего CryptAcquireContext.

#define MY_ENCODING_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
void HandleError(char *s);

void main(void)
{
//--------------------------------------------------------------------
// Объявление и инициализация переменных.
HCRYPTPROV hCryptProv;
HCRYPTKEY hKey;
BYTE pbData[1000];       // 1000 будет использоваться для наибольшего
                         // по длине имени ключевого контейнера.
DWORD cbData;

//--------------------------------------------------------------------
// Получение дескриптора криптопровайдера.

if(CryptAcquireContext(
    &hCryptProv,
    NULL,
    NULL,
    75,
    0))
{
    printf("CryptAcquireContext succeeded.\n");
}
else
{
        if (GetLastError() == 0x80090016 )
     {
       printf(" The default key container does not exist.\n");
       printf(" Create a default container and generate keys \n");
       printf(" Using the code in \n");
       printf("  Example C Program: Creating a Key Container and Generating Keys \n");
       printf("  Before running this program. \n");
       exit(0);
     }
     else
     {
          HandleError("A genral error runing CryptAcquireContext.");
     }
}

//--------------------------------------------------------------------
// Чтение имени CSP.

cbData = 1000;
if(CryptGetProvParam(
    hCryptProv,
    PP_NAME,
    pbData,
    &cbData,
    0))
{
    printf("CryptGetProvParam succeeded.\n");
    printf("Provider name: %s\n", pbData);
}
else
{
    HandleError("Error reading CSP name. \n");
}
//--------------------------------------------------------------------
// Чтение имени ключевого контейнера.

cbData = 1000;
if(CryptGetProvParam(
    hCryptProv,
    PP_CONTAINER,
    pbData,
    &cbData,
    0))
{
    printf("CryptGetProvParam succeeded. \n");
    printf("Key Container name: %s\n", pbData);
}
else
{
    HandleError("Error reading key container name. \n");
}
//--------------------------------------------------------------------
// Выполнение криптографических операций.
//...

//--------------------------------------------------------------------
//  Увеличение счетчика ссылок на криптопровайдер. Когда счетчик ссылок на
//  криптопровайдер становится больше 1, CryptReleaseContext уменьшает
//  счетчик ссылок, но не освобождает криптопровайдер.

if(CryptContextAddRef(
       hCryptProv,
       NULL,
       0))
{
    printf("CryptcontextAddRef succeeded. \n");
}
else
{
   HandleError("Error during CryptContextAddRef!\n");
}
//--------------------------------------------------------------------
//  Счетчик ссылок на hCryptProv сейчас больше 1. Первый вызов
//  функции CryptReleaseContext не освободит дескриптор криптопровайдера.

//--------------------------------------------------------------------
//  Однократное освобождение контекста.

if (CryptReleaseContext(hCryptProv, 0))
{
    printf("The first call to CryptReleaseContext succeeded. \n");
}
else
{
    HandleError("Error during CryptReleaseContext! #1 \n");
}
//--------------------------------------------------------------------
// Повторное освобождение дескриптора криптопровайдера.

if (CryptReleaseContext(hCryptProv, 0))
{
    printf("The second call to CryptReleaseContext succeeded. \n");
}
else
{
   HandleError("Error during CryptReleaseContext #2 !\n");
}
//--------------------------------------------------------------------
// Получение дескриптора криптопровайдера и
// создание ключевого контейнера с именем "KC1".

if(CryptAcquireContext(
   &hCryptProv,
   "KC1",
   NULL,
   75,
   CRYPT_NEWKEYSET))
{
    printf("CryptAcquireContext succeeded. \n");
    printf("New key set created. \n");
}
else
{
    HandleError("Error during CryptAcquireContext for a new key\
    \ncontainer. A container with this name probably \
    \nalready exists. \n");
}
//--------------------------------------------------------------------
// begin Особенность КриптоПро CSP
// Особенностью КриптоПро CSP является то, что криптопровайдер
// физически не создает (записывает) контейнер, если в нем
// нет закрытых ключей. Поэтому необходимо создать ключ.
if(CryptGenKey(
    hCryptProv,
    AT_SIGNATURE,
    0,
    &hKey))
{
    printf("Created a signature key pair.\n");
}
else
{
    HandleError("Error occurred creating a signature key.\n");
}
CryptDestroyKey( hKey );
// end Особенность КриптоПро CSP

//--------------------------------------------------------------------
// Выполнение криптографических операций.
// ...

//--------------------------------------------------------------------
// Освобождение дескриптора криптопровайдера и ключевого контейнера KC1.

if(CryptReleaseContext(hCryptProv, 0))
{
    printf("CryptReleaseContext succeeded. \n");
}
else
{
    HandleError("Error during CryptReleaseContext!\n");
}
//--------------------------------------------------------------------
// Получение дескриптора криптопровайдера, используя новый ключевой контейнер.
// Замечание: Этот ключевой контейнер будет пустым до тех пор, пока ключи
// не будут явно созданы с помощью функции CryptGenKey.

if(CryptAcquireContext(
   &hCryptProv,
   "KC1",
   NULL,
   75,
   0))
{
     printf("Acquired the key set just created. \n");
}
else
{
    HandleError("Error during CryptAcquireContext!\n");
}
//--------------------------------------------------------------------
// Выполнение криптографических операций.
// ...

//--------------------------------------------------------------------
// Освобождение дескриптора криптопровайдера.
if(CryptReleaseContext(
   hCryptProv,
   0))
{
    printf("CryptReleaseContext succeeded. \n");
}
else
{
    HandleError("Error during CryptReleaseContext!\n");
}
//--------------------------------------------------------------------
// Для повторного испоьзования этого примера необходимо удалить созданный
// ключей контейнер с именем "КС1". Контейнер можно удалить при помощи
// контрольной панели КриптоПро CSP или следующим образом:

if(CryptAcquireContext(
   &hCryptProv,
   "KC1",
   NULL,
   75,
   CRYPT_DELETEKEYSET))
{
    printf("CryptAcquireContext succeeded. \n");
}
else
{
    HandleError("Error during CryptAcquireContext!\n");
}

} // Конец main

    Требования:

    Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
    Solaris: 9 Update 4 или выше.
    FreeBSD: FreeBSD 5.2 или выше
    Linux: RedHat 7.3, RedHad 9.0.
    Ядро Windows NT: не поддерживает.


Крипто-Про CSP

Этот пример демонстрирует использование следующих функций
  • CryptEnumProviderTypes в MS CryptoAPI 2.0 World Wide Web link
  • CryptEnumProviders в MS CryptoAPI 2.0 World Wide Web link
  • CryptGetDefaultProvider в MS CryptoAPI 2.0 World Wide Web link
  • CryptGetProvParam в MS CryptoAPI 2.0 World Wide Web link

//--------------------------------------------------------------------
//  В примере используются функции CryptEnumProviderTypes, CryptEnumProviders,
//  CryptGetDefaultProvider и CryptGetProvParam.
//  Большинство из этих функций доступны только для версий Windows 2000
//  и старше.
//
// Для корректной работы данного примера необходимо предварительно создать
// контейнер с именем "OUR_Container" (например, при помощи программы
// CreatingKeyContainer).
//--------------------------------------------------------------------

void HandleError(char *s);
void Wait(char *s);

int main()
{

//--------------------------------------------------------------------
//  Объявление и инициализация переменных.

HCRYPTPROV hProv;         // Дескриптор CSP
LPTSTR      pszName;
DWORD       dwType;
DWORD       cbName;
DWORD       dwIndex=0;
BYTE        *ptr;
ALG_ID      aiAlgid;
DWORD       dwBits;
DWORD       dwNameLen;
CHAR        szName[100]; // Распределены динамически
BYTE        pbData[1024];// Распределены динамически
DWORD       cbData=1024;
DWORD       dwIncrement = sizeof(DWORD);
DWORD       dwFlags=CRYPT_FIRST;
CHAR        *pszAlgType = NULL;
BOOL        fMore=TRUE;
LPTSTR      pbProvName;
DWORD       cbProvName;

//--------------------------------------------------------------
//   Печать заголовка перечисления типов провайдеров.

printf("\n          Listing Available Provider Types.\n");
printf("Provider type      Provider Type Name\n");
printf("_____________    _____________________________________\n");

// Цикл по перечисляемым типам провайдеров.
dwIndex = 0;
while(CryptEnumProviderTypes(
       dwIndex,     // in -- dwIndex
       NULL,        // in -- pdwReserved- устанавливается в NULL
       0,           // in -- dwFlags -- устанавливается в ноль
       &dwType,     // out -- pdwProvType
       NULL,        // out -- pszProvName -- NULL при первом вызове
       &cbName      // in, out -- pcbProvName
       ))
{

//--------------------------------------------------------------------
//  cbName - длина имени следующего типа провайдера.
//  Распределение памяти в буфере для восстановления этого имени.

pszName = (LPTSTR)malloc(cbName);

if (!pszName)
{
   HandleError("ERROR - malloc failed!");
}

memset(pszName, 0, cbName);

//--------------------------------------------------------------------
//  Получение имени типа провайдера.

if (CryptEnumProviderTypes(
       dwIndex++,
       NULL,
       0,
       &dwType,
       pszName,
       &cbName))
{
    printf ("     %4.0d        %s\n",dwType, pszName);
}
else
{
    HandleError("ERROR - CryptEnumProviders");
}
free(pszName);
}

//--------------------------------------------------------------
//   Печать заголовка перечисления провайдеров.

printf("\n\n          Listing Available Providers.\n");
printf("Provider type      Provider Name\n");
printf("_____________    _____________________________________\n");
//----------------------------------------------------------------
// Цикл по перечисляемым провайдерам.
dwIndex = 0;
while(CryptEnumProviders(
       dwIndex,     // in -- dwIndex
       NULL,        // in -- pdwReserved- устанавливается в NULL
       0,           // in -- dwFlags -- устанавливается в ноль
       &dwType,     // out -- pdwProvType
       NULL,        // out -- pszProvName -- NULL при первом вызове
       &cbName      // in, out -- pcbProvName
       ))
{

//--------------------------------------------------------------------
//  cbName - длина имени следующего провайдера.
//  Распределение памяти в буфере для восстановления этого имени.

pszName = (LPTSTR)malloc(cbName);

if (!pszName)
{
   HandleError("ERROR - malloc failed!");
}

memset(pszName, 0, cbName);

//--------------------------------------------------------------------
//  Получение имени провайдера.

if (CryptEnumProviders(
       dwIndex++,
       NULL,
       0,
       &dwType,
       pszName,
       &cbName     // pcbProvName -- длина pszName
       ))
{
    printf ("     %4.0d        %s\n",dwType, pszName);
}
else
{
    HandleError("ERROR - CryptEnumProviders");
}
free(pszName);

} // Конец цикла while

printf("\n\nProvider types and provider names have been listed.\n");
Wait("Press Enter to continue.");

//-----------------------------------------------------------------
// Получение имени CSP, определенного для компьютера по умолчанию.
//

//---------------------------------------------------------------
// Получение длины имени провайдера по умолчанию.

if (!(CryptGetDefaultProvider(
     75,
     NULL,
     CRYPT_MACHINE_DEFAULT,
     NULL,
     &cbProvName)))
{
   HandleError("Error getting the length of the default provider name.");
}

//---------------------------------------------------------------
// Распределение локальной памяти под имя провайдера по умолчанию.

pbProvName = (LPTSTR)malloc(cbProvName);

if (!pbProvName)
{
    HandleError("Error during memory allocation for provider name.");
}

memset(pbProvName, 0, cbProvName);

//---------------------------------------------------------------
// Получение имени провайдера по умолчанию.

if (CryptGetDefaultProvider(
    75,
    NULL,
    CRYPT_MACHINE_DEFAULT,
    pbProvName,
    &cbProvName))
{
    printf("The default provider name is %s\n\n",pbProvName);
}
else
{
    HandleError("Getting the name of the provider failed.");
}

//-----------------------------------------------------
//  Получение криптографического контекста.

if(!CryptAcquireContext(
   &hProv,
   "OUR_Container",
   NULL,
   75,
   0                // Если контейнер с именем "OUR_Container" существует.
                    // В противном случае необходимо устаносить флаг
                    // CRYPT_NEWKEYSET для создания контейнера с таким именем.
   ))
{
    HandleError("Error during CryptAcquireContext!");
}

//------------------------------------------------------
// Перечисление поддерживаемых алгоритмов.

//------------------------------------------------------
// Печать заголовка таблицы, содержащей информацию об алгоритмах
printf("\n               Enumerating the supported algorithms\n\n");
printf("     Algid      Bits      Type        Name         Algorithm\n");
printf("                                     Length          Name\n");
printf("    ________________________________________________________\n");
while(fMore)
{
//------------------------------------------------------
// Извлечение информации об алгоритме.

    if(CryptGetProvParam(hProv, PP_ENUMALGS, pbData, &cbData, dwFlags))
    {
    //-----------------------------------------------------------
    // Извлечение информации об алгоритме из буфера 'pbData'.

       dwFlags=0;
       ptr = pbData;
       aiAlgid = *(ALG_ID *)ptr;
       ptr += sizeof(ALG_ID);
       dwBits = *(DWORD *)ptr;
       ptr += dwIncrement;
       dwNameLen = *(DWORD *)ptr;
       ptr += dwIncrement;
       strncpy(szName,(char *) ptr, dwNameLen);

     //--------------------------------------------------------
     // Определение типа алгоритма.

   switch(GET_ALG_CLASS(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("    %8.8xh    %-4d    %s     %-2d          %s\n",
        aiAlgid, dwBits, pszAlgType, dwNameLen, szName
    );
}
else
   fMore=FALSE;
}

if(GetLastError() == ERROR_NO_MORE_ITEMS)
{
   printf("\nThe program completed without error.\n");
}
else
{
   HandleError("Error reading algorithm!");
}

} // Конец main

void Wait(char *s)
{
char x;
printf("%s",s);
scanf("%c",&x);
printf("\n\n\n\n\n\n\n\n\n");
}//Конец wait

    Требования:

    Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
    Solaris: 9 Update 4 или выше.
    FreeBSD: FreeBSD 5.2 или выше
    Linux: RedHat 7.3, RedHad 9.0.
    Ядро Windows NT: не поддерживает.


Крипто-Про CSP

Этот пример демонстрирует использование следующих функций
  • CryptAcquireContext в MS CryptoAPI 2.0 World Wide Web link
  • CryptCreateHash в MS CryptoAPI 2.0 World Wide Web link
  • CryptHashData в MS CryptoAPI 2.0 World Wide Web link
  • CryptDeriveKey в MS CryptoAPI 2.0 World Wide Web link
  • CryptReleaseContext в MS CryptoAPI 2.0 World Wide Web link

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

#define MY_ENCODING_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
void HandleError(char *s);

int main()
{

//--------------------------------------------------------------------
//  Объявление и инициализация переменных.

HCRYPTPROV hCryptProv;
HCRYPTKEY hKey;
HCRYPTHASH hHash;
CHAR szPassword[512];
DWORD dwLength;

//--------------------------------------------------------------------
//  Получение пароля от пользователя.

fprintf(stderr,"Enter a password to be used to create a key:");
scanf("%s",szPassword);
fprintf(stderr,"The password is %s .\n", szPassword);
dwLength = (DWORD)strlen(szPassword);

//--------------------------------------------------------------------
// Получение дескриптора контекста криптографического провайдера.

if(CryptAcquireContext(
   &hCryptProv,
   NULL,
   NULL,
   75,
   0))
{
    printf("A context has been acquired. \n");
}
else
{
     HandleError("Error during CryptAcquireContext!");
}
//--------------------------------------------------------------------
// Создание пустого объекта хеширования.

if(CryptCreateHash(
   hCryptProv,
   CALG_GR3411,
   0,
   0,
   &hHash))
{
    printf("An empty hash object has been created. \n");
}
else
{
    HandleError("Error during CryptCreateHash!");
}
//--------------------------------------------------------------------
// Хеширование строки пароля.

if(CryptHashData(
   hHash,
   (BYTE *)szPassword,
   dwLength,
   0))
{
     printf("The password has been hashed. \n");
}
else
{
     HandleError("Error during CryptHashData!");
}
//--------------------------------------------------------------------
// Создание сессионного ключа, основанного на хеше, полученного из пароля.

if(CryptDeriveKey(
   hCryptProv,
   CALG_G28147,
   hHash,
   CRYPT_EXPORTABLE,
   &hKey))
{
    printf("The key has been derived. \n");
}
else
{
    HandleError("Error during CryptDeriveKey!");
}
//--------------------------------------------------------------------
// Использование hKey для зашифрования и расшифрования
// сообщений.

//--------------------------------------------------------------------
// Очистка.

// Уничтожение объекта функции хеширования.

if(hHash)
   CryptDestroyHash(hHash);

// Уничтожение сессионного ключа.
if(hKey)
    CryptDestroyKey(hKey);

// Освобождение дескриптора провайдера.
if(hCryptProv)
   CryptReleaseContext(hCryptProv, 0);
printf("The program to derive a key completed without error. \n");
return 0;
} // Конец main

    Требования:

    Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
    Solaris: 9 Update 4 или выше.
    FreeBSD: FreeBSD 5.2 или выше
    Linux: RedHat 7.3, RedHad 9.0.
    Ядро Windows NT: не поддерживает.


Крипто-Про CSP

Этот пример демонстрирует использование следующих функций
  • CryptAcquireContext в MS CryptoAPI 2.0 World Wide Web link
  • CryptGenKey в MS CryptoAPI 2.0 World Wide Web link
  • CryptDuplicateKey в MS CryptoAPI 2.0 World Wide Web link
  • CryptSetKeyParam в MS CryptoAPI 2.0 World Wide Web link
  • CryptGenRandom в MS CryptoAPI 2.0 World Wide Web link
  • CryptDestroyKey в MS CryptoAPI 2.0 World Wide Web link
  • CryptReleaseContext в MS CryptoAPI 2.0 World Wide Web link

//--------------------------------------------------------------------

#define MY_ENCODING_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
void HandleError(char *s);

//--------------------------------------------------------------------
//   Начало main.

void main()
{
//--------------------------------------------------------------------
// Объявление и инициализация переменных.

HCRYPTPROV   hCryptProv;
HCRYPTKEY    hOriginalKey;
HCRYPTKEY    hDuplicateKey;
DWORD        dwMode;
BYTE         pbData[16];

//--------------------------------------------------------------------
//  Начало выполнения.

printf("This program creates a session key and duplicates \n");
printf("that key. Next, parameters are added to the original \n");
printf("key. Finally, both keys are destroyed. \n\n");

//--------------------------------------------------------------------
// Получение дескриптора контекста криптографического провайдера.

if(CryptAcquireContext(
   &hCryptProv,
   NULL,
   NULL,
   75,
   0))
{
    printf("CryptAcquireContext succeeded. \n");
}
else
{
    HandleError("Error during CryptAcquireContext!\n");
}
//--------------------------------------------------------------------
// Генерация ключа.
if (CryptGenKey(
     hCryptProv,
     CALG_G28147,
     0,
     &hOriginalKey))
{
   printf("Original session key is created. \n");
}
else
{
   HandleError("ERROR - CryptGenKey.");
}
//--------------------------------------------------------------------
// Дублирование ключа.

if (CryptDuplicateKey(
     hOriginalKey,
     NULL,
     0,
     &hDuplicateKey))
{
   printf("The session key has been duplicated. \n");
}
else
{
   HandleError("ERROR - CryptDuplicateKey");
}
//--------------------------------------------------------------------
//  Установка дополнительных параметров исходного ключа.
//  В первую очередь, установка режима шифрования.

dwMode = CRYPT_MODE_ECB;
if(CryptSetKeyParam(
   hOriginalKey,
   KP_MODE,
   (BYTE*)&dwMode,
   0))
{
     printf("Key Parameters set. \n");
}
else
{
     HandleError("Error during CryptSetKeyParam.");
}
// Генерация случайного вектора инициализации.
if(CryptGenRandom(
   hCryptProv,
   8,
   pbData))
{
     printf("Random sequence generated. \n");
}
else
{
     HandleError("Error during CryptGenRandom.");
}
//--------------------------------------------------------------------
// Установка вектора инициализации.
if(CryptSetKeyParam(
   hOriginalKey,
   KP_IV,
   pbData,
   0))
{
     printf("Parameter set with random sequence as initialization vector. \n");
}
else
{
     HandleError("Error during CryptSetKeyParam.");
}
//--------------------------------------------------------------------
// Очистка.

if (hOriginalKey)
    CryptDestroyKey(hOriginalKey);

if (hDuplicateKey)
    CryptDestroyKey(hDuplicateKey);

if(hCryptProv)
    CryptReleaseContext(hCryptProv, 0);

printf("\nThe program ran to completion without error. \n");

} //  Конец main

    Требования:

    Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
    Solaris: 9 Update 4 или выше.
    FreeBSD: FreeBSD 5.2 или выше
    Linux: RedHat 7.3, RedHad 9.0.
    Ядро Windows NT: не поддерживает.


Крипто-Про CSP

Этот пример демонстрирует использование следующих функций
  • CryptAcquireContext в MS CryptoAPI 2.0 World Wide Web link
  • CryptGenRandom в MS CryptoAPI 2.0 World Wide Web link
  • CryptGenKey в MS CryptoAPI 2.0 World Wide Web link
  • CryptGetKeyParam в MS CryptoAPI 2.0 World Wide Web link
  • CryptSetKeyParam в MS CryptoAPI 2.0 World Wide Web link
  • CryptGenRandom в MS CryptoAPI 2.0 World Wide Web link
  • CryptDestroyKey в MS CryptoAPI 2.0 World Wide Web link
  • CryptReleaseContext в MS CryptoAPI 2.0 World Wide Web link

//--------------------------------------------------------------------
// В данном примере осуществляется создание случайного сессионного
// ключа шифрования и изменение одного из его параметров (вектора
// инициализации).
//---------------------------------------------------------------------

void HandleError(char *s);

int main()
{
HCRYPTPROV hProv;
HCRYPTKEY hKey;
DWORD dwMode;
BYTE pbData[16];
BYTE pbRandomData[8];
DWORD dwCount;
DWORD i;

//--------------------------------------------------------------------
// Получение дескриптора контекста криптографического параметра.

if(!CryptAcquireContext(
    &hProv,
    NULL,
    NULL,
    75,
    0))
{
    HandleError("Error during CryptAcquireContext.");
}

//--------------------------------------------------------------
//  Генерация восьми байтов случайных данных в pbRandomData.

if( CryptGenRandom(
   hProv,
   8,
   pbRandomData))
{
     printf("Eight bytes of random data have been generated.\n");
}
else
{
     HandleError("Random bytes were not correctly generated.");
}
// Создание случайного сессионного ключа блочного шифрования.

if(!CryptGenKey(
     hProv,
     CALG_G28147,
     CRYPT_EXPORTABLE,
     &hKey))
{
    HandleError("Error during CryptGenKey.");
}

//--------------------------------------------------------------------
// Чтение режима шифрования.

dwCount = sizeof(DWORD);
if(CryptGetKeyParam(
     hKey,
     KP_MODE,
     (BYTE*)&dwMode,
     &dwCount,
     0))
{
//---------------------------------------------------------------
// Печать режима шифрования.

     printf("Default cipher mode: %d\n", dwMode);

}
else
{
     HandleError("Error during CryptGetKeyParam.");
}

//---------------------------------------------------------------
// Чтение вектора инициализации.

//-------------------------------------------------------------
//  Получение длины вектора инициализации.

if(!CryptGetKeyParam(
    hKey,
    KP_IV,
    NULL,
    &dwCount,
    0))
{
    HandleError("Error getting the IV length");
}

//--------------------------------------------------------------
// Получение IV - вектора инициализации.

if(CryptGetKeyParam(
    hKey,
    KP_IV,
    pbData,
    &dwCount,
    0))
{
     //---------------------------------------------------------
     // Печать вектора инициализации.
     printf("Default IV:");
     for(i=0;i<dwCount;i++)
          printf("%2.2x ",pbData[i]);
     printf("\n");
}
else
{
    HandleError("Error getting the IV.");
}

//-------------------------------------------------------------
//  Переустановка вектора инициализации.

if(CryptSetKeyParam(
   hKey,
   KP_IV,
   pbRandomData,
   0))
{
     printf("New intialization vector is set.\n");
}
else
{
     HandleError("The new IV was not set.");
}
//---------------------------------------------------------------
// Чтение нового вектора инициализации.

//-------------------------------------------------------------
//  Получение длины нового вектора инициализации.

if(!CryptGetKeyParam(
    hKey,
    KP_IV,
    NULL,
    &dwCount,
    0))
{
    HandleError("Error getting the IV length");
}

//--------------------------------------------------------------
// Получение IV - вектора инициализации.

if(CryptGetKeyParam(
    hKey,
    KP_IV,
    pbData,
    &dwCount,
    0))
{
     //---------------------------------------------------------
     // Печать вектора инициализации.
     printf("RE-set IV:");
     for(i=0;i<dwCount;i++)
          printf("%2.2x ",pbData[i]);
     printf("\n");
}
else
{
    HandleError("Error getting the IV.");
}

//-------------------------------------------------------------
//  Очистка.

//-------------------------------------------------------------
//  Уничтожение сессионного ключа.

if(hKey)
{
    CryptDestroyKey(hKey);
}
else
{
     printf("A session key does not exist.\n");
}

//--------------------------------------------------------------
// Освобождение дескриптора провайдера.

if(hProv)
{
    CryptReleaseContext(hProv, 0);
}
else
{
     printf("No context was aquired.\n");
}

printf("\nProgram completing without error.\n\n");

return 0;
} // Конец main

    Требования:

    Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
    Solaris: 9 Update 4 или выше.
    FreeBSD: FreeBSD 5.2 или выше
    Linux: RedHat 7.3, RedHad 9.0.
    Ядро Windows NT: не поддерживает.


Крипто-Про CSP

Этот пример демонстрирует использование следующих функций
  • CryptAcquireContext в MS CryptoAPI 2.0 World Wide Web link
  • CryptGetUserKey в MS CryptoAPI 2.0 World Wide Web link
  • CryptGenKey в MS CryptoAPI 2.0 World Wide Web link
  • CryptExportKey в MS CryptoAPI 2.0 World Wide Web link
  • CryptImportKey в MS CryptoAPI 2.0 World Wide Web link
  • CryptGetKeyParam в MS CryptoAPI 2.0 World Wide Web link
  • CryptDestroyKey в MS CryptoAPI 2.0 World Wide Web link
  • CryptReleaseContext в MS CryptoAPI 2.0 World Wide Web link

//--------------------------------------------------------------------
// В данном примере осуществляется экспортирование сессионного ключа
// при помощи структуры BLOB.
// Для корректной работы этой программы необходимо создать два
// контейнера: получателя (с именем "Responder") и отправителя (c именем
// "Sender").
//--------------------------------------------------------------------

void HandleError(char *s);

int main(void)
{
//--------------------------------------------------------------------
//  Объявление и инициализация переменных.

HCRYPTPROV hProvResponder;     // Дескриптор CSP получателя
HCRYPTPROV hProvSender;        // Дескриптор CSP отправителя
HCRYPTKEY hSessionKey;         // Дескриптор сессионного ключа
HCRYPTKEY hAgreeKey;           // Дескриптор ключа согласования
HCRYPTKEY hResponderKey;       // Дескриптор открытого ключа получателя
HCRYPTKEY hSenderKey;          // Дескриптор открытого ключа отправителя
BYTE *pbKeyBlobSender;         // Указатель на ключевой BLOB отправителя
DWORD dwBlobLenSender;         // Длина ключевого BLOBа отправителя
BYTE *pbKeyBlobResponder;      // Указатель на ключевой BLOB получателя
DWORD dwBlobLenResponder;      // Длина ключевого BLOBа получателя
BYTE *pbKeyBlobSimple;         // Указатель на сессионный ключевой BLOB
DWORD dwBlobLenSimple;         // Длина сессионного ключевого BLOBа

//--------------------------------------------------------------------
// На стороне получателя: отправляем открытый ключ отправителю
//--------------------------------------------------------------------

//--------------------------------------------------------------------
// Получение дескриптора контейнера получателя с именем "Responder",
// находящегося в рамках провайдера.

if(CryptAcquireContext(
   &hProvResponder,
   "Responder",
   NULL,
   75,
   0))
{
    printf("The key container \"Responder\" has been acquired. \n");
}
else
{
    HandleError("Error during CryptAcquireContext.");
}
//--------------------------------------------------------------------
// Получение дескриптора открытого ключа получателя.

if(CryptGetUserKey(
   hProvResponder,
   AT_KEYEXCHANGE,
   &hResponderKey))
{
    printf("The responder public key has been acquired. \n");
}
else
{
    printf("Error during CryptGetUserKey public key.");
}

//--------------------------------------------------------------------
// pbKeyBlobResponder - открытый ключ получателя, передаем его оправителю.
//
//--------------------------------------------------------------------

//--------------------------------------------------------------------
// Определение размера BLOBа открытого ключа и распределение памяти.

if(CryptExportKey(
   hResponderKey,
   0,
   PUBLICKEYBLOB,
   0,
   NULL,
   &dwBlobLenResponder))
{
     printf("Size of the BLOB for the responder public key determined. \n");
}
else
{
     HandleError("Error computing BLOB length.");
}

pbKeyBlobResponder = (BYTE*)malloc(dwBlobLenResponder);

if(pbKeyBlobResponder)
{
    printf("Memory has been allocated for the BLOB. \n");
}
else
{
    HandleError("Out of memory. \n");
}
//--------------------------------------------------------------------
// Экспортирование открытого ключа получателя в BLOB открытого ключа.

if(CryptExportKey(
   hResponderKey,
   0,
   PUBLICKEYBLOB,
   0,
   pbKeyBlobResponder,
   &dwBlobLenResponder))
{
     printf("Contents have been written to the BLOB. \n");
}
else
{
    HandleError("Error during CryptExportKey.");
}

//--------------------------------------------------------------------
// На стороне отправителя: отправляем открытый ключ получателю.
//--------------------------------------------------------------------

// Получение дескриптора контейнера отправителя с именем "Sender",
// находящегося в рамках провайдера.

if(CryptAcquireContext(
   &hProvSender,
   "Sender",
   NULL,
   75,
   0))
{
    printf("The key container \"Sender\" has been acquired. \n");
}
else
{
    HandleError("Error during CryptAcquireContext.");
}
//--------------------------------------------------------------------
// Получение дескриптора открытого ключа отправителя.

if(CryptGetUserKey(
   hProvSender,
   AT_KEYEXCHANGE,
   &hSenderKey))
{
    printf("The sender public key has been acquired. \n");
}
else
{
    printf("Error during CryptGetUserKey public key.");
}

//--------------------------------------------------------------------
// pbKeyBlobSender - открытый ключ отправителя, передаем его получателю.
//
//--------------------------------------------------------------------

//--------------------------------------------------------------------
// Определение размера BLOBа открытого ключа и распределение памяти.

if(CryptExportKey(
   hSenderKey,
   0,
   PUBLICKEYBLOB,
   0,
   NULL,
   &dwBlobLenSender))
{
     printf("Size of the BLOB for the sender public key determined. \n");
}
else
{
     HandleError("Error computing BLOB length.");
}

pbKeyBlobSender = (BYTE*)malloc(dwBlobLenSender);

if(pbKeyBlobSender)
{
    printf("Memory has been allocated for the BLOB. \n");
}
else
{
    HandleError("Out of memory. \n");
}
//--------------------------------------------------------------------
// Экспортирование открытого ключа отправителя в BLOB открытого ключа.

if(CryptExportKey(
   hSenderKey,
   0,
   PUBLICKEYBLOB,
   0,
   pbKeyBlobSender,
   &dwBlobLenSender))
{
     printf("Contents have been written to the BLOB. \n");
}
else
{
    HandleError("Error during CryptExportKey.");
}
//--------------------------------------------------------------------
// Получение ключа согласования импортом открытого ключа получателя
// на открытом ключе отправителя.

if (CryptImportKey(
    hProvSender,
    pbKeyBlobResponder,
    dwBlobLenResponder,
    hSenderKey,
    0,
    &hAgreeKey))
{
    printf("The sender public key has been imported. \n");
}
else
{
    printf("Error during CryptImportKey public key.");
}

//--------------------------------------------------------------------
// Генерация сессионного ключа.

if (CryptGenKey(
    hProvSender,
    CALG_G28147,
    CRYPT_EXPORTABLE,
    &hSessionKey))
{
    printf("Original session key is created. \n");
}
else
{
   HandleError("ERROR -- CryptGenKey.");
}

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

//--------------------------------------------------------------------
// Определение размера BLOBа сессионного ключа и распределение памяти.

if(CryptExportKey(
   hSessionKey,
   hAgreeKey,
   SIMPLEBLOB,
   0,
   NULL,
   &dwBlobLenSimple))
{
     printf("Size of the BLOB for the sender session key determined. \n");
}
else
{
     HandleError("Error computing BLOB length.");
}

pbKeyBlobSimple = (BYTE*)malloc(dwBlobLenSimple);

if(pbKeyBlobSimple)
{
    printf("Memory has been allocated for the BLOB. \n");
}
else
{
    HandleError("Out of memory. \n");
}
//--------------------------------------------------------------------
// Шифрование ключа согласования на сессионном ключе.

if(CryptExportKey(
   hSessionKey,
   hAgreeKey,
   SIMPLEBLOB,
   0,
   pbKeyBlobSimple,
   &dwBlobLenSimple))
{
     printf("Contents have been written to the BLOB. \n");
}
else
{
    HandleError("Error during CryptExportKey.");
}

//--------------------------------------------------------------------
// На стороне получателя: получили зашифрованный сессионный ключ:
// pbKeyBlobSimple, получили открытый ключ: pbKeyBlobSender.
//--------------------------------------------------------------------

// Получение ключа согласования импортом открытого ключа отправителя
// на открытом ключе получателя.

if (CryptImportKey(
    hProvResponder,
    pbKeyBlobSender,
    dwBlobLenSender,
    hResponderKey,
    0,
    &hAgreeKey))
{
    printf("The responder public key has been imported. \n");
}
else
{
    printf("Error during CryptImportKey public key.");
}

// Получение сессионного ключа импортом зашифрованного сессионного ключа
// на ключе Agree.

if (CryptImportKey(
    hProvResponder,
    pbKeyBlobSimple,
    dwBlobLenSimple,
    hAgreeKey,
    0,
    &hSessionKey))
{
    printf("The session key has been imported. \n");
}
else
{
    printf("Error during CryptImportKey session key.");
}

//--------------------------------------------------------------------
//  Освобождение памяти, используемой ключевыми BLOBоми.

free(pbKeyBlobSender);
free(pbKeyBlobResponder);
free(pbKeyBlobSimple);

// Уничтожение сессионного ключа.
if(hSessionKey)
    CryptDestroyKey(hSessionKey);

// Уничтожение ключа согласования.
if(hAgreeKey)
    CryptDestroyKey(hAgreeKey);

// Уничтожение дескриптора открытого ключа получателя.
if(hResponderKey)
     CryptDestroyKey(hResponderKey);

// Уничтожение дескриптора открытого ключа отправителя.
if(hSenderKey)
     CryptDestroyKey(hSenderKey);

// Освобождение дескриптора провайдера.
if(hProvResponder)
   CryptReleaseContext(hProvResponder, 0);
if(hProvSender)
   CryptReleaseContext(hProvSender, 0);

printf("The program ran to completion without error. \n");
return 0;
}// Конец main

    Требования:

    Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
    Solaris: 9 Update 4 или выше.
    FreeBSD: FreeBSD 5.2 или выше
    Linux: RedHat 7.3, RedHad 9.0.
    Ядро Windows NT: не поддерживает.


Крипто-Про CSP

Этот пример демонстрирует использование следующих функций
  • CertOpenStore в MS CryptoAPI 2.0 World Wide Web link
  • CertFindCertificateInStore в MS CryptoAPI 2.0 World Wide Web link
  • CryptAcquireCertificatePrivateKey в MS CryptoAPI 2.0 World Wide Web link
  • CryptImportPublicKeyInfoEx в MS CryptoAPI 2.0 World Wide Web link
  • CryptGetUserKey в MS CryptoAPI 2.0 World Wide Web link
  • CryptGenKey в MS CryptoAPI 2.0 World Wide Web link
  • CryptGetKeyParam в MS CryptoAPI 2.0 World Wide Web link
  • CryptEncrypt в MS CryptoAPI 2.0 World Wide Web link
  • CryptDecrypt в MS CryptoAPI 2.0 World Wide Web link
  • CryptDestroyKey в MS CryptoAPI 2.0 World Wide Web link
  • CryptReleaseContext в MS CryptoAPI 2.0 World Wide Web link
  • CertCloseStore в MS CryptoAPI 2.0 World Wide Web link

//--------------------------------------------------------------------
// В данном примере осуществляется экспортирование сессионного ключа
// при помощи сертификатов получателя и отправителя.
// Для корректной работы этой программы необходимо создать два
// сертификата и добавить их в хранилище сертификатов MY: получателя
// (с именем, содержащим "Responder") и отправителя (c именем, содержащим
// "Sender").
//--------------------------------------------------------------------

void HandleError(char *s);

int main(void)
{
//--------------------------------------------------------------------
//  Объявление и инициализация переменных.
HCERTSTORE hStoreHandle;         // Дескриптор хранилища сертификатов
PCCERT_CONTEXT pCertSender;      // Контекст сертификата отправителя
PCCERT_CONTEXT pCertResponder;   // Контекст сертификата получателя
HCRYPTPROV hProvResponder;       // Дескриптор CSP получателя
HCRYPTPROV hProvSender;          // Дескриптор CSP отправителя
HCRYPTKEY hSenderKey;          // Дескриптор открытого ключа отправителя
HCRYPTKEY hResponderKey;       // Дескриптор открытого ключа получателя
HCRYPTKEY hSessionKey;         // Дескриптор сессионного ключа
HCRYPTKEY hAgreeKey;           // Дескриптор ключа согласования
BYTE *pbKeyBlobSimple;         // Указатель на сессионный ключевой BLOB
DWORD dwBlobLenSimple;         // Длина сессионного ключевого BLOBа
BYTE *pbKeyBlobSender;         // Указатель на ключевой BLOB отправителя
DWORD dwBlobLenSender;         // Длина ключевого BLOBа отправителя
BYTE *pbKeyBlobResponder;      // Указатель на ключевой BLOB получателя
DWORD dwBlobLenResponder;      // Длина ключевого BLOBа получателя
DWORD dwKeySpecSender;
DWORD dwKeySpecResponder;

//--------------------------------------------------------------------
// На стороне отправителя:
//--------------------------------------------------------------------

//--------------------------------------------------------------------
// Открытие системного хранилища сертификатов.

hStoreHandle = CertOpenSystemStore(
   0,
   "MY");

if(hStoreHandle)
{
    printf("The MY store is open. \n");
}
else
{
    HandleError( "Error getting store handle.");
}

//--------------------------------------------------------------------
// Получение контекста сертифика, в названии которого содержится "Sender",
// находящегося в хранилище сертификатов "MY".

pCertSender = CertFindCertificateInStore(
    hStoreHandle,
    X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
    0,
    CERT_FIND_SUBJECT_STR,
    L"Sender",
    NULL);

if (pCertSender)
{
    printf("The \" Sender \" certificate is found. \n");
}
else
{
    HandleError( "Error finding certificate.");
}

//--------------------------------------------------------------------
// Получение дескриптора CSP, включая доступ к связанному с ним ключевому
// контейнеру для контекста сертификата pCertSender.

if(CryptAcquireCertificatePrivateKey(
   pCertSender,
   0,
   NULL,
   &hProvSender,
   &dwKeySpecSender,
   NULL))
{
    printf("The CSP handle has been acquired. \n");
}
else
{
    HandleError("Error during CryptAcquireCertificatePrivateKey.");
}

//--------------------------------------------------------------------
// Поиск сертифика, в названии которого содержится "Responder",
// находящегося в хранилище сертификатов "MY".

pCertResponder = CertFindCertificateInStore(
    hStoreHandle,
    X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
    0,
    CERT_FIND_SUBJECT_STR,
    L"Responder",
    NULL);

if (pCertResponder)
{
    printf("The \" Responder \" certificate is found. \n");
}
else
{
    HandleError( "Error finding certificate.");
}

//--------------------------------------------------------------------
// Получение дескриптора открытого ключа получателя.

if(CryptImportPublicKeyInfoEx(
   hProvSender,
   X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
   &(pCertResponder->pCertInfo->SubjectPublicKeyInfo),
   0,
   0,
   NULL,
   &hResponderKey))
{
    printf("The responder public key has been acquired. \n");
}
else
{
    printf("Error during CryptImportPublicKeyInfoEx public key.");
}

//--------------------------------------------------------------------
// Определение размера BLOBа открытого ключа и распределение памяти.

if(CryptExportKey(
   hResponderKey,
   0,
   PUBLICKEYBLOB,
   0,
   NULL,
   &dwBlobLenResponder))
{
     printf("Size of the BLOB for the responder public key determined. \n");
}
else
{
     HandleError("Error computing BLOB length.");
}

pbKeyBlobResponder = (BYTE*)malloc(dwBlobLenResponder);

if(pbKeyBlobResponder)
{
    printf("Memory has been allocated for the BLOB. \n");
}
else
{
    HandleError("Out of memory. \n");
}
//--------------------------------------------------------------------
// Экспортирование открытого ключа получателя в BLOB открытого ключа.

if(CryptExportKey(
   hResponderKey,
   0,
   PUBLICKEYBLOB,
   0,
   pbKeyBlobResponder,
   &dwBlobLenResponder))
{
     printf("Contents have been written to the BLOB. \n");
}
else
{
    HandleError("Error during CryptExportKey.");
}

//--------------------------------------------------------------------
// Получение дескриптора закрытого ключа отправителя.

if(CryptGetUserKey(
   hProvSender,
   dwKeySpecSender,
   &hSenderKey))
{
    printf("The sender private key has been acquired. \n");
}
else
{
    printf("Error during CryptGetUserKey private key.");
}

//--------------------------------------------------------------------
// Получение ключа согласования импортом открытого ключа получателя из BLOBа
// на закрытом ключе отправителя.

if (CryptImportKey(
    hProvSender,
    pbKeyBlobResponder,
    dwBlobLenResponder,
    hSenderKey,
    0,
    &hAgreeKey))
{
    printf("The responder public key has been imported. \n");
}
else
{
    printf("Error during CryptImportKey public key.");
}

//--------------------------------------------------------------------
// Генерация сессионного ключа.

if (CryptGenKey(
    hProvSender,
    CALG_G28147,
    CRYPT_EXPORTABLE,
    &hSessionKey))
{
    printf("Original session key is created. \n");
}
else
{
   HandleError("ERROR -- CryptGenKey.");
}

//--------------------------------------------------------------------
// pbKeyBlobSimple - зашифрованный сессионный ключ, передаем его получателю
//
//--------------------------------------------------------------------

//--------------------------------------------------------------------
// Определение размера BLOBа сессионного ключа и распределение памяти.

if(CryptExportKey(
   hSessionKey,
   hAgreeKey,
   SIMPLEBLOB,
   0,
   NULL,
   &dwBlobLenSimple))
{
     printf("Size of the BLOB for the sender session key determined. \n");
}
else
{
     HandleError("Error computing BLOB length.");
}

pbKeyBlobSimple = (BYTE*)malloc(dwBlobLenSimple);

if(pbKeyBlobSimple)
{
    printf("Memory has been allocated for the BLOB. \n");
}
else
{
    HandleError("Out of memory. \n");
}
//--------------------------------------------------------------------
// Шифрование сессионного ключа на ключе Agree.

if(CryptExportKey(
   hSessionKey,
   hAgreeKey,
   SIMPLEBLOB,
   0,
   pbKeyBlobSimple,
   &dwBlobLenSimple))
{
     printf("Contents have been written to the BLOB. \n");
}
else
{
    HandleError("Error during CryptExportKey.");
}

//--------------------------------------------------------------------
// Закрытие системного хранилища сертификатов.

if(CertCloseStore(
   hStoreHandle,
   0))
{
    printf("The MY store is closed. \n");
}
else
{
    HandleError( "Error closing store handle.");
}

//--------------------------------------------------------------------
// Уничтожение сессионного ключа.
if(hSessionKey)
    CryptDestroyKey(hSessionKey);

// Уничтожение ключа согласования.
if(hAgreeKey)
    CryptDestroyKey(hAgreeKey);

// Уничтожение дескриптора открытого ключа получателя.
if(hResponderKey)
     CryptDestroyKey(hResponderKey);

// Уничтожение дескриптора закрытого ключа отправителя.
if(hSenderKey)
     CryptDestroyKey(hSenderKey);

// Освобождение дескриптора провайдера.
if(hProvSender)
   CryptReleaseContext(hProvSender, 0);

// Освобождение контекста сертификата.
if(pCertSender)
    CertFreeCertificateContext(pCertSender);

if(pCertResponder)
    CertFreeCertificateContext(pCertResponder);

//  Освобождение памяти, используемой ключевым BLOBом.
free(pbKeyBlobResponder);

//--------------------------------------------------------------------
// На стороне получателя: получили зашифрованный сессионный ключ
// pbKeyBlobSimple.
//--------------------------------------------------------------------

//--------------------------------------------------------------------
// Открытие системного хранилища сертификатов.

hStoreHandle = CertOpenSystemStore(
   0,
   "MY");

if(hStoreHandle)
{
    printf("The MY store is open. \n");
}
else
{
    HandleError( "Error getting store handle.");
}

//--------------------------------------------------------------------
// Получение контекста сертифика, в названии которого содержится "Responder",
// находящегося в хранилище сертификатов "MY".

pCertResponder = CertFindCertificateInStore(
    hStoreHandle,
    X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
    0,
    CERT_FIND_SUBJECT_STR,
    L"Responder",
    NULL);

if (pCertResponder)
{
    printf("The \" Responder \" certificate is found. \n");
}
else
{
    HandleError( "Error finding certificate.");
}

//--------------------------------------------------------------------
// Получение дескриптора CSP, включая доступ к связанному с ним ключевому
// контейнеру для контекста сертификата pCertResponder.

if(CryptAcquireCertificatePrivateKey(
   pCertResponder,
   0,
   NULL,
   &hProvResponder,
   &dwKeySpecResponder,
   NULL))
{
    printf("The CSP handle has been acquired. \n");
}
else
{
    HandleError("Error during CryptAcquireCertificatePrivateKey.");
}

//--------------------------------------------------------------------
// Поиск сертифика, в названии которого содержится "Sender",
// находящегося в хранилище сертификатов "MY".

pCertSender = CertFindCertificateInStore(
    hStoreHandle,
    X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
    0,
    CERT_FIND_SUBJECT_STR,
    L"Sender",
    NULL);

if (pCertSender)
{
    printf("The \" Sender \" certificate is found. \n");
}
else
{
    HandleError( "Error finding certificate.");
}

//--------------------------------------------------------------------
// Получение дескриптора открытого ключа отправителя.

if(CryptImportPublicKeyInfoEx(
   hProvSender,
   X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
   &(pCertSender->pCertInfo->SubjectPublicKeyInfo),
   0,
   0,
   NULL,
   &hSenderKey))
{
    printf("The sender public key has been acquired. \n");
}
else
{
    printf("Error during CryptImportPublicKeyInfoEx public key.");
}

//--------------------------------------------------------------------
// Определение размера BLOBа открытого ключа и распределение памяти.

if(CryptExportKey(
   hSenderKey,
   0,
   PUBLICKEYBLOB,
   0,
   NULL,
   &dwBlobLenSender))
{
     printf("Size of the BLOB for the sender public key determined. \n");
}
else
{
     HandleError("Error computing BLOB length.");
}

pbKeyBlobSender = (BYTE*)malloc(dwBlobLenSender);

if(pbKeyBlobSender)
{
    printf("Memory has been allocated for the BLOB. \n");
}
else
{
    HandleError("Out of memory. \n");
}
//--------------------------------------------------------------------
// Экспортирование открытого ключа отправителя в BLOB открытого ключа.

if(CryptExportKey(
   hSenderKey,
   0,
   PUBLICKEYBLOB,
   0,
   pbKeyBlobSender,
   &dwBlobLenSender))
{
     printf("Contents have been written to the BLOB. \n");
}
else
{
    HandleError("Error during CryptExportKey.");
}

//--------------------------------------------------------------------
// Получение дескриптора закрытого ключа получателя.

if(CryptGetUserKey(
   hProvResponder,
   dwKeySpecResponder,
   &hResponderKey))
{
    printf("The responder private key has been acquired. \n");
}
else
{
    printf("Error during CryptGetUserKey private key.");
}

//--------------------------------------------------------------------
// Получение ключа согласования импортом открытого ключа отправителя из BLOBа
// на закрытом ключе получателя.

if (CryptImportKey(
    hProvResponder,
    pbKeyBlobSender,
    dwBlobLenSender,
    hResponderKey,
    0,
    &hAgreeKey))
{
    printf("The sender public key has been imported. \n");
}
else
{
    printf("Error during CryptImportKey public key.");
}

// Получение сессионного ключа импортом зашифрованного сессионного ключа
// на ключе Agree.

if (CryptImportKey(
    hProvResponder,
    pbKeyBlobSimple,
    dwBlobLenSimple,
    hAgreeKey,
    0,
    &hSessionKey))
{
    printf("The session key has been imported. \n");
}
else
{
    printf("Error during CryptImportKey session key.");
}

//--------------------------------------------------------------------
// Закрытие системного хранилища сертификатов.

if(CertCloseStore(
   hStoreHandle,
   0))
{
    printf("The MY store is closed. \n");
}
else
{
    HandleError( "Error closing store handle.");
}

//--------------------------------------------------------------------
//  Освобождение памяти, используемой ключевыми BLOBами.
free(pbKeyBlobSimple);
free(pbKeyBlobSender);

// Уничтожение дескриптора закрытого ключа получателя.
if(hResponderKey)
     CryptDestroyKey(hResponderKey);

// Уничтожение дескриптора открытого ключа отправителя.
if(hSenderKey)
     CryptDestroyKey(hSenderKey);

// Уничтожение сессионного ключа.
if(hSessionKey)
    CryptDestroyKey(hSessionKey);

// Уничтожение ключа согласования.
if(hAgreeKey)
    CryptDestroyKey(hAgreeKey);

// Освобождение дескриптора провайдера.
if(hProvResponder)
   CryptReleaseContext(hProvResponder, 0);

// Освобождение контекста сертификата.
if(pCertSender)
    CertFreeCertificateContext(pCertSender);

if(pCertResponder)
    CertFreeCertificateContext(pCertResponder);

printf("The program ran to completion without error. \n");
return 0;
}// Конец main

    Требования:

    Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
    Solaris: 9 Update 4 или выше.
    FreeBSD: FreeBSD 5.2 или выше
    Linux: RedHat 7.3, RedHad 9.0.
    Ядро Windows NT: не поддерживает.


Крипто-Про CSP

Этот пример демонстрирует использование следующих функций
  • CryptMsgCalculateEncodedLength в MS CryptoAPI 2.0 World Wide Web link
  • CryptMsgOpenToEncode в MS CryptoAPI 2.0 World Wide Web link
  • CryptMsgUpdate в MS CryptoAPI 2.0 World Wide Web link
  • CryptMsgGetParam в MS CryptoAPI 2.0 World Wide Web link
  • CryptMsgClose в MS CryptoAPI 2.0 World Wide Web link
  • CryptMsgOpenToDecode в MS CryptoAPI 2.0 World Wide Web link
  • CryptMsgUpdate в MS CryptoAPI 2.0 World Wide Web link
  • CryptMsgGetParam в MS CryptoAPI 2.0 World Wide Web link

//--------------------------------------------------------------------
// Пример кода для закодирования и раскодирования сообщения.
//--------------------------------------------------------------------

#define MY_ENCODING_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
void HandleError(char *s);

int main(void)
{
//-------------------------------------------------------------
// Объявление и инициализация переменных. Они получают указатель на
// содержимое сообщения. Эта программа создает содержимое сообщения
// и получает указатель на него. В большинстве случаев, содержимое
// сообщения уже где-то существует и указатель на сообщение устанавливается
// приложением.

HCRYPTMSG hMsg;
BYTE* pbContent;     // Байтовый указатель на сообщение
DWORD cbContent;     // Длина сообщения
DWORD cbEncodedBlob;
BYTE *pbEncodedBlob;

//--------------------------------------------------------------------
//  Следующие ниже переменные используются только в фазе раскодирования.

DWORD cbDecoded;
BYTE *pbDecoded;

//--------------------------------------------------------------------
//  Начало выполнения. Отображение исходного сообщения.

pbContent = (BYTE*) "Security is our only business";
cbContent = (DWORD)(strlen((char *)pbContent)+1);

printf("The original message => %s\n",pbContent);

//--------------------------------------------------------------------
// Получение размера BLOBа закодированного сообщения.

cbEncodedBlob = CryptMsgCalculateEncodedLength(
             MY_ENCODING_TYPE,       // Тип закодированного сообщения
             0,                      // Флаги
             CMSG_DATA,              // Тип сообщения
             NULL,                   // Указатель на структуру
             NULL,                   // Внутренний контекст ID объекта
             cbContent);             // Размер контекста

if(cbEncodedBlob)
{
    printf("The length of the data has been calculated. \n");
}
else
{
    HandleError("Getting cbEncodedBlob length failed");
}
//--------------------------------------------------------------------
// Распределени памяти под закодированный BLOB.

pbEncodedBlob = (BYTE *) malloc(cbEncodedBlob);

if(pbEncodedBlob)
{
   printf("Memory has been allocated for the signed message. \n");
}
else
{
   HandleError("Memory allocation failed");
}
//--------------------------------------------------------------------
// Открытие сообщения для закодирования.

hMsg = CryptMsgOpenToEncode(
          MY_ENCODING_TYPE,        // Тип закодированного сообщения
          0,                       // Флаги
          CMSG_DATA,               // Тип сообщения
          NULL,                    // Указатель на структуру
          NULL,                    // Внутренний контекст ID объекта
          NULL);                   // Потоковая информация (не используется)

if(hMsg)
{
    printf("The message to be encoded has been opened. \n");
}
else
{
     HandleError("OpenToEncode failed");
}
//--------------------------------------------------------------------
// Обновление сообщения с данными.

if(CryptMsgUpdate(
        hMsg,         // Дескриптор сообщения
        pbContent,    // Указатель на содержимое
        cbContent,    // Размер содержимого
        TRUE))        // Последний вызов
{
     printf("Content has been added to the encoded message. \n");
}
else
{
      HandleError("MsgUpdate failed");
}
//--------------------------------------------------------------------
// Получение результирующего сообщения.

if(CryptMsgGetParam(
               hMsg,                      // Дескриптор сообщения
               CMSG_BARE_CONTENT_PARAM,   // Тип параметров
               0,                         // Индекс
               pbEncodedBlob,             // Указатель на BLOB
               &cbEncodedBlob))           // Размер BLOBа
{
    printf("Message encoded successfully. \n");
}
else
{
      HandleError("MsgGetParam failed");
}
//--------------------------------------------------------------------
// pbEncodedBlob сейчас указывает на закодированное, подписанное содержимое.

//--------------------------------------------------------------------
// Закрытие сообщения.

if(hMsg)
    CryptMsgClose(hMsg);

//--------------------------------------------------------------------
// Нижеследующий код осуществляет раскодирование сообщения.
// Этот код может быть включен здесь или может быть использован в
// автономной программе, если сообщение, подлежащее раскодированию,
// и его длина заданы.
// BLOB закодированного сообщения и его длина могут быть прочитаны
// с дискового файла или могут быть получены из e-mail сообщения или
// из других входных данных.

//--------------------------------------------------------------------
// Открытие сообщения для раскодирования.

hMsg = CryptMsgOpenToDecode(
               MY_ENCODING_TYPE,      // тип закодированного сообщения.
               0,                     // Флаги.
               CMSG_DATA,             // Поиск данных сообщения.
               0,                     // Криптографический провайдер.
               NULL,                  // Информация издателя.
               NULL);                 // потоковая информация.

if(hMsg)
{
     printf("The message to decode is open. \n");
}
else
{
    HandleError("OpenToDecode failed");
}
//--------------------------------------------------------------------
// Обновление сообщения с закодированным BLOBом.
// И pbEncodedBlob, закодированные данные,
// и cbEncodedBlob, длина закодированных данных,
// должны быть доступны.

printf("\nThe length of the encoded message is %d.\n\n",cbEncodedBlob);

if(CryptMsgUpdate(
    hMsg,                 // Дескриптор сообщения
    pbEncodedBlob,        // Указатель на закодированный BLOB
    cbEncodedBlob,        // Размер закодированного BLOBа
    TRUE))                // Последний вызов
{
      printf("The encoded BLOB has been added to the message. \n");
}
else
{
    HandleError("Decode MsgUpdate failed");
}
//--------------------------------------------------------------------
// Получение размера содержимого.

if(CryptMsgGetParam(
                  hMsg,                  // Дескриптор сообщения
                  CMSG_CONTENT_PARAM,    // Тип параметров
                  0,                     // Индекс
                  NULL,                  // Адрес возвращаемой
                                         // информации
                  &cbDecoded))           // Размер возвращаемой
                                         // информации
{
    printf("The decoded message size is %d. \n", cbDecoded);
}
else
{
    HandleError("Decode CMSG_CONTENT_PARAM failed");
}
//--------------------------------------------------------------------
// Распределение памяти.

pbDecoded = (BYTE *) malloc(cbDecoded);

if(pbDecoded)
{
     printf("Memory has been allocated for the decoded message.\n");
}
else
{
    HandleError("Decoding memory allocation failed.");
}
//--------------------------------------------------------------------
// Получение указателя на содержимое.

if(CryptMsgGetParam(
                  hMsg,                  // Дескриптор сообщения
                  CMSG_CONTENT_PARAM,    // Тип параметров
                  0,                     // Индекс
                  pbDecoded,             // Адрес возвращаемой
                                         // информации
                  &cbDecoded))           // Размер возвращаемой
                                         // информации
{
     printf("The message is %s.\n",(LPSTR)pbDecoded);
}
else
{
     HandleError("Decode CMSG_CONTENT_PARAM #2 failed");
}
//--------------------------------------------------------------------
// Освобождение.

if(pbEncodedBlob)
   free(pbEncodedBlob);
if(pbDecoded)
   free(pbDecoded);
if(hMsg)
    CryptMsgClose(hMsg);

printf("This program ran to completion without error. \n");
return 0;
} //  Конец main

    Требования:

    Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
    Solaris: 9 Update 4 или выше.
    FreeBSD: FreeBSD 5.2 или выше
    Linux: RedHat 7.3, RedHad 9.0.
    Ядро Windows NT: не поддерживает.


Крипто-Про CSP

Этот пример демонстрирует использование следующих функций
  • CryptAcquireContext в MS CryptoAPI 2.0 World Wide Web link
  • CryptGetProvParam в MS CryptoAPI 2.0 World Wide Web link
  • CryptSetProvParam в MS CryptoAPI 2.0 World Wide Web link
  • CryptExportKey в MS CryptoAPI 2.0 World Wide Web link
  • CryptImportKey в MS CryptoAPI 2.0 World Wide Web link
  • CryptGetKeyParam в MS CryptoAPI 2.0 World Wide Web link
  • CryptSetKeyParam в MS CryptoAPI 2.0 World Wide Web link
  • CryptDestroyKey в MS CryptoAPI 2.0 World Wide Web link
  • CryptReleaseContext в MS CryptoAPI 2.0 World Wide Web link

//--------------------------------------------------------------------
// В данном примере реализовано копирование закрытого ключа AT_KEYEXCHANGE.
// Копирование ключа AT_SIGNATURE производится аналогично. Необходимо также
// произвести копирование соответствующих этим ключам сертификатов.
// Для корректной работы этой программы копируемые ключи должны быть
// созданы как exportable. Копирование ключа производится из контейнера
// с именем "Source" (который, соответственно, должен быть создан) в
// создаваемый контейнер с именем "Destination" (который, если он имеется,
// до начала работы программы должен быть удален).
//--------------------------------------------------------------------

void HandleError(char *s);

void main (void)
{
//--------------------------------------------------------------------
//  Объявление и инициализация переменных.

HCRYPTPROV hProvResponder;     // Дескриптор CSP получателя
HCRYPTPROV hProvSender;        // Дескриптор CSP отправителя
DWORD dwProvType = 75; // Тип провайдера по умолчанию
DWORD data_len = 0;            // Длина буфера
BYTE *oid = NULL;              // Буфер для хранения параметров
HCRYPTKEY hSenderKey;          // Дескриптор копирумого ключа AT_EXCHANGE
HCRYPTKEY hResponderKey;       // Дескриптор полученного ключа AT_EXCHANGE
HCRYPTKEY hSenderEphemKey;     // Дескриптор эфемерного ключа для отправителя
HCRYPTKEY hResponderEphemKey;     // Дескриптор эфемерного ключа для получателя
HCRYPTKEY hSenderAgreeKey;      // Дескриптор ключа согласования отправителя
HCRYPTKEY hResponderAgreeKey;   // Дескриптор ключа согласования получателя
DWORD dwBlobLen = 0;            // Длина ключевого BLOBа
BYTE *pbKeyBlob = NULL;         // Указатель на ключевой BLOB
DWORD cAlg = CALG_PRO_EXPORT;

//--------------------------------------------------------------------
// Получение дескриптора контейнера, в который осуществляется копирование
// ключа (получатель).

if(CryptAcquireContext(
   &hProvResponder,
   "Destination",
   NULL,
   dwProvType,
   CRYPT_NEWKEYSET))
{
    printf("The responder key container has been acquired. \n");
}
else
{
    HandleError("Error during CryptAcquireContext.");
}

//--------------------------------------------------------------------
// Получение дескриптора контейнера, из которого осуществляется копирование
// ключа (отправитель).

if(CryptAcquireContext(
   &hProvSender,
   "Source",
   NULL,
   dwProvType,
   0))
{
    printf("The sender key container has been acquired. \n");
}
else
{
    HandleError("Error during CryptAcquireContext.");
}

//--------------------------------------------------------------------
// Копирование параметров контейнера-отправителя в контейнер-получатель
// для параметра PP_HASHOID.

//--------------------------------------------------------------------
// Определение размера буфера и распределение памяти.

if(CryptGetProvParam(
   hProvSender,
   PP_HASHOID,
   NULL,
   &data_len,
   0))
{
     printf("Size of the buffer determined. \n");
}
else
{
     HandleError("Error computing buffer length.");
}

oid = malloc( data_len );

if( oid )
{
    printf("Memory has been allocated for the buffer. \n");
}
else
{
    HandleError("Out of memory. \n");
}

//--------------------------------------------------------------------
// Копирование параметров контейнера-отправителя в буфер.

if(CryptGetProvParam(
   hProvSender,
   PP_HASHOID,
   oid,
   &data_len,
   0))
{
     printf("Parameters have been written to the buffer. \n");
}
else
{
    HandleError("Error during CryptGetProvParam.");
}

//--------------------------------------------------------------------
// Установка параметров, находящихся в буфере, получателем.

if(CryptSetProvParam(
   hProvResponder,
   PP_HASHOID,
   oid,
   0 ))
{
    printf("The parameters have been set. \n");
}
else
{
    HandleError("Error during CryptSetProvParam.");
}

//--------------------------------------------------------------------
//  Освобождение памяти, используемой буфером.
free( oid );

// Обнуление длины буфера для повторного использования.
data_len = 0;

//--------------------------------------------------------------------
// Копирование параметров контейнера-отправителя в контейнер-получатель
// для параметра PP_CIPHEROID.

//--------------------------------------------------------------------
// Определение размера буфера и распределение памяти.

if(CryptGetProvParam(
   hProvSender,
   PP_CIPHEROID,
   NULL,
   &data_len,
   0))
{
     printf("Size of the buffer determined. \n");
}
else
{
     HandleError("Error computing buffer length.");
}

oid = malloc( data_len );

if( oid )
{
    printf("Memory has been allocated for the buffer. \n");
}
else
{
    HandleError("Out of memory. \n");
}

//--------------------------------------------------------------------
// Копирование параметров контейнера-отправителя в буфер.

if(CryptGetProvParam(
   hProvSender,
   PP_CIPHEROID,
   oid,
   &data_len,
   0))
{
     printf("Parameters have been written to the buffer. \n");
}
else
{
    HandleError("Error during CryptGetProvParam.");
}

//--------------------------------------------------------------------
// Установка параметров, находящихся в буфере, получателем.

if(CryptSetProvParam(
   hProvResponder,
   PP_CIPHEROID,
   oid,
   0 ))
{
    printf("The parameters have been set. \n");
}
else
{
    HandleError("Error during CryptSetProvParam.");
}

//--------------------------------------------------------------------
//  Освобождение памяти, используемой буфером.

free( oid );

//--------------------------------------------------------------------
// Получение дескриптора закрытого ключа, который будет скопирован.
if ( CryptGetUserKey(
    hProvSender,
    AT_KEYEXCHANGE,
    &hSenderKey ))
{
    printf("The sender private key has been acquired. \n");
}
else
{
    HandleError("Error during CryptGetUserKey private key.");
}

//--------------------------------------------------------------------
// Генерация эфемерного ключа в контейнере-отправителе.

if(CryptGenKey(
   hProvSender,
   CALG_DH_EX_EPHEM,
   CRYPT_EXPORTABLE,
   &hSenderEphemKey))
{
    printf("Ephemeral sender key is created. \n");
}
else
{
   HandleError("ERROR -- CryptGenKey.");
}

//--------------------------------------------------------------------
// Генерация эфемерного ключа в контейнере-получателе.

if(CryptGenKey(
   hProvResponder,
   CALG_DH_EX_EPHEM,
   CRYPT_EXPORTABLE | CRYPT_PREGEN,
   &hResponderEphemKey))
{
    printf("Ephemeral responder key is created. \n");
}
else
{
   HandleError("ERROR -- CryptGenKey.");
}

//--------------------------------------------------------------------
// Согласование параметра KP_DHOID, вырабатываемого в алгоритме
// Диффи-Хелмана.
//--------------------------------------------------------------------

//--------------------------------------------------------------------
// Определение размера BLOBа и распределение памяти.

if(CryptGetKeyParam(
   hSenderEphemKey,
   KP_DHOID,
   NULL,
   &dwBlobLen,
   0))
{
     printf("Size of the BLOB determined. \n");
}
else
{
     HandleError("Error computing BLOB length.");
}

pbKeyBlob = (BYTE*)malloc(dwBlobLen);

if(pbKeyBlob)
{
    printf("Memory has been allocated for the BLOB. \n");
}
else
{
    HandleError("Out of memory. \n");
}

//--------------------------------------------------------------------
// Копирование параметров ключа в BLOB.

if(CryptGetKeyParam(
   hSenderEphemKey,
   KP_DHOID,
   pbKeyBlob,
   &dwBlobLen,
   0))
{
     printf("Parameters have been written to the BLOB. \n");
}
else
{
    HandleError("Error during CryptGetProvParam.");
}

//--------------------------------------------------------------------
// Копирование параметров в hResponderEphemKey.

if(CryptSetKeyParam(
   hResponderEphemKey,
   KP_DHOID,
   pbKeyBlob,
   0))
{
    printf("The parameters have been set. \n");
}
else
{
    HandleError("Error during CryptSetProvParam.");
}

//--------------------------------------------------------------------
//  Освобождение памяти, используемой BLOBом.
free(pbKeyBlob);
pbKeyBlob = NULL;
dwBlobLen = 0;

//--------------------------------------------------------------------
// Генерация ключа

if(CryptSetKeyParam(
   hResponderEphemKey,
   KP_X,
   NULL,
   0))
{
    printf("X parameter is generated. \n");
}
else
{
   HandleError("Error during CryptSetKeyParam.");
}

//--------------------------------------------------------------------
// Получение ключа согласования в контейнере - получателе.
//--------------------------------------------------------------------

//--------------------------------------------------------------------
// Определение размера BLOBа эфемерного ключа и распределение памяти.

if(CryptExportKey(
   hSenderEphemKey,
   0,
   PUBLICKEYBLOB,
   0,
   NULL,
   &dwBlobLen ))
{
     printf("Size of the BLOB for the sender ephemeral key determined. \n");
}
else
{
     HandleError("Error computing BLOB length.");
}

pbKeyBlob = (BYTE*)malloc(dwBlobLen);

if(pbKeyBlob)
{
    printf("Memory has been allocated for the BLOB. \n");
}
else
{
    HandleError("Out of memory. \n");
}
//--------------------------------------------------------------------
// Экспортирование эфемерного ключа отправителя в BLOB.

if(CryptExportKey(
   hSenderEphemKey,
   0,
   PUBLICKEYBLOB,
   0,
   pbKeyBlob,
   &dwBlobLen ))
{
     printf("Contents have been written to the BLOB. \n");
}
else
{
    HandleError("Error during CryptExportKey.");
}

//--------------------------------------------------------------------
// Получение ключа согласования получателя импортом эфемерного ключа отправителя
// на эфемерном ключе получателя.

if (CryptImportKey(
    hProvResponder,
    pbKeyBlob,
    dwBlobLen,
    hResponderEphemKey,
    0,
    &hResponderAgreeKey))
{
    printf("The sender ephemeral key has been imported. \n");
}
else
{
   HandleError("Error during CryptImportKey ephemeral key.");
}

//--------------------------------------------------------------------
//  Освобождение памяти, используемой BLOBом.
free(pbKeyBlob);
pbKeyBlob = NULL;
dwBlobLen = 0;

//--------------------------------------------------------------------
// Получение ключа согласования в контейнере - отправителе.
//--------------------------------------------------------------------

//--------------------------------------------------------------------
// Определение размера BLOBа эфемерного ключа и распределение памяти.

if(CryptExportKey(
   hResponderEphemKey,
   0,
   PUBLICKEYBLOB,
   0,
   NULL,
   &dwBlobLen ))
{
     printf("Size of the BLOB for the responder ephemeral key determined. \n");
}
else
{
     HandleError("Error computing BLOB length.");
}

pbKeyBlob = (BYTE*)malloc(dwBlobLen);

if(pbKeyBlob)
{
    printf("Memory has been allocated for the BLOB. \n");
}
else
{
    HandleError("Out of memory. \n");
}
//--------------------------------------------------------------------
// Экспортирование эфемерного ключа получателя в BLOB.

if(CryptExportKey(
   hResponderEphemKey,
   0,
   PUBLICKEYBLOB,
   0,
   pbKeyBlob,
   &dwBlobLen ))
{
     printf("Contents have been written to the BLOB. \n");
}
else
{
    HandleError("Error during CryptExportKey.");
}

//--------------------------------------------------------------------
// Получение ключа согласования получателя импортом эфемерного ключа получателя
// на эфемерном ключе отправителя.

if (CryptImportKey(
    hProvSender,
    pbKeyBlob,
    dwBlobLen,
    hSenderEphemKey,
    0,
    &hSenderAgreeKey))
{
    printf("The responder ephemeral key has been imported. \n");
}
else
{
    HandleError("Error during CryptImportKey ephemeral key.");
}

//--------------------------------------------------------------------
//  Освобождение памяти, используемой BLOBом.
free(pbKeyBlob);
pbKeyBlob = NULL;
dwBlobLen = 0;

//--------------------------------------------------------------------
// Конвертирование ключа согласования в сессионный в контейнере - отправителе.

if(CryptSetKeyParam(
   hSenderAgreeKey,
   KP_ALGID,
   (BYTE*)&cAlg,
   0 ))
{
    printf("The sender agree key has been converted. \n");
}
else
{
    HandleError("Error during CryptSetKeyParam agree key.");
}

//--------------------------------------------------------------------
// Конвертирование ключа согласования в сессионный в контейнере - получателе.

if(CryptSetKeyParam(
   hResponderAgreeKey,
   KP_ALGID,
   (BYTE*)&cAlg,
   0 ))
{
    printf("The responder agree key has been converted. \n");
}
else
{
    HandleError("Error during CryptSetKeyParam agree key.");
}

//--------------------------------------------------------------------
// Экспорт копируемого пользовательского ключа  на сессионном.
//--------------------------------------------------------------------

//--------------------------------------------------------------------
// Определение размера BLOBа ключа и распределение памяти.

if(CryptExportKey(
   hSenderKey,
   hSenderAgreeKey,
   PRIVATEKEYBLOB,
   0,
   NULL,
   &dwBlobLen ))
{
     printf("Size of the BLOB for the sender key determined. \n");
}
else
{
     HandleError("Error computing BLOB length.");
}

pbKeyBlob = (BYTE*)malloc(dwBlobLen);

if(pbKeyBlob)
{
    printf("Memory has been allocated for the BLOB. \n");
}
else
{
    HandleError("Out of memory. \n");
}
//--------------------------------------------------------------------
// Экспорт копируемого пользовательского ключа  на сессионном.

if(CryptExportKey(
   hSenderKey,
   hSenderAgreeKey,
   PRIVATEKEYBLOB,
   0,
   pbKeyBlob,
   &dwBlobLen ))
{
     printf("Contents have been written to the BLOB. \n");
}
else
{
    HandleError("Error during CryptExportKey.");
}

//--------------------------------------------------------------------
// Получение копируемого ключа импортом пользовательского ключа на ключе
// согласования.

if (CryptImportKey(
    hProvResponder,
    pbKeyBlob,
    dwBlobLen,
    hResponderAgreeKey,
    0,
    &hResponderKey))
{
    printf("The private key has been imported. \n");
}
else
{
    printf("Error during CryptImportKey private key.");
}

//--------------------------------------------------------------------
//  Освобождение памяти, используемой BLOBом.
free(pbKeyBlob);
pbKeyBlob = NULL;
dwBlobLen = 0;

//--------------------------------------------------------------------
// Копирование параметров ключа hSenderKey в параметры ключа hResponderKey
// для KP_CERTIFICATE.

//--------------------------------------------------------------------
// Определение размера BLOBа и распределение памяти.

if(CryptGetKeyParam(
   hSenderKey,
   KP_CERTIFICATE,
   NULL,
   &dwBlobLen,
   0))
{
     printf("Size of the BLOB determined. \n");
}
else
{
     HandleError("Error computing BLOB length.");
}

pbKeyBlob = (BYTE*)malloc(dwBlobLen);

if(pbKeyBlob)
{
    printf("Memory has been allocated for the BLOB. \n");
}
else
{
    HandleError("Out of memory. \n");
}

//--------------------------------------------------------------------
// Копирование параметров ключа в BLOB.

if(CryptGetKeyParam(
   hSenderKey,
   KP_CERTIFICATE,
   pbKeyBlob,
   &dwBlobLen,
   0))
{
     printf("Parameters have been written to the BLOB. \n");
}
else
{
    HandleError("Error during CryptGetProvParam.");
}

//--------------------------------------------------------------------
// Копирование параметров в hResponderKey.

if(CryptSetKeyParam(
   hResponderKey,
   KP_CERTIFICATE,
   pbKeyBlob,
   0))
{
    printf("The parameters have been set. \n");
}
else
{
    HandleError("Error during CryptSetProvParam.");
}

//--------------------------------------------------------------------
//  Освобождение памяти, используемой BLOBом.
free(pbKeyBlob);
pbKeyBlob = NULL;
dwBlobLen = 0;

// Освобождение дескриптора провайдера.
if(hProvResponder)
   CryptReleaseContext(hProvResponder, 0);
if(hProvSender)
   CryptReleaseContext(hProvSender, 0);

// Уничтожение дескрипторов ключей.
if(hSenderKey)
    CryptDestroyKey(hSenderKey);

if(hResponderKey)
    CryptDestroyKey(hResponderKey);

if(hSenderEphemKey)
    CryptDestroyKey(hSenderEphemKey);

if(hResponderEphemKey)
    CryptDestroyKey(hResponderEphemKey);

if(hSenderAgreeKey)
    CryptDestroyKey(hSenderAgreeKey);

if(hResponderAgreeKey)
    CryptDestroyKey(hResponderAgreeKey);
}// Конец main

    Требования:

    Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
    Solaris: 9 Update 4 или выше.
    FreeBSD: FreeBSD 5.2 или выше
    Linux: RedHat 7.3, RedHad 9.0.
    Ядро Windows NT: не поддерживает.


Крипто-Про CSP

Этот пример демонстрирует использование следующих функций
  • CryptAcquireContext в MS CryptoAPI 2.0 World Wide Web link
  • CryptGetProvParam в MS CryptoAPI 2.0 World Wide Web link
  • CryptGetUserKey в MS CryptoAPI 2.0 World Wide Web link
  • CryptDestroyKey в MS CryptoAPI 2.0 World Wide Web link
  • CryptReleaseContext в MS CryptoAPI 2.0 World Wide Web link

//--------------------------------------------------------------------
// Пример кода для работы в режиме SILENT, без окон.
// В данном примере осуществляется подпись строки.
// Для корректной работы этой программы необходимо создать контейнер с
// именем "Source" и с паролем "1234". При этом в контейнере должны
// существовать оба ключа (ключ обмена и ключ подписи).
//--------------------------------------------------------------------

void HandleError(char *s);

int main(void)
{
//--------------------------------------------------------------------
// Объявление и инициализация переменных.

HCRYPTPROV hProv;               // Дескриптор CSP
HCRYPTKEY hKey;                 // Дескриптор ключа
BYTE *pbBuffer= (BYTE *)"The data that is to be hashed and signed.";
DWORD dwBufferLen = (DWORD)(strlen((char *)pbBuffer)+1);
BYTE *pbHash;
DWORD cbHash;
HCRYPTHASH hHash;
BYTE *pbKeyBlob;
BYTE *pbSignature;
DWORD dwSigLen;
DWORD dwBlobLen;
FILE *signature;

//--------------------------------------------------------------------
// Получение дескриптора провайдера.

if(CryptAcquireContext(
    &hProv,
    "\\\\.\\Registry\\Source",
    NULL,
    75,
    CRYPT_SILENT))
{
    printf("CryptAcquireContext succeeded.\n");
}
else
{
        if (GetLastError() == 0x80090016 )
     {
       printf(" The key container with name \"Source\" does not exist.\n");
       printf(" Create a container and generate keys \n");
       exit(0);
     }
     else
     {
          HandleError("A genral error runing CryptAcquireContext.");
     }
}

//--------------------------------------------------------------------
// Установка параметров в соответствии с паролем.

if(CryptSetProvParam(
   hProv,
   PP_KEYEXCHANGE_PIN,
   (BYTE*)"1234",
   0))
{
    printf("CryptSetProvParam succeeded.\n");
}
else
{
    HandleError("Error during CryptSetProvParam.");
}

//--------------------------------------------------------------------
// Получение ключа пользователя.

if(CryptGetUserKey(
   hProv,
   AT_KEYEXCHANGE,
   &hKey))
{
    printf("CryptGetUserKey succeeded.\n");
}
else
{
    HandleError("Error during CryptGetUserKey.");
}

//--------------------------------------------------------------------
// Экпорт открытого ключа. Здесь открытый ключ экспортируется в
// PUBLICKEYBOLB для того, чтобы получатель подписанного хеша мог
// проверить подпись. Этот BLOB может быть записан в файл и передан
// другому пользователю.

if(CryptExportKey(
   hKey,
   0,
   PUBLICKEYBLOB,
   0,
   NULL,
   &dwBlobLen))
{
     printf("Size of the BLOB for the public key determined. \n");
}
else
{
     if (GetLastError() == 0x8009000b )
     {
       printf(" The password of key container is differ from \"1234\".\n");
       exit(0);
     }
     else
     {
        HandleError("Error computing BLOB length.");
     }
}

//--------------------------------------------------------------------
// Распределение памяти под pbKeyBlob.

pbKeyBlob = (BYTE*)malloc(dwBlobLen);

if(pbKeyBlob)
{
    printf("Memory has been allocated for the BLOB. \n");
}
else
{
    HandleError("Out of memory. \n");
}
//--------------------------------------------------------------------
// Сам экспорт в ключевой BLOB.

if(CryptExportKey(
   hKey,
   0,
   PUBLICKEYBLOB,
   0,
   pbKeyBlob,
   &dwBlobLen))
{
     printf("Contents have been written to the BLOB. \n");
}
else
{
    HandleError("Error during CryptExportKey.");
}
//--------------------------------------------------------------------
// Создание объекта функции хеширования.

if(CryptCreateHash(
   hProv,
   CALG_GR3411,
   0,
   0,
   &hHash))
{
     printf("Hash object created. \n");
}
else
{
    HandleError("Error during CryptCreateHash.");
}

//--------------------------------------------------------------------
// Передача параметра HP_OID объекта функции хеширования.
//--------------------------------------------------------------------

//--------------------------------------------------------------------
// Определение размера BLOBа и распределение памяти.

if(CryptGetHashParam(hHash,
   HP_OID,
   NULL,
   &cbHash,
   0))
{
     printf("Size of the BLOB determined. \n");
}
else
{
     HandleError("Error computing BLOB length.");
}

pbHash = (BYTE*)malloc(cbHash);

if(pbHash)
{
    printf("Memory has been allocated for the pbHash. \n");
}
else
{
    HandleError("Out of memory. \n");
}

//--------------------------------------------------------------------
// Копирование параметра HP_OID в pbHash.

if(CryptGetHashParam(hHash,
   HP_OID,
   pbHash,
   &cbHash,
   0))
{
     printf("Parameters have been written to the pbHash. \n");
}
else
{
    HandleError("Error during CryptGetHashParam.");
}

//--------------------------------------------------------------------
// Вычисление криптографического хеша буфера.

if(CryptHashData(
   hHash,
   pbBuffer,
   dwBufferLen,
   0))
{
     printf("The data buffer has been hashed.\n");
}
else
{
     HandleError("Error during CryptHashData.");
}
//--------------------------------------------------------------------
// Определение размера подписи и распределение памяти.

dwSigLen= 0;
if(CryptSignHash(
   hHash,
   AT_SIGNATURE,
   NULL,
   0,
   NULL,
   &dwSigLen))
{
     printf("Signature length %d found.\n",dwSigLen);
}
else
{
     HandleError("Error during CryptSignHash.");
}
//--------------------------------------------------------------------
// Распределение памяти под буфер подписи.

pbSignature = (BYTE *)malloc(dwSigLen);

if(pbSignature)
{
     printf("Memory allocated for the signature.\n");
}
else
{
     HandleError("Out of memory.");
}
//--------------------------------------------------------------------
// Подпись объекта функции хеширования.

if(CryptSignHash(
   hHash,
   AT_SIGNATURE,
   NULL,
   0,
   pbSignature,
   &dwSigLen))
{
     printf("pbSignature is the hash signature.\n");
}
else
{
     HandleError("Error during CryptSignHash.");
}

signature = fopen( "signature.txt", "w+b" );

if(!signature)
    HandleError( "Problem opening the file\n" );

fwrite (pbSignature, 1, dwSigLen, signature);

//--------------------------------------------------------------------
// Уничтожение объекта функции хеширования.

if(hHash)
  CryptDestroyHash(hHash);

printf("The hash object has been destroyed.\n");
printf("The signature is created.\n\n");

// Уничтожение дескриптора ключа пользователя.

if(hKey)
     CryptDestroyKey(hKey);

// Освобождение дескриптора провайдера.

if(hProv)
   CryptReleaseContext(hProv, 0);

printf("The program ran to completion without error. \n");
return 0;
} // Конец main

    Требования:

    Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
    Solaris: 9 Update 4 или выше.
    FreeBSD: FreeBSD 5.2 или выше
    Linux: RedHat 7.3, RedHad 9.0.
    Ядро Windows NT: не поддерживает.


Крипто-Про CSP

Этот пример демонстрирует использование следующих функций
  • CPAcquireContext
  • CPReleaseContext

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

#include <string.h>
#include <wincsp.h>
void HandleError(char *s);

void WINAPI FunReturnHWnd( HWND *hwnd )
{
    *hwnd = 0;
}

BOOL WINAPI FunVerifyImage( LPCSTR szImage, CONST BYTE *pbSigData )
{
    UNREFERENCED_PARAMETER( szImage );
    UNREFERENCED_PARAMETER( pbSigData );
    return TRUE;
}

//--------------------------------------------------------------------

void main(void)
{
//--------------------------------------------------------------------
// Объявление и инициализация переменных.

HMODULE hModule;                        // Дескриптор модуля DLL
CPAcquireContext_t lpProcAcquire;       // Адрес функции "CPAcquireContext"
CPReleaseContext_t lpProcRelease;       // Адрес функции "CPGetUserKey"
VTABLEPROVSTRUC VTable;                 // Передается провайдеру для
                                        // корректной работы
HKEY hkResult;                          // Реестровый ключ
char sDefaultProviderName[MAX_PATH];    // Массив, содержаший имя провайдера
                                        // по умолчанию
char sDefaultProviderNamePath[MAX_PATH];// Массив, содержаший путь провайдера
                                        // по умолчанию
DWORD cbDefaultProviderName = (DWORD)sizeof( sDefaultProviderName );
char sDefaultFileName[80];              // Массив, содержаший имя загружаемого
                                        // DLL
DWORD cbDefaultFileName = (DWORD)sizeof( sDefaultFileName );
HCRYPTPROV hProv;                       // Дескриптор CSP

//--------------------------------------------------------------------
// Открытие реестрового ключа.

if(!RegOpenKeyEx(
   HKEY_LOCAL_MACHINE,
   "SOFTWARE\\Microsoft\\Cryptography\\Defaults\\Provider Types\\Type 075",
   0,
   KEY_QUERY_VALUE,
   &hkResult))
{
    printf("RegOpenKeyEx succeeded.\n");
}
else
{
    HandleError("A error runing RegOpenKeyEx.");
}

//--------------------------------------------------------------------
// Получение имени провайдера по умолчанию.

{
    DWORD type;
if(!RegQueryValueEx(
   hkResult,
   "Name",
   0,
   &type,
   (BYTE*)sDefaultProviderName,
   &cbDefaultProviderName ))
{
    printf("RegQueryValueEx succeeded.\nDefault provider name: '%s.'\n", sDefaultProviderName );
}
else
{
    HandleError("A error runing RegQueryValueEx.");
}
}

//--------------------------------------------------------------------
// Закрытие реестрового ключа.

RegCloseKey( hkResult );

//--------------------------------------------------------------------
// Определение пути для получения имени загружаемого DLL.

strcpy( sDefaultProviderNamePath,
       "SOFTWARE\\Microsoft\\Cryptography\\Defaults\\Provider\\" );

strcat( sDefaultProviderNamePath, sDefaultProviderName );

//--------------------------------------------------------------------
// Открытие реестрового ключа.

if(!RegOpenKeyEx(
   HKEY_LOCAL_MACHINE,
   sDefaultProviderNamePath,
   0,
   KEY_QUERY_VALUE,
   &hkResult))
{
    printf("RegOpenKeyEx succeeded.\n");
}
else
{
    HandleError("A error runing RegOpenKeyEx.");
}

//--------------------------------------------------------------------
// Получение имени загружаемого DLL.

if(!RegQueryValueEx(
   hkResult,
   "Image Path",
   0,
   NULL,
   (BYTE*)sDefaultFileName,
   &cbDefaultFileName ))
{
    printf("RegQueryValueEx succeeded.\nProvider dll:'%s'\n", sDefaultFileName);
}
else
{
    HandleError("A error runing RegQueryValueEx.");
}

//--------------------------------------------------------------------
// Закрытие реестрового ключа.

RegCloseKey( hkResult );

//--------------------------------------------------------------------
// Заполнение таблицы.

VTable.Version = 3;
VTable.dwProvType = 75;
VTable.pszProvName = sDefaultProviderName;
VTable.cbContextInfo = 0;
VTable.pbContextInfo = NULL;
VTable.FuncReturnhWnd = &FunReturnHWnd;
VTable.FuncVerifyImage = &FunVerifyImage;

//--------------------------------------------------------------------
// Загрузка DLL.

hModule =  LoadLibrary(sDefaultFileName);

if(hModule)
{
    printf("LoadLibrary succeeded.\n");
}
else
{
    HandleError("A error runing LoadLibrary.");
}

//--------------------------------------------------------------------
// Получение адреса функции "CPAcquireContext".

lpProcAcquire = (CPAcquireContext_t)GetProcAddress(hModule, "CPAcquireContext");

if(lpProcAcquire)
{
    printf("GetProcAddress for CPAcquireContext succeeded.\n");
}
else
{
    HandleError("A error runing GetProcAddress.");
}

//--------------------------------------------------------------------
// Получение адреса функции "CPReleaseContext".

lpProcRelease = (CPReleaseContext_t)GetProcAddress(hModule, "CPReleaseContext");

if(lpProcRelease)
{
    printf("GetProcAddress for CPReleaseContext succeeded.\n");
}
else
{
    HandleError("A error runing GetProcAddress.");
}

//--------------------------------------------------------------------
// Вызов функции "CPAcquireContext".

if(lpProcAcquire)
{
    printf("CPAcquireContext succeeded.\n");
}
else
{
    HandleError("A error runing CPAcquireContext.");
}

//--------------------------------------------------------------------
// Выполнение криптографических операций.
// ...

//--------------------------------------------------------------------
// Вызов функции "CPReleaseContext".

if(lpProcRelease)
{
    printf("CPReleaseContext succeeded.\n");
}
else
{
    HandleError("A error runing CPReleaseContext.");
}

//--------------------------------------------------------------------
// Получение дескриптора провайдера.

if(lpProcAcquire(
   &hProv,
   "Source",
   0,
   &VTable ))
{
    printf("A context has been acquired.\n");
}
else
{
    HandleError("A error runing CPAcquireContext.");
}

//--------------------------------------------------------------------
// Освобождение дескриптора провайдера.

if(lpProcRelease(
   hProv,
   0))
{
    printf("A context has been released.\n");
}
else
{
    HandleError("A error runing CPReleaseContext.");
}

printf("The program ran to completion without error. \n");

} // Конец main

    Требования:

    Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
    Solaris: 9 Update 4 или выше.
    FreeBSD: FreeBSD 5.2 или выше
    Linux: RedHat 7.3, RedHad 9.0.
    Ядро Windows NT: не поддерживает.


Примеры использования функций хеширования

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

  • Пример на создание хеша
  • Пример на подпись объекта функции хеширования и проверку подписи
  • Пример на дублирование хеша


Крипто-Про CSP

Этот пример демонстрирует использование следующих функций
  • CryptAcquireContext в MS CryptoAPI 2.0 World Wide Web link
  • CryptCreateHash в MS CryptoAPI 2.0 World Wide Web link
  • CryptHashData в MS CryptoAPI 2.0 World Wide Web link
  • CryptGetHashParam в MS CryptoAPI 2.0 World Wide Web link
  • CryptDestroyHash в MS CryptoAPI 2.0 World Wide Web link
  • CryptReleaseContext в MS CryptoAPI 2.0 World Wide Web link

//--------------------------------------------------------------------
// Пример создания хеша из содержимого файла. Имя файла задается в
// командной строке и является обязательным параметром.
//--------------------------------------------------------------------

#define BUFSIZE 1024
#define GR3411LEN  64

int main(int argc, char *argv[])
{
//-------------------------------------------------------------
// Объявление и инициализация переменных.
    DWORD dwStatus = 0;
    BOOL bResult = FALSE;
    HCRYPTPROV hProv = 0;
    HCRYPTHASH hHash = 0;
    FILE* hFile;
    BYTE rgbFile[BUFSIZE];
    DWORD cbRead = 0;
    BYTE rgbHash[GR3411LEN];
    DWORD cbHash = 0;
    CHAR rgbDigits[] = "0123456789abcdef";

//--------------------------------------------------------------------
// Проверка того, передано ли имя файла.
    if (argv[1] == NULL)
    {
        printf("The file name is absent.\n");
        return 1;
    }

//--------------------------------------------------------------------
// Открытие файла.

    hFile = fopen( argv[1], "r+b" );

if(hFile)
{
        printf( "The file %s was opened\n", argv[1]);
}
else
{
        dwStatus = GetLastError();
        printf("Error opening file %s\nError: %d\n", argv[1], dwStatus);
        return dwStatus;
}

//--------------------------------------------------------------------
// Получение дескриптора криптопровайдера.

    if (!CryptAcquireContext(
        &hProv,
        NULL,
        NULL,
        75,
        CRYPT_VERIFYCONTEXT))
    {
        dwStatus = GetLastError();
        printf("CryptAcquireContext failed: %d\n", dwStatus);
        fclose(hFile);
        return dwStatus;
    }

//--------------------------------------------------------------------
// Создание пустого объекта функции хеширования.

    if (!CryptCreateHash(hProv, CALG_GR3411, 0, 0, &hHash))
    {
        dwStatus = GetLastError();
        printf("CryptAcquireContext failed: %d\n", dwStatus);
        fclose(hFile);
        CryptReleaseContext(hProv, 0);
        return dwStatus;
    }

        if (!CryptSetHashParam(hHash,HP_OID,(BYTE*)OID_HashTest, 0))
                {
        dwStatus = GetLastError();
        printf("CryptAcquireContext failed: %d\n", dwStatus);
        CryptReleaseContext(hProv, 0);
        return dwStatus;
    }

//--------------------------------------------------------------------
// Чтение данных из файла и хеширование этих данных.

    do
    {
        cbRead = (DWORD)fread(rgbFile, 1, BUFSIZE, hFile);

        if (!cbRead)
        {
            bResult = TRUE;
            break;
        }

        if (!CryptHashData(hHash, rgbFile, cbRead, 0))
        {
            dwStatus = GetLastError();
            printf("CryptHashData failed: %d\n", dwStatus);
            CryptReleaseContext(hProv, 0);
            CryptDestroyHash(hHash);
            fclose(hFile);
            return dwStatus;
        }
    }
    while (!feof(hFile));

    if (bResult)
    {
        dwStatus = GetLastError();
        printf("ReadFile failed: %d\n", dwStatus);
        CryptReleaseContext(hProv, 0);
        CryptDestroyHash(hHash);
        fclose(hFile);
        return dwStatus;
    }

    cbHash = GR3411LEN;

//--------------------------------------------------------------------
// Получение параметра объекта функции хеширования.

    if (CryptGetHashParam(hHash, HP_HASHVAL, rgbHash, &cbHash, 0))
    {
        printf("GR3411 hash of file %s is: ", argv[1]);
        for (DWORD i = 0; i < cbHash; i++)
        {
            printf("%c%c", rgbDigits[rgbHash[i] >> 4],
                rgbDigits[rgbHash[i] & 0xf]);
        }
        printf("\n");
    }
    else
    {
        dwStatus = GetLastError();
        printf("CryptGetHashParam failed: %d\n", dwStatus);
    }

//--------------------------------------------------------------------
// Освобождение.

    CryptDestroyHash(hHash);
    CryptReleaseContext(hProv, 0);
    fclose(hFile);

    return dwStatus;
} //  Конец main

    Требования:

    Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
    Solaris: 9 Update 4 или выше.
    FreeBSD: FreeBSD 5.2 или выше
    Linux: RedHat 7.3, RedHad 9.0.
    Ядро Windows NT: не поддерживает.


Крипто-Про CSP

Этот пример демонстрирует использование следующих функций
  • CryptAcquireContext в MS CryptoAPI 2.0 World Wide Web link
  • CryptGetUserKey в MS CryptoAPI 2.0 World Wide Web link
  • CryptExportKey в MS CryptoAPI 2.0 World Wide Web link
  • CryptCreateHash в MS CryptoAPI 2.0 World Wide Web link
  • CryptHashData в MS CryptoAPI 2.0 World Wide Web link
  • CryptSignHash в MS CryptoAPI 2.0 World Wide Web link
  • CryptDestroyHash в MS CryptoAPI 2.0 World Wide Web link
  • CryptImportKey в MS CryptoAPI 2.0 World Wide Web link
  • CryptVerifySignature в MS CryptoAPI 2.0 World Wide Web link

//--------------------------------------------------------------------
// В этом примере реализованы создание подписи объекта функции хеширования
// и проверка этой электронно-цифровой подписи.
//--------------------------------------------------------------------

#define MY_ENCODING_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
void HandleError(char *s);

void main(void)
{
//-------------------------------------------------------------
// Объявление и инициализация переменных.

HCRYPTPROV hProv;
BYTE *pbBuffer= (BYTE *)"The data that is to be hashed and signed.";
DWORD dwBufferLen = (DWORD)(strlen((char *)pbBuffer)+1);
HCRYPTHASH hHash;
HCRYPTKEY hKey;
HCRYPTKEY hPubKey;
BYTE *pbKeyBlob;
BYTE *pbSignature;
DWORD dwSigLen;
DWORD dwBlobLen;
BYTE *pbHash;
DWORD cbHash;
FILE *signature;
LPTSTR szDescription = "Test Data Description";

//--------------------------------------------------------------------
// Получение дескриптора контекста криптографического провайдера.

if(CryptAcquireContext(
   &hProv,
   NULL,
   NULL,
   75,
   0))
{
     printf("CSP context acquired.\n");
}
else
{
     HandleError("Error during CryptAcquireContext.");
}
//--------------------------------------------------------------------
// Получение открытого ключа подписи. Этот открытый ключ будет
// использоваться получателем хеша для проверки подписи.
// В случае, когда получатель имеет доступ к открытому ключю
// отправителя с помощью сертификата, этот шаг не нужен.

if(CryptGetUserKey(
   hProv,
   AT_SIGNATURE,
   &hKey))
{
    printf("The signature key has been acquired. \n");
}
else
{
    HandleError("Error during CryptGetUserKey for signkey.");
}
//--------------------------------------------------------------------
// Экпорт открытого ключа. Здесь открытый ключ экспортируется в
// PUBLICKEYBOLB для того, чтобы получатель подписанного хеша мог
// проверить подпись. Этот BLOB может быть записан в файл и передан
// другому пользователю.

if(CryptExportKey(
   hKey,
   0,
   PUBLICKEYBLOB,
   0,
   NULL,
   &dwBlobLen))
{
     printf("Size of the BLOB for the public key determined. \n");
}
else
{
     HandleError("Error computing BLOB length.");
}
//--------------------------------------------------------------------
// Распределение памяти под pbKeyBlob.

pbKeyBlob = (BYTE*)malloc(dwBlobLen);

if(pbKeyBlob)
{
    printf("Memory has been allocated for the BLOB. \n");
}
else
{
    HandleError("Out of memory. \n");
}
//--------------------------------------------------------------------
// Сам экспорт в ключевой BLOB.

if(CryptExportKey(
   hKey,
   0,
   PUBLICKEYBLOB,
   0,
   pbKeyBlob,
   &dwBlobLen))
{
     printf("Contents have been written to the BLOB. \n");
}
else
{
    HandleError("Error during CryptExportKey.");
}
//--------------------------------------------------------------------
// Создание объекта функции хеширования.

if(CryptCreateHash(
   hProv,
   CALG_GR3411,
   0,
   0,
   &hHash))
{
     printf("Hash object created. \n");
}
else
{
    HandleError("Error during CryptCreateHash.");
}

//--------------------------------------------------------------------
// Передача параметра HP_OID объекта функции хеширования.
//--------------------------------------------------------------------

//--------------------------------------------------------------------
// Определение размера BLOBа и распределение памяти.

if(CryptGetHashParam(hHash,
   HP_OID,
   NULL,
   &cbHash,
   0))
{
     printf("Size of the BLOB determined. \n");
}
else
{
     HandleError("Error computing BLOB length.");
}

pbHash = (BYTE*)malloc(cbHash);

if(pbHash)
{
    printf("Memory has been allocated for the pbHash. \n");
}
else
{
    HandleError("Out of memory. \n");
}

//--------------------------------------------------------------------
// Копирование параметра HP_OID в pbHash.

if(CryptGetHashParam(hHash,
   HP_OID,
   pbHash,
   &cbHash,
   0))
{
     printf("Parameters have been written to the pbHash. \n");
}
else
{
    HandleError("Error during CryptGetHashParam.");
}

//--------------------------------------------------------------------
// Вычисление криптографического хеша буфера.

if(CryptHashData(
   hHash,
   pbBuffer,
   dwBufferLen,
   0))
{
     printf("The data buffer has been hashed.\n");
}
else
{
     HandleError("Error during CryptHashData.");
}
//--------------------------------------------------------------------
// Определение размера подписи и распределение памяти.

dwSigLen= 0;
if(CryptSignHash(
   hHash,
   AT_SIGNATURE,
   szDescription,
   0,
   NULL,
   &dwSigLen))
{
     printf("Signature length %d found.\n",dwSigLen);
}
else
{
     HandleError("Error during CryptSignHash.");
}
//--------------------------------------------------------------------
// Распределение памяти под буфер подписи.

pbSignature = (BYTE *)malloc(dwSigLen);

if(pbSignature)
{
     printf("Memory allocated for the signature.\n");
}
else
{
     HandleError("Out of memory.");
}
//--------------------------------------------------------------------
// Подпись объекта функции хеширования.

if(CryptSignHash(
   hHash,
   AT_SIGNATURE,
   szDescription,
   0,
   pbSignature,
   &dwSigLen))
{
     printf("pbSignature is the hash signature.\n");
}
else
{
     HandleError("Error during CryptSignHash.");
}

signature = fopen( "signature.txt", "w+b" );

if(!signature)
    HandleError( "Problem opening the file\n" );

fwrite (pbSignature, 1, dwSigLen, signature);

//--------------------------------------------------------------------
// Уничтожение объекта функции хеширования.

if(hHash)
  CryptDestroyHash(hHash);

printf("The hash object has been destroyed.\n");
printf("The signing phase of this program is completed.\n\n");

//--------------------------------------------------------------------
// Во второй части программы проверяется подпись.
// Чаще всего проверка осуществляется в случае, когда различные
// пользователи используют одну и ту же программу. Хеш, подпись,
// а также PUBLICKEYBLOB могут быть прочитаны из файла, e-mail сообщения
// или из другого источника.

// Здесь используюся определенные ранее pbBuffer, pbSignature,
// szDescription, pbKeyBlob и их длины.

// Содержимое буфера pbBuffer представляет из себя некоторые
// подписанные ранее данные.

// Указатель szDescription на текст, описывающий данные, подписывается.
// Это тот же самый текст описания, который был ранее передан
// функции CryptSignHash.

//--------------------------------------------------------------------
// Получение откытого ключа пользователя, который создал цифровую подпись,
// и импортирование его в CSP с помощью функции CryptImportKey. Она
// возвращает дескриптор открытого ключа в hPubKey.

if(CryptImportKey(
   hProv,
   pbKeyBlob,
   dwBlobLen,
   0,
   0,
   &hPubKey))
{
     printf("The key has been imported.\n");
}
else
{
     HandleError("Public key import failed.");
}
//--------------------------------------------------------------------
// Создание нового объекта функции хеширования.

if(CryptCreateHash(
   hProv,
   CALG_GR3411,
   0,
   0,
   &hHash))
{
     printf("The hash object has been recreated. \n");
}
else
{
     HandleError("Error during CryptCreateHash.");
}

//--------------------------------------------------------------------
// Установка параметра HP_OID.

// По умолчанию провайдер работает на наборе параметров 1.2.643.2.2.30.1.
// Без установки параметра HP_OID программа будет неверно работать,
// если параметры хеширования не будут являться параметрами
// по умолчанию.

   if(CryptSetHashParam(
        hHash,
        HP_OID,
        pbHash,
        0))
{
    printf("The parameters have been set. \n");
}
else
{
    HandleError("Error during SetHashParam.");
 }

//--------------------------------------------------------------------
// Вычисление криптографического хеша буфера.

if(CryptHashData(
   hHash,
   pbBuffer,
   dwBufferLen,
   0))
{
     printf("The new has been created.\n");
}
else
{
     HandleError("Error during CryptHashData.");
}
//--------------------------------------------------------------------
// Проверка цифровой подписи.

if(CryptVerifySignature(
   hHash,
   pbSignature,
   dwSigLen,
   hPubKey,
   szDescription,
   0))
{
     printf("The signature has been verified.\n");
}
else
{
     printf("Signature not validated!\n");
}
//--------------------------------------------------------------------
// Освобождение памяти, необходимой для хранения подписи и для хранения
// параметров объекта функции хеширования.

if(pbSignature)
  free(pbSignature);
if(pbHash)
  free(pbHash);

//--------------------------------------------------------------------
// Уничтожение объекта функции хеширования.

if(hHash)
  CryptDestroyHash(hHash);

//--------------------------------------------------------------------
// Освобождение дескриптора провайдера.

if(hProv)
   CryptReleaseContext(hProv, 0);
} //  Конец main

    Требования:

    Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
    Solaris: 9 Update 4 или выше.
    FreeBSD: FreeBSD 5.2 или выше
    Linux: RedHat 7.3, RedHad 9.0.
    Ядро Windows NT: не поддерживает.


Крипто-Про CSP

Этот пример демонстрирует использование следующих функций
  • CryptAcquireContext в MS CryptoAPI 2.0 World Wide Web link
  • CryptCreateHash в MS CryptoAPI 2.0 World Wide Web link
  • CryptHashData в MS CryptoAPI 2.0 World Wide Web link
  • CryptDuplicateHash в MS CryptoAPI 2.0 World Wide Web link
  • CryptSetHashParam в MS CryptoAPI 2.0 World Wide Web link
  • CryptGetHashParam в MS CryptoAPI 2.0 World Wide Web link
  • CryptDestroyHash в MS CryptoAPI 2.0 World Wide Web link
  • CryptReleaseContext в MS CryptoAPI 2.0 World Wide Web link

//--------------------------------------------------------------------
// В данном примере осуществляется хеширование строки, дублирование
// полученного хеша. Затем осуществляется хеширование дополнительных
// данных при помощи оригинального и дублированного хеша.
//--------------------------------------------------------------------

#define MY_ENCODING_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
void HandleError(char *s);
void Get_And_Print_Hash(HCRYPTHASH hHash);

int main(void)
{
//--------------------------------------------------------------------
// Объявление и инициализация переменных.

HCRYPTPROV   hCryptProv = 0;
HCRYPTHASH   hOriginalHash;
HCRYPTHASH   hDuplicateHash;
BYTE         pbData[20];
DWORD        i;

//-------------------------------------------------------------------
// Инициализация буфера pbData.

for(i=0;i<20;i++)
   pbData[i]=(unsigned char)i*7;
//--------------------------------------------------------------------
// Получение дескриптора контекста криптографического провайдера.

if(CryptAcquireContext(
   &hCryptProv,
   NULL,
   NULL,
   75,
   0))
{
    printf("CryptAcquireContext succeeded. \n");
}
else
{
    HandleError("Error during CryptAcquireContext!");
}
//--------------------------------------------------------------------
// Создание объекта функции хеширования.

if (CryptCreateHash(
    hCryptProv,
    CALG_GR3411,
    0,
    0,
    &hOriginalHash))
{
   printf("An empty hash object has been created. \n");
}
else
{
   HandleError("Error during CryptCreateHash.");
}
//--------------------------------------------------------------------
// Хеширование байтовой строки.

if (CryptHashData(
    hOriginalHash,
    (BYTE*)"Some Common Data",
    sizeof("Some Common Data"), 0))
{
   printf("An original hash has been created. \n");
}
else
{
   HandleError("Error during CryptHashData.");
}
//--------------------------------------------------------------------
// Дублирование хеша.
// Эта функция работает только в Windows 2000 и старше.

if (CryptDuplicateHash(
   hOriginalHash,
   NULL,
   0,
   &hDuplicateHash))
{
   printf("The hash has been duplicated. \n");
}
else
{
   HandleError("Error during CryptDuplicateHash.");
}

printf("The original hash -- phase 1.\n");
Get_And_Print_Hash(hOriginalHash);

printf("The duplicate hash -- phase 1.\n");
Get_And_Print_Hash(hDuplicateHash);

//--------------------------------------------------------------------
// Хеширование "Some Data" с оригинальным хешем.

if (CryptHashData(
     hOriginalHash,
     (BYTE*)"Some Data",
     sizeof("Some Data"),
     0))
{
    printf("Additional data has been hashed with the original. \n");
}
else
{
    HandleError("Error during CryptHashData.");
}
//--------------------------------------------------------------------
// Хеширование "Other Data" с дублированным хешем.

if (CryptHashData(
     hDuplicateHash,
     (BYTE*)"Other Data",
     sizeof("Other Data"),
     0))
{
   printf("More data has been hashed with the duplicate. \n");
}
else
{
   HandleError("Error during CryptHashData.");
}

printf("The original hash -- phase 2.\n");
Get_And_Print_Hash(hOriginalHash);

printf("The duplicate hash -- phase 2.\n");
Get_And_Print_Hash(hDuplicateHash);

// Уничтожение оригинального хеша.

if(CryptDestroyHash(hOriginalHash))
{
   printf("The original hash has been destroyed. \n");
}
else
{
   HandleError("ERROR during CryptDestroyHash");
}
//--------------------------------------------------------------------
// Уничтожение дублированного хеша.

if (CryptDestroyHash(hDuplicateHash))
{
   printf("The duplicate hash has been destroyed. \n");
}
else
{
   HandleError("Error -- CryptDestroyHash");
}

//--------------------------------------------------------------------
// Освобождение CSP.

if(hCryptProv)
   CryptReleaseContext(hCryptProv,0);

printf("The program ran to completion without error. \n");
return 0;
} // Конец main

//--------------------------------------------------------------------
// Определение функции Get_And_Print_Hash.

void Get_And_Print_Hash(HCRYPTHASH hOHash)
{
//--------------------------------------------------------------------
// Объявление и инициализация локальных переменных.

BYTE         *pbHash;
BYTE         *pbHashSize;
DWORD        dwHashLen = sizeof(DWORD);
DWORD        i;
HCRYPTHASH   hHash=0;

//--------------------------------------------------------------------
// Дублирование установленного хеша.
// Эта функция работает только в Windows 2000 и старше.
// Хеш продублирован для того, чтобы не изменять исходный хеш.

if (CryptDuplicateHash(
   hOHash,
   NULL,
   0,
   &hHash))
{
// Работает. Ничего не надо делать.
}
else
{
   HandleError("Error during CryptDuplicateHash.");
}

pbHashSize =(BYTE *) malloc(dwHashLen);

if(!pbHashSize)
HandleError("Memory allocation failed.");
if(CryptGetHashParam(
   hHash,
   HP_HASHSIZE,
   pbHashSize,
   &dwHashLen,
   0))
{
// Работает. Освобождение pbHashSize.
   free(pbHashSize);
}
else
{
    HandleError("CryptGetHashParam failed to get size.");
}

if(CryptGetHashParam(
   hHash,
   HP_HASHVAL,
   NULL,
   &dwHashLen,
   0))
{
// Работает. Ничего не надо делать.
}
else
{
    HandleError("CryptGetHashParam failed to get length.");
}

pbHash = (BYTE*)malloc(dwHashLen);

if(pbHash)
{
// Работает. Ничего не надо делать.
}
else
{
     HandleError("Allocation failed.");
}
if(CryptGetHashParam(
   hHash,
   HP_HASHVAL,
   pbHash,
   &dwHashLen,
   0))
{
// Печать значения хеша.
printf("The hash is:  ");
   for(i = 0 ; i < dwHashLen ; i++)
   {
       printf("%2.2x ",pbHash[i]);
   }
printf("\n");
}
else
{
    HandleError("Error during reading hash value.");
}
free(pbHash);
if (CryptDestroyHash(hHash))
{
// Работает. Ничего не надо делать.
}
else
{
   HandleError("ERROR - CryptDestroyHash");
}
} // Конец Get_And_Print_Hash

    Требования:

    Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
    Solaris: 9 Update 4 или выше.
    FreeBSD: FreeBSD 5.2 или выше
    Linux: RedHat 7.3, RedHad 9.0.
    Ядро Windows NT: не поддерживает.


Примеры использования функций шифрования

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

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

1) Запись открытого ключа в файл.

2) Зашифрование файла.

3) Расшифрование файла.

  • Пример на CryptEncryptMessage и CryptDecryptMessage
  • Пример на запись открытого ключа в файл
  • Пример на зашифрование файла
  • Пример на расшифрование файла


Крипто-Про CSP

Этот пример демонстрирует использование следующих функций
  • CryptEncryptMessage в MS CryptoAPI 2.0 World Wide Web link
  • CryptDecryptMessage в MS CryptoAPI 2.0 World Wide Web link

//--------------------------------------------------------------------
// Пример кода для зашифрования данных и создания зашифрованного
// сообщения при помощи функции CryptEncryptMessage.

// Для функционирования данного кода необходим контейнер с ключом
// AT_KEYEXCHANGE с именем, совпадающим с именем текущего пользователя.
// Ключ можно создать используя пример CryptAcquireContext.
//--------------------------------------------------------------------

#define MY_ENCODING_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
void HandleError(char *s);
//--------------------------------------------------------------------
// В этой программе используется функция GetRecipientCert, объявленная
// здесь и описанная после main.

PCCERT_CONTEXT GetRecipientCert(
     HCERTSTORE hCertStore);

//--------------------------------------------------------------------
// В этой программе используется функция ByteToStr, объявленная здесь
// и описанная после main. Код функции ByteToStr также можно найти среди
// универсальных функций.

void ByteToStr(
     DWORD cb,
     void* pv,
     LPSTR sz);

//--------------------------------------------------------------------
// В этой программе используется функция DecryptMessage, объявленная
// здесь и описанная после main.

BOOL DecryptMessage(
       BYTE *pbEncryptedBlob,
       DWORD cbEncryptedBlob,
       HCERTSTORE hStoreHandle);

int main()
{
//--------------------------------------------------------------------
// Объявление и инициализация переменных. Они получают указатель на
// сообщение, которое будет зашифровано. В данном коде создается сообщение,
// получается указатель на него. В действительности, обычно содержимое
// сообщения уже где-то существует и указатель на сообщение устанавливается
// приложением.

BYTE* pbContent = (BYTE*) "Security is our business.";
                                            // Сообщение
DWORD cbContent = (DWORD)(strlen((char *)pbContent)+1);
                                            // Длина сообщения
HCRYPTPROV hCryptProv;                      // дескриптор CSP
HCERTSTORE hStoreHandle;
PCCERT_CONTEXT pRecipientCert;
PCCERT_CONTEXT RecipientCertArray[1];
DWORD EncryptAlgSize;
CRYPT_ALGORITHM_IDENTIFIER EncryptAlgorithm;
CRYPT_ENCRYPT_MESSAGE_PARA EncryptParams;
DWORD EncryptParamsSize;
BYTE*    pbEncryptedBlob;
DWORD    cbEncryptedBlob;

//--------------------------------------------------------------------
//  Начало обработки данных.

printf("About to begin with the message %s.\n",pbContent);
printf("The message length is %d bytes. \n", cbContent);

//--------------------------------------------------------------------
// Получение дескриптора криптографического провайдера.

if(CryptAcquireContext(
            &hCryptProv,         // Адрес возврашаемого дескриптора.
            NULL,                // Используется имя текущего
                                 // зарегестрированного пользователя.
            NULL,                // Используется провайдер по умолчанию.
            75,   // Необходимо для зашифрования и подписи.
            0))               // Никакие флаги не нужны.
{
    printf("A CSP has been acquired. \n");
}
else
{
    HandleError("Cryptographic context could not be acquired.");
}
//--------------------------------------------------------------------
// Открытие системного хранилища сертификатов.

hStoreHandle = CertOpenSystemStore(
     hCryptProv,
     "MY");

if(hStoreHandle)
{
    printf("The MY store is open. \n");
}
else
{
    HandleError( "Error getting store handle.");
}
//--------------------------------------------------------------------
// Получение указателя на сертификат издателя с помощью
// функции GetRecipientCert.

pRecipientCert = GetRecipientCert(
     hStoreHandle);

if(pRecipientCert)
{
    printf("A recipient's certificate has been acquired. \n");
}
else
{
    printf("No certificate with a CERT_KEY_CONTEXT_PROP_ID \n");
    printf("property and an AT_KEYEXCHANGE private key available. \n");
    printf("While the message could be encrypted, in this case, \n");
    printf("it could not be decrypted in this program. \n");
    printf("For more information, see the documentation for \n");
    printf("CrypteEncryptMessage and CryptDecryptMessage.\n\n");
    HandleError( "No Certificate with AT_KEYEXCHANGE key in store.");
}
//--------------------------------------------------------------------
// Создание RecipientCertArray.

RecipientCertArray[0] = pRecipientCert;

//--------------------------------------------------------------------
// Инициализация структуры идентификатора алгоритма.

EncryptAlgSize = sizeof(EncryptAlgorithm);

//--------------------------------------------------------------------
// Инициализация структуры с нулем.

memset(&EncryptAlgorithm, 0, EncryptAlgSize);

//--------------------------------------------------------------------
// Установка необходимого элемента.

EncryptAlgorithm.pszObjId = OID_CipherVar_Default;

//--------------------------------------------------------------------
// Инициализация структуры CRYPT_ENCRYPT_MESSAGE_PARA.

EncryptParamsSize = sizeof(EncryptParams);
memset(&EncryptParams, 0, EncryptParamsSize);
EncryptParams.cbSize =  EncryptParamsSize;
EncryptParams.dwMsgEncodingType = MY_ENCODING_TYPE;
EncryptParams.hCryptProv = hCryptProv;
EncryptParams.ContentEncryptionAlgorithm = EncryptAlgorithm;

//--------------------------------------------------------------------
// Вызов функции CryptEncryptMessage.

if(CryptEncryptMessage(
          &EncryptParams,
          1,
          RecipientCertArray,
          pbContent,
          cbContent,
          NULL,
          &cbEncryptedBlob))
{
    printf("The encrypted message is %d bytes. \n",cbEncryptedBlob);
}
else
{
    HandleError( "Getting EncrypBlob size failed.");
}
//--------------------------------------------------------------------
// Распределение памяти под возвращаемый BLOB.

pbEncryptedBlob = (BYTE*)malloc(cbEncryptedBlob);

if(pbEncryptedBlob)
{
    printf("Memory has been allocated for the encrypted BLOB. \n");
}
else
{
    HandleError("Memory allocation error while encrypting.");
}
//--------------------------------------------------------------------
// Повторный вызов функции CryptEncryptMessage для зашифрования содержимого.

if(CryptEncryptMessage(
          &EncryptParams,
          1,
          RecipientCertArray,
          pbContent,
          cbContent,
          pbEncryptedBlob,
          &cbEncryptedBlob))
{
    printf( "Encryption succeeded. \n");
}
else
{
    HandleError("Encryption failed.");
}

//--------------------------------------------------------------------
// Вызов функции DecryptMessage, код которой описан после main,
// для расшифрования сообщения.

if(DecryptMessage(
     pbEncryptedBlob,
     cbEncryptedBlob,
     hStoreHandle))
{
   printf("Decryption succeeded. \n");
}
else
{
   printf("Decryption failed. \n");
}
//--------------------------------------------------------------------
// Освобождение памяти.

CertFreeCertificateContext(pRecipientCert);
if(CertCloseStore(
          hStoreHandle,
          CERT_CLOSE_STORE_CHECK_FLAG))
{
    printf("The MY store was closed without incident. \n");
}
else
{
   printf("Store closed after encryption -- \n"
        "but not all certificates or CRLs were freed. \n");
}
if(hCryptProv)
{
    CryptReleaseContext(hCryptProv,0);
    printf("The CSP has been released. \n");
}
else
{
    printf("CSP was NULL. \n");
}
} // Конец main

//--------------------------------------------------------------------
//  Определение функции DecryptMessage.

BOOL DecryptMessage(
     BYTE *pbEncryptedBlob,
     DWORD cbEncryptedBlob,
     HCERTSTORE hStoreHandle)

//--------------------------------------------------------------------
// Пример функции для расшифрования зашифрованного сообщения с
// использованием функции CryptDecryptMessage. ЕЕ параметрами являются
// pbEncryptedBlob, зашифрованное сообщение; cbEncryptedBlob, длина
// этого сообщения; и hStoreHandle, дескриптор
// открытого хранилища сертификатов.

{
//--------------------------------------------------------------------
// Объявление и инициализация локальных переменных.

DWORD cbDecryptedMessage;
char* EncryptedString = new char[(cbEncryptedBlob * 2) +1];
HCERTSTORE CertStoreArray[] = {hStoreHandle};
CRYPT_DECRYPT_MESSAGE_PARA  DecryptParams;
DWORD  DecryptParamsSize = sizeof(DecryptParams);
BYTE*  pbDecryptedMessage;
LPSTR  DecryptedString;
BOOL   fReturn = TRUE;

//--------------------------------------------------------------------
// Получение указателя на зашифрованное сообщение, pbEncryptedBlob,
// и его длину, cbEncryptedBlob. В этом примере они устанавливаются
// как параметры совместно с  CSP и дескриптором открытого хранилища.

//--------------------------------------------------------------------
// Просмотр зашифрованного BLOBа.
// Вызов функции ByteToStr для конвертирования байтового BLOBа
// шестнадцатиричный формат ASCII.

ByteToStr(
    cbEncryptedBlob,
    pbEncryptedBlob,
    EncryptedString);

//--------------------------------------------------------------------
// Печать конвертированной строки.

printf("The encrypted string is: \n%s\n",EncryptedString);

//--------------------------------------------------------------------
//   В этом примере дескриптор хранилище MY установлен как параметр.

//--------------------------------------------------------------------
//   Создание "CertStoreArray."
//   В этом примере был выполнен в процессе объявления и инициализации
//   локальных переменных, потому что дескриптор хранилища в функции
//   был установлен как параметр.

//--------------------------------------------------------------------
//   Инициализация структуры CRYPT_DECRYPT_MESSAGE_PARA.

memset(&DecryptParams, 0, DecryptParamsSize);
DecryptParams.cbSize = DecryptParamsSize;
DecryptParams.dwMsgAndCertEncodingType = MY_ENCODING_TYPE;
DecryptParams.cCertStore = 1;
DecryptParams.rghCertStore = CertStoreArray;

//--------------------------------------------------------------------
//  Расшифрование сообщения.
//  Вызов фнукции CryptDecryptMessage для получения возвращаемого размера
//  данных.

if(CryptDecryptMessage(
          &DecryptParams,
          pbEncryptedBlob,
          cbEncryptedBlob,
          NULL,
          &cbDecryptedMessage,
          NULL))
{
    printf("The size for the decrypted message is: %d.\n",cbDecryptedMessage);
}
else
{
    HandleError( "Error getting decrypted message size");
}
//--------------------------------------------------------------------
// Освобождение памяти под возвращаемые расшифрованные данные.

pbDecryptedMessage = (BYTE*)malloc(cbDecryptedMessage);

if(pbDecryptedMessage)
{
    printf("Memory has been allocated for the decrypted message. \n");
}
else
{
    HandleError("Memory allocation error while decrypting");
}
//--------------------------------------------------------------------
// Вызов функции CryptDecryptMessage для расшифрования данных.

if(CryptDecryptMessage(
          &DecryptParams,
          pbEncryptedBlob,
          cbEncryptedBlob,
          pbDecryptedMessage,
          &cbDecryptedMessage,
          NULL))
{
    DecryptedString = (LPSTR) pbDecryptedMessage;
    printf("Message Decrypted Successfully. \n");
    printf("The decrypted string is: %s\n",DecryptedString);
}
else
{
    printf("Error decrypting the message \n");
    printf("Error code %x \n",GetLastError());
    fReturn = FALSE;
}

//--------------------------------------------------------------------
// Освобождение памяти.

free(pbEncryptedBlob);
free(pbDecryptedMessage);
return fReturn;
}  // Конец определения DecryptMessage

//--------------------------------------------------------------------
// Определение функции ByteToStr.

void ByteToStr(
     DWORD cb,
     void* pv,
     LPSTR sz)
//--------------------------------------------------------------------
// Устанавливаемые параметры:
//    pv - байтовый массив для конвертирования.
//    cb - число байтов в массиве.
//    sz - указатель на возвращаемую строку.

{
//--------------------------------------------------------------------
//  Объявление и инициализация локальных переменных.

BYTE* pb = (BYTE*) pv; // Локальный указатель на байт в байтовом массиве
DWORD i;               // Локальный счетчик цикла
int b;                 // Локальная переменная

//--------------------------------------------------------------------
//  Начало выполнения цикла.

for (i = 0; i<cb; i++)
{
   b = (*pb & 0xF0) >> 4;
   *sz++ = (CHAR)((b <= 9) ? b + '0' : (b - 10) + 'A');
   b = *pb & 0x0F;
   *sz++ = (CHAR)((b <= 9) ? b + '0' : (b - 10) + 'A');
   pb++;
}
*sz++ = 0;
} // Конец определения ByteToStr

//--------------------------------------------------------------------
//  В этом примере используется функция HandleError, функция обработки
//  простых ошибок, для печати сообщения об ошибке в стандартный файл
//  ошибок (stderr) и выхода из программы.
//  В большинстве приложений эта функция заменяется другой функцией,
//  которая выводит более полное сообщение об ошибке.

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);
} // Конец опредления HandleError

//--------------------------------------------------------------------
// GetRecipientCert перечисляет сертификаты в хранилище и находит
// первый сертификат, обладающий ключем AT_EXCHANGE. Если сертификат
// сертификат найден, то возвращается указатель на него.

PCCERT_CONTEXT GetRecipientCert(
    HCERTSTORE hCertStore)
//--------------------------------------------------------------------
// Устанавлеваемый параметр:
// hCertStore, дескриптор хранилища, в котором будет осуществлен поиск.
{
//--------------------------------------------------------------------
// Объявление и инициализация локальных переменных.

PCCERT_CONTEXT pCertContext = NULL;
BOOL fMore = TRUE;
DWORD dwSize = 0;
CRYPT_KEY_PROV_INFO* pKeyInfo = NULL;
DWORD PropId = CERT_KEY_PROV_INFO_PROP_ID;

//--------------------------------------------------------------------
// Поиск сертификатов в хранилище до тех пор, пока не будет достигнут
// конец хранилища, или сертификат с ключем AT_KEYEXCHANGE не будет найден.

pCertContext= CertFindCertificateInStore(
   hCertStore, // Дескриптор хранилища, в котором будет осуществлен поиск.
   0,          // Тип зашифрования. В этом поиске не используется.
   0,          // dwFindFlags. Специальный критерий поиска.
               // в этом поиске не используется.
   CERT_FIND_PROPERTY,
               // Тип поиска. Задает вид поиска, который будет
               // осуществлен. В этом случае, поиск сертификатов,
               // имеющих определенные расширенные свойства.
   &PropId,    // pvFindPara. Выдает определенное значение
               // поиска, в данном случае идентификатор
               // расширенного свойства.
   pCertContext);
               // pCertContext равен NULL для первого вызова
               // функции. Если функция вызывается в цикле,
               // после первого ее вызова pCertContext становится
               // указателем, возвращенным предыдущим вызовом.

while(fMore && pCertContext)
{
//-------------------------------------------------------------
// Для простоты в этом коде реализован только поиск первого
// вхождения ключа AT_KEYEXCHANGE. Во многих случаях, помимо
// поиска типа ключа, осуществляется также поиск определенного
// имени субъекта.

//-------------------------------------------------------------
// Однократный вызов функции CertGetCertificateContextProperty
// для получения возврашенного размера структуры.

if(!(CertGetCertificateContextProperty(
     pCertContext,
     CERT_KEY_PROV_INFO_PROP_ID,
     NULL, &dwSize)))
{
     HandleError("Error getting key property.");
}

//--------------------------------------------------------------
// распределение памяти под возвращенную структуру.

if(pKeyInfo)
    free(pKeyInfo);

pKeyInfo = (CRYPT_KEY_PROV_INFO*)malloc(dwSize);

if(!pKeyInfo)
{
     HandleError("Error allocating memory for pKeyInfo.");
}

//--------------------------------------------------------------
// Получение структуры информации о ключе.

if(!(CertGetCertificateContextProperty(
   pCertContext,
   CERT_KEY_PROV_INFO_PROP_ID,
   pKeyInfo,
   &dwSize)))
{
    HandleError("The second call to the function failed.");
}

//-------------------------------------------
// Проверка члена dwKeySpec на расширенный ключ.

if(pKeyInfo->dwKeySpec == AT_KEYEXCHANGE)
{
    fMore = FALSE; }
}    // Конец цикла while

if(pKeyInfo)
      free(pKeyInfo);
return (pCertContext);
} // Конец определения GetRecipientCert

    Требования:

    Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
    Solaris: 9 Update 4 или выше.
    FreeBSD: FreeBSD 5.2 или выше
    Linux: RedHat 7.3, RedHad 9.0.
    Ядро Windows NT: не поддерживает.


Крипто-Про CSP

Этот пример демонстрирует использование следующих функций
  • CryptAcquireContext в MS CryptoAPI 2.0 World Wide Web link
  • CryptGetUserKey в MS CryptoAPI 2.0 World Wide Web link
  • CryptExportKey в MS CryptoAPI 2.0 World Wide Web link
  • CryptDestroyKey в MS CryptoAPI 2.0 World Wide Web link
  • CryptReleaseContext в MS CryptoAPI 2.0 World Wide Web link

//--------------------------------------------------------------------
// Данный пример демонстрирует экспортирование открытого ключа в
// в файл.
// Эта программа используется для экспортирования как открытого ключа
// отправителя, так и открытого ключа получателя.
// Она необходима для работы таких программ, как зашифрование и
// расшифрование содержимого файла.
// Для корректной работы этой программы необходимо создать контейнер
// с именем "Public".
// Контейнер может быть создан при помощи примера CreatingKeyContainer.
//--------------------------------------------------------------------

void HandleError(char *s);

int main(void)
{
//--------------------------------------------------------------------
//  Объявление и инициализация переменных.

HCRYPTPROV hProv;               // Дескриптор CSP
HCRYPTKEY hKey;                 // Дескриптор открытого ключа получателя
BYTE *pbKeyBlob;                // Указатель на ключевой BLOB
DWORD dwBlobLen;                // Длина ключевого BLOBа
FILE *Public;                   // Файл для хранения открытого ключа

//--------------------------------------------------------------------
// Получение дескриптора контейнера с именем "Public",
// находящегося в рамках провайдера.

if(CryptAcquireContext(
   &hProv,
   "Public",
   NULL,
   75,
   0))
{
    printf("The key container \"Public\" has been acquired. \n");
}
else
{
    HandleError("Error during CryptAcquireContext.");
}

//--------------------------------------------------------------------
// Получение дескриптора открытого ключа.

if(CryptGetUserKey(
   hProv,
   AT_KEYEXCHANGE,
   &hKey))
{
    printf("The public key has been acquired. \n");
}
else
{
    printf("Error during CryptGetUserKey public key.");
}

//--------------------------------------------------------------------
// Запись открытого ключа в ключевой BLOB.
//
//--------------------------------------------------------------------

//--------------------------------------------------------------------
// Определение размера BLOBа открытого ключа и распределение памяти.

if(CryptExportKey(
   hKey,
   0,
   PUBLICKEYBLOB,
   0,
   NULL,
   &dwBlobLen))
{
     printf("Size of the BLOB for the public key determined. \n");
}
else
{
     HandleError("Error computing BLOB length.");
}

pbKeyBlob = (BYTE*)malloc(dwBlobLen);

if(pbKeyBlob)
{
    printf("Memory has been allocated for the BLOB. \n");
}
else
{
    HandleError("Out of memory. \n");
}
//--------------------------------------------------------------------
// Экспортирование открытого ключа в BLOB открытого ключа.

if(CryptExportKey(
   hKey,
   0,
   PUBLICKEYBLOB,
   0,
   pbKeyBlob,
   &dwBlobLen))
{
     printf("Contents have been written to the BLOB. \n");
}
else
{
    HandleError("Error during CryptExportKey.");
}

//--------------------------------------------------------------------
// Открытие файла на запись в него BLOBа открытого ключа.

Public = fopen( "public.bin", "w+b" );

if(Public)
{
    printf( "The file 'public.bin' was opened\n" );
}
else
{
    HandleError( "Problem opening the file\n" );
}

//--------------------------------------------------------------------
// Запись открытого ключа в файл.

if(fwrite(pbKeyBlob,
       1,
       dwBlobLen,
       Public))
{
    printf( "The public key was written to the 'public.bin'\n" );
}
else
{
    HandleError( "The public key can not be written to the 'public.bin'\n" );
}

//--------------------------------------------------------------------
// Закрытие файла.

fclose (Public);

//--------------------------------------------------------------------
//  Освобождение памяти, используемой ключевым BLOBом.

free(pbKeyBlob);

// Уничтожение дескриптора открытого ключа.
if(hKey)
     CryptDestroyKey(hKey);

// Освобождение дескриптора провайдера.
if(hProv)
   CryptReleaseContext(hProv, 0);

printf("The program ran to completion without error. \n");

}// Конец main

    Требования:

    Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
    Solaris: 9 Update 4 или выше.
    FreeBSD: FreeBSD 5.2 или выше
    Linux: RedHat 7.3, RedHad 9.0.
    Ядро Windows NT: не поддерживает.


Крипто-Про CSP

Этот пример демонстрирует использование следующих функций
  • CryptAcquireContext в MS CryptoAPI 2.0 World Wide Web link
  • CryptGetUserKey в MS CryptoAPI 2.0 World Wide Web link
  • CryptExportKey в MS CryptoAPI 2.0 World Wide Web link
  • CryptImportKey в MS CryptoAPI 2.0 World Wide Web link
  • CryptGenKey в MS CryptoAPI 2.0 World Wide Web link
  • CryptGetKeyParam в MS CryptoAPI 2.0 World Wide Web link
  • CryptEncrypt в MS CryptoAPI 2.0 World Wide Web link
  • CryptDestroyKey в MS CryptoAPI 2.0 World Wide Web link
  • CryptReleaseContext в MS CryptoAPI 2.0 World Wide Web link

//--------------------------------------------------------------------
// В данном примере производится зашифрование файла на открытом ключе
// получателя.
// Для корректной работы данного примера предварительно необходимо
// записать открытый ключ в файл "public.bin" при помощи
// примера ExportInFile.
// Также предварительно необходимо создать файл, подлежаший зашифрованию,
// с именем "source.txt".
// Следует сделить за тем, чтобы контейнер с именем "Public", используемый
// в программе ExportInFile, на момент выполнения данной программы существовал.
//--------------------------------------------------------------------

#include <string.h>
void HandleError(char *s);

int main(void)
{
//--------------------------------------------------------------------
//  Объявление и инициализация переменных.

HCRYPTPROV hProv;               // Дескриптор CSP
HCRYPTKEY hKey;                 // Дескриптор закрытого ключа
HCRYPTKEY hSessionKey;          // Дескриптор сессионного ключа
HCRYPTKEY hAgreeKey;            // Дескриптор ключа согласования
BYTE  pbKeyBlob[100];           // Указатель на ключевой BLOB
DWORD dwBlobLen;                // Длина ключевого BLOBа
BYTE *pbKeyBlobSimple;          // Указатель на сессионный ключевой BLOB
DWORD dwBlobLenSimple;          // Длина сессионного ключевого BLOBа
FILE *Public;                   // Файл, в котором хранится открытый ключ
FILE *source;                   // Исходный файл
FILE *encrypt;                  // Зашифрованный файл
FILE *session;                  // Файл для хранения сессионного ключа
FILE *vector;                   // Файл для хранения вектора инициализации
BYTE pbContent[4096];           // Указатель на содержимое исходного файла
DWORD cbContent = 0;            // Длина содержимого
BYTE *pbIV = NULL;              // Вектор инициализации сессионного ключа
DWORD dwIV = 0;                 // Длина вектора инициализации
DWORD bufLen = sizeof(pbContent);   // Длина буфера

//--------------------------------------------------------------------
// Открытие файла, в котором содержится открытый ключ получателя.

Public = fopen( "public.bin", "r+b" );

if(Public)
{
    printf( "The file 'public.bin' was opened\n" );
}
else
{
    HandleError( "Problem opening the file 'public.bin'\n" );
}

//--------------------------------------------------------------------
// Открытие файла, который будет зашифрован.

source = fopen( "source.txt", "r+b" );

if(source)
{
    printf( "The file 'source.txt' was opened\n" );
}
else
{
    HandleError( "Problem opening the file 'source.txt'\n" );
}

//--------------------------------------------------------------------
// Открытие файла, в который будет производится запись зашифрованного
// файла.

encrypt = fopen( "encrypt.bin", "w+b" );

if(encrypt)
{
    printf( "The file 'encrypt.bin' was opened\n" );
}
else
{
    HandleError( "Problem opening the file 'encrypt.bin'\n" );
}

//--------------------------------------------------------------------
// Открытие файла, в который производится запись сессионного ключа.

session = fopen( "session.bin", "w+b" );

if(session)
{
    printf( "The file 'session.bin' was opened\n" );
}
else
{
    HandleError( "Problem opening the file 'session.bin'\n" );
}

//--------------------------------------------------------------------
// Открытие файла, в который производится запись вектора инициализации.

vector = fopen( "vector.bin", "w+b" );

if(vector)
{
    printf( "The file 'vector.bin' was opened\n" );
}
else
{
    HandleError( "Problem opening the file 'vector.bin'\n" );
}

//--------------------------------------------------------------------
// Получение дескриптора контейнера получателя с именем "Public",
// находящегося в рамках провайдера.

if(CryptAcquireContext(
   &hProv,
   "Public",
   NULL,
   75,
   0))
{
    printf("The key container \"Public\" has been acquired. \n");
}
else
{
    HandleError("Error during CryptAcquireContext.");
}

//--------------------------------------------------------------------
// Чтение  открытого ключа получателя из файла.

dwBlobLen = (DWORD)fread(pbKeyBlob, 1, 100, Public);

if(dwBlobLen)
{
    printf( "The public key was read from the 'public.bin'\n" );
}
else
{
    HandleError( "The public key can not be reading from the 'public.bin'\n" );
}

fclose(Public);

//--------------------------------------------------------------------
// Получение дескриптора закрытого ключа отправителя.

if(CryptGetUserKey(
   hProv,
   AT_KEYEXCHANGE,
   &hKey))
{
    printf("The private key has been acquired. \n");
}
else
{
    printf("Error during CryptGetUserKey private key.");
}

//--------------------------------------------------------------------
// Получение ключа согласования импортом открытого ключа получателя
// на закрытом ключе отправителя.

if (CryptImportKey(
    hProv,
    pbKeyBlob,
    dwBlobLen,
    hKey,
    0,
    &hAgreeKey))
{
    printf("The responder public key has been imported. \n");
}
else
{
    printf("Error during CryptImportKey public key.");
}

//--------------------------------------------------------------------
// Генерация сессионного ключа.

if (CryptGenKey(
    hProv,
    CALG_G28147,
    CRYPT_EXPORTABLE,
    &hSessionKey))
{
    printf("Original session key is created. \n");
}
else
{
   HandleError("ERROR -- CryptGenKey.");
}

//--------------------------------------------------------------------
// Зашифрование сессионного ключа.
//--------------------------------------------------------------------

//--------------------------------------------------------------------
// Определение размера BLOBа сессионного ключа и распределение памяти.

if(CryptExportKey(
   hSessionKey,
   hAgreeKey,
   SIMPLEBLOB,
   0,
   NULL,
   &dwBlobLenSimple))
{
     printf("Size of the BLOB for the sender session key determined. \n");
}
else
{
     HandleError("Error computing BLOB length.");
}

pbKeyBlobSimple = (BYTE*)malloc(dwBlobLenSimple);

if(pbKeyBlobSimple)
{
    printf("Memory has been allocated for the BLOB. \n");
}
else
{
    HandleError("Out of memory. \n");
}
//--------------------------------------------------------------------
// Зашифрование сессионного ключа на ключе Agree.

if(CryptExportKey(
   hSessionKey,
   hAgreeKey,
   SIMPLEBLOB,
   0,
   pbKeyBlobSimple,
   &dwBlobLenSimple))
{
     printf("Contents have been written to the BLOB. \n");
}
else
{
    HandleError("Error during CryptExportKey.");
}

//--------------------------------------------------------------------
// Определение размера вектора инициализации сессионного ключа.

if (CryptGetKeyParam(
    hSessionKey,
    KP_IV,
    NULL,
    &dwIV,
    0))
{
    printf("Size of the IV for the session key determined. \n");
}
else
{
     HandleError("Error computing IV length.");
}

pbIV = (BYTE*)malloc(dwIV);

if (pbIV)
{
    printf("Memory has been allocated for the IV. \n");
}
else
{
    HandleError("Out of memory. \n");
}

//--------------------------------------------------------------------
// Определение вектора инициализации сессионного ключа.

if (CryptGetKeyParam(
    hSessionKey,
    KP_IV,
    pbIV,
    &dwIV,
    0))
{
    printf( "CryptGetKeyParam succeeded. \n");
}
else
{
    HandleError("Error during CryptGetKeyParam.");
}

//--------------------------------------------------------------------
// Запись вектора инициализации в файл.

if(fwrite(
   pbIV,
   1,
   dwIV,
   vector))
{
    printf( "The IV was written to the 'vector.bin'\n" );
}
else
{
    HandleError( "The IV can not be written to the 'vector.bin'\n" );
}

//--------------------------------------------------------------------
// Запись зашифрованного сессионного ключа в файл.

if(fwrite(
   pbKeyBlobSimple,
   1,
   dwBlobLenSimple,
   session))
{
    printf( "The session key was written to the 'session.bin'\n" );
}
else
{
    HandleError( "The session key can not be written to the 'session.bin'\n" );
}

//--------------------------------------------------------------------
// Чтение  файла, который будет зашифрован блоками по 4 КБ. Зашифрование
// прочитанного блока и запись его в файл "encrypt.bin".
//--------------------------------------------------------------------

do
{
    cbContent = (DWORD)fread(pbContent, 1, 4096, source);
    if(cbContent)
    {
       // Зашифрование прочитанного блока на сессионном ключе.
        if(CryptEncrypt(
          hSessionKey,
          0,
          TRUE,
          0,
          pbContent,
          &cbContent,
          bufLen))
        {
            printf( "Encryption succeeded. \n");
            // Запись зашифрованного блока в файл.
            if(fwrite(
                pbContent,
                1,
                cbContent,
                encrypt))
            {
                printf( "The encrypted content was written to the 'encrypt.bin'\n" );
            }
            else
            {
                HandleError( "The encrypted content can not be written to the 'encrypt.bin'\n" );
            }
        }
        else
        {
            HandleError("Encryption failed.");
        }
    }
    else
    {
        HandleError( "Problem reading the file 'source.txt'\n" );
    }
}
while (!feof(source));

//--------------------------------------------------------------------
// Закрытие файлов.

fclose (source);
fclose (encrypt);
fclose (session);
fclose (vector);

//--------------------------------------------------------------------
//  Освобождение памяти, используемой ключевым BLOBом.

free(pbKeyBlobSimple);

// Уничтожение дескриптора закрытого ключа.
if(hKey)
     CryptDestroyKey(hKey);

// Уничтожение дескриптора сессионного ключа.
if(hSessionKey)
     CryptDestroyKey(hSessionKey);

// Уничтожение дескриптора ключа согласования.
if(hAgreeKey)
     CryptDestroyKey(hAgreeKey);

// Освобождение дескриптора провайдера.
if(hProv)
   CryptReleaseContext(hProv, 0);

printf("The program ran to completion without error. \n");

}// Конец main

    Требования:

    Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
    Solaris: 9 Update 4 или выше.
    FreeBSD: FreeBSD 5.2 или выше
    Linux: RedHat 7.3, RedHad 9.0.
    Ядро Windows NT: не поддерживает.


Крипто-Про CSP

Этот пример демонстрирует использование следующих функций
  • CryptAcquireContext в MS CryptoAPI 2.0 World Wide Web link
  • CryptGetUserKey в MS CryptoAPI 2.0 World Wide Web link
  • CryptImportKey в MS CryptoAPI 2.0 World Wide Web link
  • CryptSetKeyParam в MS CryptoAPI 2.0 World Wide Web link
  • CryptDecrypt в MS CryptoAPI 2.0 World Wide Web link
  • CryptDestroyKey в MS CryptoAPI 2.0 World Wide Web link
  • CryptReleaseContext в MS CryptoAPI 2.0 World Wide Web link

//--------------------------------------------------------------------
// Данный пример демонстрирует расшифрование файла на сессионном ключе.
// Для корректной работы этого примера передаваемые ему входные данные
// должны являться результатом работы примера EncryptFile.
// Зашифрованный сессионный ключ содержится в файле "session.bin".
// Для его расшифрования необходим открытый ключ отправителя, содержащийся
// в файле "public.bin" (данный файл создается при выполнении примера
// ExportInFile).
// Для корректной работы этой программы необходимо получить зашифрованный
// файл с именем "encrypt.bin". Для правильного расшифрования файла
// необходим вектор инициализации, который хранится в файле "vector.bin".
// Расшифрование производится в файл "destination.txt".
// Следует сделить за тем, чтобы контейнер с именем "Public", используемый
// в программах ExportInFile и EncryptFile, на момент выполнения данной программы
// существовал.
//--------------------------------------------------------------------

void HandleError(char *s);

int main(void)
{
//--------------------------------------------------------------------
//  Объявление и инициализация переменных.

HCRYPTPROV hProv;               // Дескриптор CSP
HCRYPTKEY hKey;                 // Дескриптор закрытого ключа
HCRYPTKEY hSessionKey;          // Дескриптор сессионного ключа
HCRYPTKEY hAgreeKey;            // Дескриптор ключа согласования
BYTE  pbKeyBlob[100];           // Указатель на ключевой BLOB
DWORD dwBlobLen;                // Длина ключевого BLOBа
BYTE pbKeyBlobSimple[100];      // Указатель на сессионный ключевой BLOB
DWORD dwBlobLenSimple;          // Длина сессионного ключевого BLOBа
FILE *encrypt;                  // Зашифрованный файл
FILE *Public;                   // Файл, в котором хранится открытый ключ
FILE *session;                  // Файл для хранения сессионного ключа
FILE *vector;                   // Файл для хранения вектора инициализации
FILE *destination;              // Расшифрованный файл
BYTE pbIV[100];                 // Вектор инициализации сессионного ключа
DWORD dwIV = 0;                 // Длина вектора инициализации
BYTE pbContent[4096];           // Указатель на содержимое зашифрованного файла
DWORD cbContent = 0;            // Длина содержимого

//--------------------------------------------------------------------
// Открытие файла, в котором содержится открытый ключ отправителя.

Public = fopen( "public.bin", "r+b" );

if(Public)
{
    printf( "The file 'public.bin' was opened\n" );
}
else
{
    HandleError( "Problem opening the file 'public.bin'\n" );
}

//--------------------------------------------------------------------
// Открытие файла, в котором хранится зашифрованный файл.

encrypt = fopen( "encrypt.bin", "r+b" );

if(encrypt)
{
    printf( "The file 'encrypt.bin' was opened\n" );
}
else
{
    HandleError( "Problem opening the file 'encrypt.bin'\n" );
}

//--------------------------------------------------------------------
// Открытие файла, в котором хранится сессионный ключ.

session = fopen( "session.bin", "r+b" );

if(session)
{
    printf( "The file 'session.bin' was opened\n" );
}
else
{
    HandleError( "Problem opening the file 'session.bin'\n" );
}

//--------------------------------------------------------------------
// Открытие файла, в котором хранится вектор инициализации.

vector = fopen( "vector.bin", "r+b" );

if(vector)
{
    printf( "The file 'vector.bin' was opened\n" );
}
else
{
    HandleError( "Problem opening the file 'vector.bin'\n" );
}

//--------------------------------------------------------------------
// Открытие файла, в который будет записан расшифрованный файл.

destination = fopen( "destination.txt", "w+b" );

if(destination)
{
    printf( "The file 'destination.txt' was opened\n" );
}
else
{
    HandleError( "Problem opening the file 'destination.txt'\n" );
}

//--------------------------------------------------------------------
// Чтение  вектора инициализации из файла.

dwIV = (DWORD)fread(pbIV, 1, 100, vector);

if(dwIV)
{
    printf( "The IV was read from the 'vector.bin'\n" );
}
else
{
    HandleError( "The IV can not be reading from the 'vector.bin'\n" );
}

//--------------------------------------------------------------------
// Получение дескриптора контейнера получателя с именем "Public",
// находящегося в рамках провайдера.

if(CryptAcquireContext(
   &hProv,
   "Public",
   NULL,
   75,
   0))
{
    printf("The key container \"Public\" has been acquired. \n");
}
else
{
    HandleError("Error during CryptAcquireContext.");
}

//--------------------------------------------------------------------
// Чтение  сесcионного ключа из файла.

dwBlobLenSimple = (DWORD)fread(pbKeyBlobSimple, 1, 100, session);

if(dwBlobLenSimple)
{
    printf( "The session key was read from the 'session.bin'\n" );
}
else
{
    HandleError( "The session key can not be reading from the 'session.bin'\n" );
}

//--------------------------------------------------------------------
// Чтение  открытого ключа отправителя из файла.

dwBlobLen = (DWORD)fread(pbKeyBlob, 1, 100, Public);

if(dwBlobLen)
{
    printf( "The public key was read from the 'public.bin'\n" );
}
else
{
    HandleError( "The public key can not be reading from the 'public.bin'\n" );
}

fclose(Public);

//--------------------------------------------------------------------
// Получение дескриптора закрытого ключа получателя.

if(CryptGetUserKey(
   hProv,
   AT_KEYEXCHANGE,
   &hKey))
{
    printf("The private key has been acquired. \n");
}
else
{
    printf("Error during CryptGetUserKey private key.");
}

//--------------------------------------------------------------------
// Получение ключа согласования импортом открытого ключа отправителя
// на закрытом ключе получателя.

if (CryptImportKey(
    hProv,
    pbKeyBlob,
    dwBlobLen,
    hKey,
    0,
    &hAgreeKey))
{
    printf("The sender public key has been imported. \n");
}
else
{
    printf("Error during CryptImportKey public key.");
}

//--------------------------------------------------------------------
// Получение сессионного ключа импортом зашифрованного сессионного ключа
// на ключе Agree.

if (CryptImportKey(
    hProv,
    pbKeyBlobSimple,
    dwBlobLenSimple,
    hAgreeKey,
    0,
    &hSessionKey))
{
    printf("The session key has been imported. \n");
}
else
{
    printf("Error during CryptImportKey session key.");
}

//--------------------------------------------------------------------
// Установка вектора инициализации - без него первые 8 байт
// расшифруются неправильно.

if (CryptSetKeyParam(
    hSessionKey,
    KP_IV,
    pbIV,
    0))
{
    printf( "CryptSetKeyParam succeeded. \n");
}
else
{
    HandleError("Error during CryptSetKeyParam.");
}

//--------------------------------------------------------------------
// Чтение  зашифрованного файла блоками по 4 КБ. Расшифрование прочитанного
// блока и запись его в файл "destination.txt".
//--------------------------------------------------------------------

do
{
    cbContent = (DWORD)fread(pbContent, 1, 4096, encrypt);
    if(cbContent)
    {
       // Расшифрование прочитанного блока на сессионном ключе.
        if(CryptDecrypt(
          hSessionKey,
          0,
          TRUE,
          0,
          pbContent,
          &cbContent))
        {
            printf( "Decryption succeeded. \n");
            // Запись расшифрованного блока в файл.
            if(fwrite(
                pbContent,
                1,
                cbContent,
                destination))
            {
                printf( "The decrypted content was written to the 'destination.txt'\n" );
            }
            else
            {
                HandleError( "The decrypted content can not be written to the 'destination.txt'\n" );
            }
        }
        else
        {
            HandleError("Decryption failed.");
        }
    }
    else
    {
        HandleError( "Problem reading the file 'encrypt.bin'\n" );
    }
}
while (!feof(encrypt));

//--------------------------------------------------------------------
// Закрытие файлов.

fclose (encrypt);
fclose (session);
fclose (vector);
fclose (destination);

// Уничтожение дескриптора закрытого ключа.
if(hKey)
     CryptDestroyKey(hKey);

// Уничтожение дескриптора сессионного ключа.
if(hSessionKey)
     CryptDestroyKey(hSessionKey);

// Уничтожение дескриптора ключа согласования.
if(hAgreeKey)
     CryptDestroyKey(hAgreeKey);

// Освобождение дескриптора провайдера.
if(hProv)
   CryptReleaseContext(hProv, 0);

printf("The program ran to completion without error. \n");

}// Конец main

    Требования:

    Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
    Solaris: 9 Update 4 или выше.
    FreeBSD: FreeBSD 5.2 или выше
    Linux: RedHat 7.3, RedHad 9.0.
    Ядро Windows NT: не поддерживает.


Примеры работы в драйвере.

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

  • Пример на зашифрование сообщения в драйвере
  • Пример на проверку подписи в драйвере


Пример на зашифрование сообщения в драйвере

Этот пример демонстрирует использование следующих функций
  • CPAcquireContext
  • CPGenKey
  • CPImportKey
  • CPExportKey
  • CPSetKeyParam
  • CPGetKeyParam
  • CPSetProvParam
  • CPEncrypt
  • CPDestroyKey
  • CPReleaseContext

//--------------------------------------------------------------------
// Пример кода, в котором описан процесс зашифрования драйвером
// сообщения, на основе информации, полученной от пользователя.
// В данной программе от пользователя получен пакет, в котором содержится
// следующая информация:
// - длина открытого ключа пользователя
// - открытый ключ пользователя
// - длина BLOBа для инициализации ДСЧ
// - BLOB для инициализации ДСЧ
// - длина BLOBа для хранения параметра KP_DHOID
// - BLOB для хранения параметра KP_DHOID
// Вся эта информация передается через InputBuffer.
//
// В действительности процесс расшифрования можно разбить на 3 основные части:
// - Инициализация контекста. Для этой части необходимо, чтобы отправителем
// сообщения являлся CSP. Для каждого получателя инициализация контектса
// осуществляется один раз, после чего может проводится обмен пакетами
// с отправителем.
//
// - Получение Agree ключа с другой стороной (с отправителем). Для этой части
// отправителем может быть не только CSP, но и драйвер. Для каждого получателя
// эта часть процесса осуществляется один раз.
//
// - Собственно зашифрование сообщения. Для каждого сообщения эта часть
// процесса осуществляется заново (после того, как Agree ключи согласованы,
// обмен пакетами может производиться любое число раз).
//--------------------------------------------------------------------

NTSTATUS Encrypt( PCHAR inBuf, ULONG  inBufLength, PCHAR outBuf,
    ULONG *outBufLength )
{
//--------------------------------------------------------------------
//  Объявление и инициализация переменных.

    CRYPT_UINT_BLOB BLOB;
    VTABLEPROVSTRUC VTable;
    HCRYPTPROV hProv;           // Дескриптор CSP
    DWORD keyLen = 0;           // Длина BLOBа открытого ключа пользователя
    DWORD RNGLen = 0;           // Длина BLOBа ДСЧ
    DWORD ParamLenD = 0;        // Длина BLOBа для хранения параметра KP_DHOID
    BYTE* ParamD ;              // BLOB для хранения параметра KP_DHOID
    BYTE* keyBLOB;              // BLOB открытого ключа пользователя
    BYTE* RNGBLOB;              // BLOB ДСЧ
    BYTE *pbKeyBlobSimple;      // Указатель на сессионный ключевой BLOB
    DWORD dwBlobLenSimple = 0;  // Длина сессионного ключевого BLOBа
    BYTE *pbKeyBlob;            // Указатель на BLOB открытого ключа драйвера
    DWORD dwBlobLen = 0;        // Длина BLOBа открытого ключа драйвера
    BYTE *pbParamBlob;          // Указатель на BLOB для передачи параметра KP_CIPHEROID
    DWORD dwParamBlobLen = 0;   // Длина BLOBа для передачи параметра KP_CIPHEROID
    HCRYPTKEY hDriverKey;       // Дескриптор открытого ключа драйвера
    HCRYPTKEY hSessionKey;      // Дескриптор сессионного ключа
    HCRYPTKEY hAgreeKey;        // Дескриптор ключа согласования
    BYTE *pbIV = NULL;          // Вектор инициализации сессионного ключа
    DWORD dwIV = 0;             // Длина вектора инициализации
    BYTE pbContent[100] = { "Security is our business." }; // Сообщение
    DWORD cbContent = (DWORD)(strlen((char *)pbContent)+1); // Длина сообщения
    DWORD bufLen = sizeof(pbContent);   // Длина буфера

//--------------------------------------------------------------------
// Часть 1 - получение контекста.
//--------------------------------------------------------------------

//--------------------------------------------------------------------
// Заполнение таблицы. Необходимо для корректной работы провайдера.
    VTable.Version = 3;
    VTable.dwProvType = 75;
    VTable.pszProvName = "Crypto-Pro GOST R 34.10-2001 Cryptographic Service Provider";
    VTable.cbContextInfo = 0;
    VTable.pbContextInfo = NULL;
    VTable.FuncReturnhWnd = &FunReturnHWnd;
    VTable.FuncVerifyImage = &FunVerifyImage;

//--------------------------------------------------------------------
// Получение дескриптора провайдера без доступа к закрытым ключам.

    if(CPAcquireContext(
                &hProv,
                NULL,
                CRYPT_VERIFYCONTEXT,
                &VTable ))
    {
        CPIOCTL_KDPRINT(("CPAcquireContext succeeded.\n"));
    }
    else
    {
        CPIOCTL_KDPRINT(("Error: CPAcquireContext Failed."));
        return STATUS_UNSUCCESSFUL;
    }

//--------------------------------------------------------------------
// Получение BLOBа открытого ключа пользователя, BLOBа ДСЧ, BLOBов для
// хранения параметров ключа пользователя и их длин из InputBuffer.

    memcpy(&keyLen, inBuf, sizeof(DWORD));
    keyBLOB = (BYTE*)ExAllocatePoolWithTag( PagedPool, keyLen, CPTEST_POOL );
    memcpy(keyBLOB, inBuf + sizeof(DWORD), keyLen);

    memcpy(&RNGLen, inBuf + sizeof(DWORD) + keyLen, sizeof(DWORD));
    RNGBLOB = (BYTE*)ExAllocatePoolWithTag( PagedPool, RNGLen, CPTEST_POOL );
    memcpy(RNGBLOB, inBuf + 2*sizeof(DWORD) + keyLen, RNGLen);

    memcpy(&ParamLenD, inBuf + 2*sizeof(DWORD) + keyLen + RNGLen, sizeof(DWORD));
    ParamD = (BYTE*)ExAllocatePoolWithTag( PagedPool, ParamLenD, CPTEST_POOL );
    memcpy(ParamD, inBuf + 3*sizeof(DWORD) + keyLen + RNGLen, ParamLenD);

//--------------------------------------------------------------------
// Установка параметра PP_RANDOM. Необходимо для корректной работы
// провайдера (инициализация ДСЧ).

    BLOB.cbData = RNGLen;
    BLOB.pbData = RNGBLOB;

    if(CPSetProvParam(
                hProv,
                PP_RANDOM,
                (BYTE*)&BLOB,
                0))
    {
        CPIOCTL_KDPRINT(("CPSetProvParam succeeded.\n"));
    }
    else
    {
        CPIOCTL_KDPRINT(("Error: CPSetProvParam Failed."));
        return STATUS_UNSUCCESSFUL;
    }

//--------------------------------------------------------------------
// Подготовка эфемерного ключа драйвера.

    if(CPGenKey(
        hProv,
        CALG_DH_EL_EPHEM,
        CRYPT_PREGEN,
        &hDriverKey))
    {
        CPIOCTL_KDPRINT(("Created a ephemeral driver key.\n"));
    }
    else
    {
        CPIOCTL_KDPRINT(("Error: CPGenKey Failed."));
        return STATUS_UNSUCCESSFUL;
    }

//--------------------------------------------------------------------
// Установка параметра KP_DHOID (согласование с CSP).

// По умолчанию драйвер работает на наборе параметров 1.2.643.2.2.35.1.
// Без установки параметра KP_DHOID программа будет неверно работать,
// если параметры алгоритма Диффи-Хелмана не будут являться параметрами
// по умолчанию.

 if(CPSetKeyParam(
        hProv,
        hDriverKey,
        KP_DHOID,
        ParamD,
        0))
{
    CPIOCTL_KDPRINT(("The parameters have been set. \n"));
}
else
{
    CPIOCTL_KDPRINT(("Error during SetKeyParam."));
    return STATUS_UNSUCCESSFUL;
}

//--------------------------------------------------------------------
// Генерация эфемерного ключа (с установленным параметром KP_DHOID).

    if(CPSetKeyParam(
        hProv,
        hDriverKey,
        KP_X,
        NULL,
        0))
{
    CPIOCTL_KDPRINT(("The key is generated. \n"));
}
else
{
    CPIOCTL_KDPRINT(("Error during SetKeyParam."));
    return STATUS_UNSUCCESSFUL;
}

//--------------------------------------------------------------------
// Часть 2 - получение ключа согласования.
//--------------------------------------------------------------------

//--------------------------------------------------------------------
// Получение ключа согласования импортом открытого ключа пользователя
// на открытом ключе драйвера.

if (CPImportKey(
    hProv,
    keyBLOB,
    keyLen,
    hDriverKey,
    0,
    &hAgreeKey))
{
    CPIOCTL_KDPRINT(("The Agree key has been acquired. \n"));
}
else
{
    CPIOCTL_KDPRINT(("Error: CPImportKey Failed."));
    return STATUS_UNSUCCESSFUL;
}

//--------------------------------------------------------------------
// Передача параметра KP_CIPHEROID ключа согласования.

// По умолчанию CSP работает на наборе параметров 1.2.643.2.2.31.1.
// Без установки параметра KP_CIPHEROID программа будет неверно работать,
// если параметры шифрования для CSP не будут являться параметрами по умолчанию.

//--------------------------------------------------------------------
// Определение размера BLOBа и распределение памяти.

if(CPGetKeyParam(
   hProv,
   hAgreeKey,
   KP_CIPHEROID,
   NULL,
   &dwParamBlobLen,
   0))
{
     CPIOCTL_KDPRINT(("Size of the BLOB determined. \n"));
}
else
{
     CPIOCTL_KDPRINT(("Error computing BLOB length."));
     return STATUS_UNSUCCESSFUL;
}

pbParamBlob = (BYTE*)ExAllocatePoolWithTag( PagedPool, dwParamBlobLen, CPTEST_POOL );

if(pbParamBlob)
{
    CPIOCTL_KDPRINT(("Memory has been allocated for the pbParamBlob. \n"));
}
else
{
    CPIOCTL_KDPRINT(("Out of memory. \n"));
    return STATUS_UNSUCCESSFUL;
}

//--------------------------------------------------------------------
// Копирование параметров ключа в pbParamBlob.

if(CPGetKeyParam(
   hProv,
   hAgreeKey,
   KP_CIPHEROID,
   pbParamBlob,
   &dwParamBlobLen,
   0))
{
     CPIOCTL_KDPRINT(("Parameters have been written to the pbParamBlob. \n"));
}
else
{
    CPIOCTL_KDPRINT(("Error during CPGetKeyParam."));
    return STATUS_UNSUCCESSFUL;
}

//--------------------------------------------------------------------
// Получение сессионного ключа драйвера.

    if(CPGenKey(
        hProv,
        CALG_G28147,
        CRYPT_EXPORTABLE,
        &hSessionKey))
    {
        CPIOCTL_KDPRINT(("Created a session driver key.\n"));
    }
    else
    {
        CPIOCTL_KDPRINT(("Error: CPGenKey Failed."));
        return STATUS_UNSUCCESSFUL;
    }

//--------------------------------------------------------------------
// Экспортирование сессионного ключа на ключе Agree в SIMPLEBLOB.
//
//--------------------------------------------------------------------

//--------------------------------------------------------------------
// Определение размера BLOBа сессионного ключа и распределение памяти.

if(CPExportKey(
   hProv,
   hSessionKey,
   hAgreeKey,
   SIMPLEBLOB,
   0,
   NULL,
   &dwBlobLenSimple))
{
     CPIOCTL_KDPRINT(("Size of the BLOB for the session key determined. \n"));
}
else
{
     CPIOCTL_KDPRINT(("Error computing BLOB length."));
     return STATUS_UNSUCCESSFUL;
}

pbKeyBlobSimple = (BYTE*)ExAllocatePoolWithTag( PagedPool, dwBlobLenSimple, CPTEST_POOL );

if(pbKeyBlobSimple)
{
    CPIOCTL_KDPRINT(("Memory has been allocated for the BLOB. \n"));
}
else
{
    CPIOCTL_KDPRINT(("Out of memory. \n"));
    return STATUS_UNSUCCESSFUL;
}
//--------------------------------------------------------------------
// Шифрование сессионного ключа на ключе Agree.

if(CPExportKey(
   hProv,
   hSessionKey,
   hAgreeKey,
   SIMPLEBLOB,
   0,
   pbKeyBlobSimple,
   &dwBlobLenSimple))
{
     CPIOCTL_KDPRINT(("Contents have been written to the BLOB. \n"));
}
else
{
    CPIOCTL_KDPRINT(("Error during CryptExportKey."));
    return STATUS_UNSUCCESSFUL;
}

//--------------------------------------------------------------------
// Экспортирование открытого ключа драйвера в PUBLICKEYBLOB.
//
//--------------------------------------------------------------------

//--------------------------------------------------------------------
// Определение размера BLOBа открытого ключа и распределение памяти.

if(CPExportKey(
   hProv,
   hDriverKey,
   0,
   PUBLICKEYBLOB,
   0,
   NULL,
   &dwBlobLen))
{
     CPIOCTL_KDPRINT(("Size of the BLOB for the public key determined. \n"));
}
else
{
     CPIOCTL_KDPRINT(("Error computing BLOB length."));
     return STATUS_UNSUCCESSFUL;
}

pbKeyBlob = (BYTE*)ExAllocatePoolWithTag( PagedPool, dwBlobLen, CPTEST_POOL );

if(pbKeyBlob)
{
    CPIOCTL_KDPRINT(("Memory has been allocated for the BLOB. \n"));
}
else
{
    CPIOCTL_KDPRINT(("Out of memory. \n"));
    return STATUS_UNSUCCESSFUL;
}
//--------------------------------------------------------------------
// Экспортирование открытого ключа в BLOB.

if(CPExportKey(
   hProv,
   hDriverKey,
   0,
   PUBLICKEYBLOB,
   0,
   pbKeyBlob,
   &dwBlobLen))
{
     CPIOCTL_KDPRINT(("Contents have been written to the BLOB. \n"));
}
else
{
    CPIOCTL_KDPRINT(("Error during CryptExportKey."));
    return STATUS_UNSUCCESSFUL;
}

//--------------------------------------------------------------------
// Часть 3 - собственно зашифрование.
//--------------------------------------------------------------------

//--------------------------------------------------------------------
// Определение размера вектора инициализации сессионного ключа.

if (CPGetKeyParam(
    hProv,
    hSessionKey,
    KP_IV,
    NULL,
    &dwIV,
    0))
{
    CPIOCTL_KDPRINT(("Size of the IV for the session key determined. \n"));
}
else
{
     CPIOCTL_KDPRINT(("Error computing IV length."));
     return STATUS_UNSUCCESSFUL;
}

pbIV = (BYTE*)ExAllocatePoolWithTag( PagedPool, dwIV, CPTEST_POOL );

if (pbIV)
{
    CPIOCTL_KDPRINT(("Memory has been allocated for the IV. \n"));
}
else
{
    CPIOCTL_KDPRINT(("Out of memory. \n"));
    return STATUS_UNSUCCESSFUL;
}

//--------------------------------------------------------------------
// Определение вектора инициализации сессионного ключа.

if (CPGetKeyParam(
    hProv,
    hSessionKey,
    KP_IV,
    pbIV,
    &dwIV,
    0))
{
    CPIOCTL_KDPRINT(("CPGetKeyParam succeeded. \n"));
}
else
{
    CPIOCTL_KDPRINT(("Error during CPGetKeyParam."));
    return STATUS_UNSUCCESSFUL;
}

//--------------------------------------------------------------------
// Зашифрование исходного сообщения.

if(CPEncrypt(
   hProv,
   hSessionKey,
   0,
   TRUE,
   0,
   pbContent,
   &cbContent,
   bufLen))

{
    CPIOCTL_KDPRINT(("CPEncrypt succeeded. \n"));
}
else
{
    CPIOCTL_KDPRINT(("Error during CPEncrypt."));
    return STATUS_UNSUCCESSFUL;
}

//--------------------------------------------------------------------
// Определение длины OutputBuffer и запись в него следующей информации:
// - длина BLOBа открытого ключа драйвера
// - BLOB открытого ключа драйвера
// - длина BLOBа сессионного ключа драйвера
// - BLOB сессионного ключа драйвера
// - длина вектора инициализации
// - вектор инициализации
// - длина зашифрованного сообщения
// - зашифрованное сообщение
// - длина BLOBа для перечачи параметра KP_CIPHEROID
// - BLOB для перечачи параметра KP_CIPHEROID.

*outBufLength = 5*sizeof(DWORD) + dwBlobLen + dwBlobLenSimple + dwIV + cbContent + dwParamBlobLen;

memcpy(outBuf, &dwBlobLen, sizeof(DWORD));
memcpy(outBuf + sizeof(DWORD), pbKeyBlob, dwBlobLen);
memcpy(outBuf + sizeof(DWORD) + dwBlobLen, &dwBlobLenSimple, sizeof(DWORD));
memcpy(outBuf + 2*sizeof(DWORD) + dwBlobLen, pbKeyBlobSimple, dwBlobLenSimple);
memcpy(outBuf + 2*sizeof(DWORD) + dwBlobLen + dwBlobLenSimple, &dwIV, sizeof(DWORD));
memcpy(outBuf + 3*sizeof(DWORD) + dwBlobLen + dwBlobLenSimple, pbIV, dwIV);
memcpy(outBuf + 3*sizeof(DWORD) + dwBlobLen + dwBlobLenSimple + dwIV, &cbContent, sizeof(DWORD));
memcpy(outBuf + 4*sizeof(DWORD) + dwBlobLen + dwBlobLenSimple + dwIV, pbContent, cbContent);
memcpy(outBuf + 4*sizeof(DWORD) + dwBlobLen + dwBlobLenSimple + dwIV + cbContent, &dwParamBlobLen, sizeof(DWORD));
memcpy(outBuf + 5*sizeof(DWORD) + dwBlobLen + dwBlobLenSimple + dwIV + cbContent, pbParamBlob, dwParamBlobLen);

// Вся эта информация передается пакетом пользователю для расшифрования сообщения.

// Уничтожение дескриптора открытого ключа.
if(hDriverKey)
     CPDestroyKey(hProv, hDriverKey);

// Уничтожение дескриптора сессионного ключа.
if(hSessionKey)
     CPDestroyKey(hProv, hSessionKey);

// Уничтожение дескриптора ключа согласования.
if(hAgreeKey)
     CPDestroyKey(hProv, hAgreeKey);

// Освобождение дескриптора провайдера.
if(hProv)
   CPReleaseContext(hProv, 0);

// Освобождение памяти.
ExFreePool( pbIV );
ExFreePool( pbKeyBlob );
ExFreePool( pbKeyBlobSimple );
ExFreePool( keyBLOB );
ExFreePool( RNGBLOB );
ExFreePool( ParamD );
ExFreePool( pbParamBlob );

return STATUS_SUCCESS;
} // Конец Encrypt

    Требования:

    Ядро Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
    Ядро Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
    Ядро Solaris: 9 Update 4 или выше.
    Ядро FreeBSD: FreeBSD 5.2 или выше
    Ядро Linux: RedHat 7.3, RedHad 9.0.


Пример на проверку подписи в драйвере

Этот пример демонстрирует использование следующих функций
  • CPAcquireContext
  • CPImportKey
  • CPCreateHash
  • CPSetHashParam
  • CPHashData
  • CPVerifySignature
  • CPDestroyKey
  • CPReleaseContext

//--------------------------------------------------------------------
// Пример кода, в котором описан процесс проверки подписи, полученной
// от пользователя.
// В данной программе от пользователя получен пакет, в котором содержится
// следующая информация:
// - длина BLOBa открытого ключа пользователя
// - BLOB открытого ключа пользователя
// - длина BLOBa для хранения параметра HP_OID
// - BLOB для хранения параметра HP_OID
// - длина буфера подписи
// - буфер подписи
// - длина исходного сообщения
// - исходное сообщение
// Вся эта информация передается через InputBuffer.
//
// В действительности процесс расшифрования можно разбить на 2 основные части:
// - Инициализация контекста. Для этой части необходимо, чтобы отправителем
// сообщения являлся CSP. Для каждого получателя инициализация контектса
// осуществляется один раз, после чего может проводится обмен пакетами
// с отправителем.
//
// - Проверка подписи. Для каждого сообщения эта часть процесса
// осуществляется заново (после того, как инициализация выполнена,
// обмен пакетами может производиться любое число раз).
//--------------------------------------------------------------------

NTSTATUS Verify( PCHAR inBuf, ULONG  inBufLength, PCHAR outBuf,
    ULONG *outBufLength )
{
//--------------------------------------------------------------------
//  Объявление и инициализация переменных.

    VTABLEPROVSTRUC VTable;
    HCRYPTPROV hProv;           // Дескриптор CSP
    HCRYPTKEY hKey;             // Дескриптор открытого ключа пользователя
    HCRYPTHASH hHash;           // Объект функции хеширования
    BYTE *keyBLOB = NULL;       // BLOB открытого ключа пользователя
    DWORD keyLen = 0;           // Длина BLOBа открытого ключа пользователя
    BYTE *paramBLOB = NULL;     // BLOB для хранения параметра HP_OID
    DWORD paramLen = 0;         // Длина BLOBа для хранения параметра HP_OID
    BYTE *buffer = NULL;        // Буфер подписи
    DWORD bufLen = 0;           // Длина буфера подписи
    BYTE *message = NULL;       // Исходное сообщение
    DWORD messLen = 0;          // Длина исходного сообщения
    DWORD result;

//--------------------------------------------------------------------
// Часть 1 - получение контекста.
//--------------------------------------------------------------------

//--------------------------------------------------------------------
// Заполнение таблицы. Необходимо для корректной работы провайдера.
    VTable.Version = 3;
    VTable.dwProvType = 75;
    VTable.pszProvName = "Crypto-Pro GOST R 34.10-2001 Cryptographic Service Provider";
    VTable.cbContextInfo = 0;
    VTable.pbContextInfo = NULL;
    VTable.FuncReturnhWnd = &FunReturnHWnd;
    VTable.FuncVerifyImage = &FunVerifyImage;

//--------------------------------------------------------------------
// Получение дескриптора провайдера без доступа к закрытым ключам.

    if(CPAcquireContext(
                &hProv,
                NULL,
                CRYPT_VERIFYCONTEXT,
                &VTable ))
    {
        CPSIGNIOCTL_KDPRINT(("CPAcquireContext succeeded.\n"));
    }
    else
    {
        CPSIGNIOCTL_KDPRINT(("Error: CPAcquireContext Failed."));
        return STATUS_UNSUCCESSFUL;
    }

//--------------------------------------------------------------------
// Получение BLOBа открытого ключа пользователя, BLOBа для хранения
// параметра HP_OID, буфера подписи, исходного сообщения и их длин
// из InputBuffer.

    memcpy(&keyLen, inBuf, sizeof(DWORD));
    keyBLOB = (BYTE*)ExAllocatePoolWithTag( PagedPool, keyLen, CPTEST_POOL );
    memcpy(keyBLOB, inBuf + sizeof(DWORD), keyLen);

    memcpy(&paramLen, inBuf + sizeof(DWORD) + keyLen, sizeof(DWORD));
    paramBLOB = (BYTE*)ExAllocatePoolWithTag( PagedPool, paramLen, CPTEST_POOL );
    memcpy(paramBLOB, inBuf + 2*sizeof(DWORD) + keyLen, paramLen);

    memcpy(&bufLen, inBuf + 2*sizeof(DWORD) + keyLen + paramLen, sizeof(DWORD));
    buffer = (BYTE*)ExAllocatePoolWithTag( PagedPool, bufLen, CPTEST_POOL );
    memcpy(buffer, inBuf + 3*sizeof(DWORD) + keyLen + paramLen, bufLen);

    memcpy(&messLen, inBuf + 3*sizeof(DWORD) + keyLen + bufLen + paramLen, sizeof(DWORD));
    message = (BYTE*)ExAllocatePoolWithTag( PagedPool, messLen, CPTEST_POOL );
    memcpy(message, inBuf + 4*sizeof(DWORD) + keyLen + bufLen + paramLen, messLen);

//--------------------------------------------------------------------
// Получение откытого ключа пользователя, который создал цифровую подпись
// с помощью функции CPImportKey. Она возвращает дескриптор открытого
// ключа в hKey.

if(CPImportKey(
   hProv,
   keyBLOB,
   keyLen,
   0,
   0,
   &hKey))
{
     CPSIGNIOCTL_KDPRINT(("The key has been imported.\n"));
}
else
{
    CPSIGNIOCTL_KDPRINT(("Error: CPImportKey Failed."));
    return STATUS_UNSUCCESSFUL;
}

//--------------------------------------------------------------------
// Часть 1 - получение контекста.
//--------------------------------------------------------------------

//--------------------------------------------------------------------
// Создание объекта функции хеширования.

if(CPCreateHash(
   hProv,
   CALG_GR3411,
   0,
   0,
   &hHash))
{
     CPSIGNIOCTL_KDPRINT(("The hash object has been created. \n"));
}
else
{
    CPSIGNIOCTL_KDPRINT(("Error: CPCreateHash."));
    return STATUS_UNSUCCESSFUL;
}

//--------------------------------------------------------------------
// Установка параметра HP_OID (согласование с CSP).

// По умолчанию драйвер работает на наборе параметров 1.2.643.2.2.30.1.
// Без установки параметра HP_OID программа будет неверно работать,
// если параметры хеширования не будут являться параметрами
// по умолчанию.

   if(CPSetHashParam(
        hProv,
        hHash,
        HP_OID,
        paramBLOB,
        0))
{
    CPSIGNIOCTL_KDPRINT(("The parameters have been set. \n"));
}
else
{
    CPSIGNIOCTL_KDPRINT(("Error during SetHashParam."));
    return STATUS_UNSUCCESSFUL;
}

//--------------------------------------------------------------------
// Вычисление криптографического хеша сообщения.

if(CPHashData(
   hProv,
   hHash,
   message,
   messLen,
   0))
{
     CPSIGNIOCTL_KDPRINT(("The hash has been created.\n"));
}
else
{
    CPSIGNIOCTL_KDPRINT(("Error: CPHashData."));
    return STATUS_UNSUCCESSFUL;
}

//--------------------------------------------------------------------
// Проверка цифровой подписи и передача в OutputBuffer результата.

if(CPVerifySignature(
   hProv,
   hHash,
   buffer,
   bufLen,
   hKey,
   NULL,
   0))
{
    CPSIGNIOCTL_KDPRINT(("The signature has been verified.\n"));
    result = TRUE;
    memcpy(outBuf, &result, sizeof(DWORD));
}
else
{
     CPSIGNIOCTL_KDPRINT(("Signature not validated!\n"));
     result = FALSE;
     memcpy(outBuf, &result, sizeof(DWORD));
}

*outBufLength = sizeof(DWORD);

// Освобождение памяти.
ExFreePool( keyBLOB );
ExFreePool( paramBLOB );
ExFreePool( buffer );
ExFreePool( message );

// Уничтожение дескриптора открытого ключа.
if(hKey)
     CPDestroyKey(hProv, hKey);

//--------------------------------------------------------------------
// Уничтожение объекта функции хеширования.

if(hHash)
  CPDestroyHash(hProv, hHash);

// Освобождение дескриптора провайдера.
if(hProv)
   CPReleaseContext(hProv, 0);

return STATUS_SUCCESS;
}// Конец Verify

    Требования:

    Ядро Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
    Ядро Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).
    Ядро Solaris: 9 Update 4 или выше.
    Ядро FreeBSD: FreeBSD 5.2 или выше
    Ядро Linux: RedHat 7.3, RedHad 9.0.


Примеры использования функций криптопровайдера для работы с XML-документом.

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

  • Шаблон XML-документа на подпись
  • Шаблон XML-документа для создания двух подписей
  • Пример создания подписи XML-документа
  • Пример проверки подписи XML-документа
  • Пример создания и проверки двух подписей XML-документа


Шаблон XML-документа на подпись

Данный шаблон является обязательным шаблоном XML-документа, для которого осуществляется подпись.

<?xml version="1.0" encoding="UTF-8"?>
<ds:signatures xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:Signature Id="FirstSignature" >
  <ds:SignedInfo>
    <ds:CanonicalizationMethod
       Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
    <ds:SignatureMethod
    Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411"/>
    <ds:Reference URI="#obj"
      Type="http://www.w3.org/2000/09/xmldsig#;Object">
          <ds:DigestMethod
      Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr3411"/>
        <ds:DigestValue/>
    </ds:Reference>
  </ds:SignedInfo>
  <ds:SignatureValue />
  <ds:Object Id="obj" MimeType="text/xml">Hello, World!</ds:Object>
     <ds:KeyInfo></ds:KeyInfo>
</ds:Signature>

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше и MSXML 5.0.


Шаблон XML-документа для создания двух подписей

Данный шаблон является обязательным шаблоном XML-документа, для которого создаются две независимые подписи.

<?xml version="1.0" encoding="UTF-8"?>
<ds:signatures xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:Signature Id="FirstSignature" >
  <ds:SignedInfo>
    <ds:CanonicalizationMethod
       Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
    <ds:SignatureMethod
    Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411"/>
    <ds:Reference URI="#obj"
      Type="http://www.w3.org/2000/09/xmldsig#;Object">
          <ds:DigestMethod
      Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr3411"/>
        <ds:DigestValue/>
    </ds:Reference>
  </ds:SignedInfo>
  <ds:SignatureValue />
  <ds:Object Id="obj" MimeType="text/xml">Hello, World!</ds:Object>
     <ds:KeyInfo></ds:KeyInfo>
</ds:Signature>
<ds:Signature Id="SecondSignature">
  <ds:SignedInfo>
    <ds:CanonicalizationMethod
       Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
    <ds:SignatureMethod
    Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411"/>
    <ds:Reference URI="#obj"
      Type="http://www.w3.org/2000/09/xmldsig#;Object">
          <ds:DigestMethod
      Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr3411"/>
        <ds:DigestValue/>
    </ds:Reference>
  </ds:SignedInfo>
  <ds:SignatureValue />
     <ds:KeyInfo></ds:KeyInfo>
</ds:Signature>
</ds:signatures>

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше и MSXML 5.0.


Крипто-Про CSP

Этот пример демонстрирует использование следующих функций

  • CertOpenStore в MS CryptoAPI 2.0 World Wide Web link
  • CertFindCertificateInStore в MS CryptoAPI 2.0 World Wide Web link
  • CertGetCertificateContextProperty в MS CryptoAPI 2.0 World Wide Web link
  • CertFreeCertificateContext в MS CryptoAPI 2.0 World Wide Web link
  • CertCloseStore в MS CryptoAPI 2.0 World Wide Web link

//--------------------------------------------------------------------
// Пример создания подписи документа MSXML 5.0 на ключе, получаемом по
// имени ключевого контейнера. Имя контейнера, в свою очередь, получается
// из расширенных свойств заданного сертификата.
// Данная программа имеет два аргумента командной строки:
// 1) Имя исходного XML-документа (документ должен соответствовать
// шаблону, приведенному в примере).
// 2) Имя сертификата.
// Подписанным (выходным) XML-документом является файл "out_signature.xml".
//--------------------------------------------------------------------

#include <tchar.h>
#include <stdio.h>

#import <msxml5.dll>
using namespace MSXML2;

#define DSIGNS "xmlns:ds='http://www.w3.org/2000/09/xmldsig#'"

void HandleError(char *s);

//-------------------------------------------------------------
// Объявление и инициализация переменных.

IXMLDOMDocument3Ptr xmldoc = NULL;
IXMLDigitalSignaturePtr xmldsig = NULL;
VARIANT_BOOL objectsAreInitialized = VARIANT_FALSE;
PCCERT_CONTEXT pContext = NULL ; // Контекст сертификата
HCERTSTORE hStore = NULL; // Дескритор хранилища сертификатов
HCRYPTPROV hProv = 0 ; // Дескриптор криптопровайдера
DWORD dwPropId = CERT_KEY_PROV_INFO_PROP_ID; // Параметр для получения информации
                                            // из свойств сертификата
BYTE  *pbData; // Указатель на буфер данных, получаемых из свойств сертификата.
DWORD cbData;  // Длина буфера данных
TCHAR* fileName = NULL; //Имя подписываемого XML-документа
TCHAR* userName = NULL; //Имя сертификата, используемого для подписи
HRESULT hr; //Переменные, которые используются
BSTR bstr = NULL; //для получения XML документа

#undef CERT_FIND_SUBJECT_STR
#ifdef UNICODE
#define CERT_FIND_SUBJECT_STR  CERT_FIND_SUBJECT_STR_W
#else
#define CERT_FIND_SUBJECT_STR  CERT_FIND_SUBJECT_STR_A
#endif // !UNICODE

//---------------------------------------------------------------------------
// Описание функции загрузки XML-документа.
//---------------------------------------------------------------------------

VARIANT_BOOL LoadXML(_bstr_t sigFile)
{
   if (!objectsAreInitialized)
   {
      printf("Must initialize objects before loading signature.\n");
      return VARIANT_FALSE;
   }

   if (xmldoc->load(sigFile) == VARIANT_FALSE)
   {
      printf("Can't load %s\n", (LPCSTR)sigFile);
      return VARIANT_FALSE;
   }

   xmldoc->setProperty("SelectionNamespaces", DSIGNS);
//------------------------------------------------------------------------------
// Определение свойств подписи в соответствии с DOM узлом <ds:Signature>
// XML-документа.
   xmldsig->signature = xmldoc->selectSingleNode(".//ds:Signature");

   if (xmldsig->signature == NULL)
   {
      printf("Failed to set the signature property.\n");
      return VARIANT_FALSE;
   }

   return VARIANT_TRUE;

}// Конец описания функции LoadXML

//---------------------------------------------------------------------------
// Описание функции подписи XML-документа.
//
// Данная функция имеет параметр fwWriteKeyInfo, отвечающий
// за заполнение шаблона подписанного (выходного) XML-документа.
// Шаблон подписанного (выходного) XML-документа изначально включает в себя
// три пустых элемента: <ds:DigestValue>, <ds:SignatureValue>  и  <ds:KeyInfo>.
// Первые два заполняются после выполнения функции SignXML(fwWriteKeyInfo).
// Последний будет заполнен только в том случае, если функции
// в качестве параметра fwWriteKeyInfo передаётся KEYVALUE.
// Параметр не меняется, если fwWriteKeyInfo = NOKEYINFO и всё
// содержимое элементов очищается в случае  fwWriteKeyInfo = PURGE.
// Когда fwWriteKeyInfo = CERTIFICATES,  заполняется элемент <X509Data>
// при условии, что сертификат ключа, который используется, доступен.
//
// Также параметр fwWriteKeyInfo может представлять собой комбинацию
// перечисленных выше значений, объединённых знаком "|" :
// KEYVALUE | CERTIFICATES  - Добавляет значение ключа и сертификаты в <ds:KeyInfo>,
//                         не изменяя другие элементы.
// KEYVALUE | CERTIFICATES | PURGE - Сначала удаляет всё из <ds:KeyInfo>, а затем
//                          добавляет значение ключа и сертификаты.
// KEYVALUE | PURGE - Сначала удаляет всё из <ds:KeyInfo>, а  затем добавляет значение ключа.
// CERTIFICATES | PURGE - Сначала удаляет всё из <ds:KeyInfo>, а затем добавляет сертификаты.
//---------------------------------------------------------------------------

VARIANT_BOOL SignXML(XMLDSIG_WRITEKEYINFO fwWriteKeyInfo)
{
    if (xmldsig->signature == NULL)
    {
      printf("Invalid signature template\n");
      return false;
    }

//------------------------------------------------------------------------------
// Открытие хранилища сертификатов "MY" текущего пользователя.
    hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM,
                            0,
                            0,
                            CERT_STORE_OPEN_EXISTING_FLAG|CERT_STORE_READONLY_FLAG|
                            CERT_SYSTEM_STORE_CURRENT_USER,
                            L"MY");
    if (!hStore)
    {
        HandleError("The store could not be opened!\n");
    }
    else
    {
        printf("The store is open!\n");
    }

//-----------------------------------------------------------------
// Получение сертификата с заданным именем из хранилища сертификатов.
    pContext = CertFindCertificateInStore(  hStore,
                                            X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
                                            0,
                                            CERT_FIND_SUBJECT_STR,
                                            userName,
                                            NULL);
    if(pContext == NULL)
    {
        HandleError("There is no such a certificate in the store\n");
    }

//--------------------------------------------------------------------------
// Указатель на структуру CRYPT_KEY_PROV_INFO, содержащую подробную информацию
// о ключевом контейнере.
    CRYPT_KEY_PROV_INFO *pbData;

//--------------------------------------------------------------------------
// Получение информации из расширенных свойств контекста сертификата. Определение размера
// возвращаемых данных.
    if(CertGetCertificateContextProperty(pContext,
                                        dwPropId,
                                        NULL,
                                        &cbData))
    {
        printf("CertGetCertificateContextProperty was started for the 1-st time\n");
    }
    else
    {
        printf("CertGetCertificateContextProperty was started for the 1-st time\n");
        HandleError("It's impossible to get the certificate property!\n ");
    }

//-------------------------------------------------------------------------
// Выделение памяти.

    if(pbData = (CRYPT_KEY_PROV_INFO*)malloc(cbData))
    {
        printf("Memory has been allocated.\n");
    }
    else
    {
        HandleError("Malloc operation failed. ");
    }
//------------------------------------------------------------------------
// Получение подробной информации о ключевом контейнере из расширенных свойств
// контекста сертификата.

    if(CertGetCertificateContextProperty(pContext,
                                         dwPropId,
                                         pbData,
                                         &cbData))
    {
        printf("CertGetCertificateContextProperty was started for the 2-nd time\n");
        printf( "ContainerName is  %S ProvType = %d\n", pbData->pwszContainerName, pbData->dwProvType);
    }
    else
    {
          printf("CertGetCertificateContextProperty was started for the 2-nd time\n");
          HandleError("It's impossible to get the certificate property!\n ");
    }

//--------------------------------------------------------------------------
// Освобождение контекста сертификата.
    if (pContext)
        CertFreeCertificateContext(pContext);

//--------------------------------------------------------------------------
// Закрытие хранилища сертификатов.

    if (CertCloseStore(hStore,
                       0))
    {
        printf("Store was closed successfully!\n");
        printf("\n");
    }
    else
    {
        printf("Attempt to close the store is failed\n");
        exit(1);
    }

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

    IXMLDSigKeyPtr pKey = xmldsig->createKeyFromCSP(pbData->dwProvType, pbData->pwszProvName, pbData->pwszContainerName, 0);

    if (pKey==NULL)
    {
        printf("Invalid key\n");
        return false;
    }

//----------------------------------------------------
// Подпись XML-документа на полученном ключе.

    IXMLDSigKeyPtr pKeyOut = xmldsig->sign(pKey, fwWriteKeyInfo);
    if (NULL == pKeyOut)
    {
        printf("sign failed.\n");
        return false;
    }

    printf("The specified data was signed successfully.\n");
    printf("Resultant signature:\n");

    printf((LPCSTR)xmldoc->xml);

//----------------------------------------------------
// Запись подписи в файл "out_signature.xml".
   hr = xmldoc->get_xml(&bstr);
   printf("\n");
   printf("out_signature.xml:\n%S\n", bstr);
   {
        FILE * f;
        if( (f = fopen("out_signature.xml","w")) == NULL)
            HandleError( "The file 'out_signature.xml' was not opened\n" );
        else
            printf( "The file 'out_signature.xml' was opened\n" );

        fprintf(f,"%S",bstr);

        if( fclose( f ) )
            HandleError( "The file 'out_signature.xml' was not closed\n" );

   }
   return true;
}// Конец описания SignXML

//-------------------------------------------------------------------------------
// Описание функции инициализации объектов.
//-------------------------------------------------------------------------------

VARIANT_BOOL initObjects()
{
   if (FAILED(xmldsig.CreateInstance(__uuidof(MXDigitalSignature50)) ))
   {
      printf("Installation of msxml5 is required to run this app.\n");
      return VARIANT_FALSE;
   }

   if (FAILED(xmldoc.CreateInstance(__uuidof(DOMDocument50)) )) {
      printf("Installation of msxml5 is required to run this app.\n");
      return VARIANT_FALSE;
   }
   xmldoc->async = VARIANT_FALSE;
   xmldoc->validateOnParse = VARIANT_FALSE;
   xmldoc->preserveWhiteSpace = VARIANT_TRUE;
   xmldoc->resolveExternals = VARIANT_FALSE;

   objectsAreInitialized = VARIANT_TRUE;

   return VARIANT_TRUE;
}// Конец описания initObjects

//------------------------------------------------------------------------------
// Описание функции очистки объектов.
//-------------------------------------------------------------------------------

void cleanObjects()
{
   if (xmldoc) xmldoc.Release();
   if (xmldsig) xmldsig.Release();
}// Конец описания cleanObjects

//------------------------------------------------------------------------------
// Подпись XML-документа на основе сертификата.
//------------------------------------------------------------------------------

void _tmain(int argc, TCHAR **argv)
{
//------------------------------------------------------------------------------
// Инициализация COM библиотеки.

   if ( CoInitialize(NULL) == E_FAIL)
   {
      printf("can't initialize COM Lib\n");
      exit(-1);
   }
//------------------------------------------------------------------------------
// Инициализация объектов.

   if (!initObjects())
   {
      cleanObjects();
      exit(-1);
   }
//------------------------------------------------------------------------------
// Разбор командной строки.

   if (argc < 2)
   {
        printf("Please, enter tne name of xml-file and certificate name!\n");
        exit(-1);
    }
   fileName = argv[1];
   userName = argv[2];

   printf("Verifying %S\n\n", fileName);
   if (VARIANT_TRUE == LoadXML((_bstr_t)fileName))
   {

//------------------------------------------------------------------------------
// Подпись XML-документа.
   printf("Sign with fwWriteKeyInfo = CERTIFICATES:\n");
   SignXML(CERTIFICATES);
   }

//------------------------------------------------------------------------------
// Очистка.
   cleanObjects();
   CoUninitialize();

}// Конец main

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше и MSXML 5.0.


Крипто-Про CSP

Данный пример демонстрирует проверку подписи XML-документа, а также проверку цепочки сертификатов, начиная с сертификата, на котором осуществлялась подпись.

//--------------------------------------------------------------------
// Пример проверки подписи документа MSXML 5.0 на ключе, получаемом из
// DOM узла <ds:KeyInfo> подписанного XML-документа.
// Также данная программа осуществляет проверку действительности цепочки
// сертификатов, начиная с сертификата, на котором осуществлялась подпись,
// и заканчивая корневым сертификатом.
// В качестве обязательного аргумента командной строки выступает
// "out_signature.xml" - имя XML-документа, полученного во время подписи.
// НЕОБХОДИМО установить CAPICOM (http://www.microsoft.com/downloads/details.aspx?FamilyID=860ee43a-a843-462f-abb5-ff88ea5896f6&DisplayLang=en)
//--------------------------------------------------------------------

#include <stdio.h>
#include <tchar.h>

#import <msxml5.dll>
using namespace MSXML2;

#import <capicom.dll>
using namespace CAPICOM;

#define DSIGNS "xmlns:ds='http://www.w3.org/2000/09/xmldsig#'"
#define PROV_GOST_2001_DH 75

//-------------------------------------------------------------
// Объявление и инициализация переменных.

IXMLDOMDocument3Ptr xmldoc = NULL;
IXMLDigitalSignaturePtr xmldsig = NULL;

VARIANT_BOOL objectsAreInitialized = VARIANT_FALSE;

TCHAR* fileName = NULL; // Имя подписанного XML-документа.

//---------------------------------------------------------------------------
// Описание функции загрузки XML-документа.
//---------------------------------------------------------------------------

VARIANT_BOOL LoadXML(_bstr_t sigFile)
{
   if (!objectsAreInitialized)
   {
      printf("Must initialize objects before loading signature.\n");
      return VARIANT_FALSE;
   }

   if (xmldoc->load(sigFile) == VARIANT_FALSE)
   {
      printf("Can't load %s\n", (LPCSTR)sigFile);
      return VARIANT_FALSE;
   }

   _bstr_t ns= DSIGNS;
   xmldoc->setProperty("SelectionNamespaces", ns);

//------------------------------------------------------------------------------
// Определение свойств подписи в соответствии с DOM узлом <ds:Signature>
// XML-документа.
   xmldsig->signature = xmldoc->selectSingleNode(".//ds:Signature");

   if (xmldsig->signature == NULL)
   {
      printf("Failed to set the signature property.\n");
      return VARIANT_FALSE;
   }

   return VARIANT_TRUE;

}// Конец описания функции LoadXML

//---------------------------------------------------------------------------
// Описание функции проверки цепочки сертификатов, начиная с сертификата, на
// котором осуществлялась подпись XML-документа.
//---------------------------------------------------------------------------

VARIANT_BOOL IsCertificateValid(IXMLDSigKeyPtr pKey)
{
   if (pKey == NULL)
   {
      printf("invalid key object.\n");
      return VARIANT_FALSE;
   }

//---------------------------------------------------------------------------
// Получение сертификата, на котором осуществлялась подпись, из ключа проверки.

   ICertificatePtr pCert=NULL;

   pCert = pKey->getVerifyingCertificate();
   if (pCert == NULL)
   {
      printf ("Can't get verifying certificate\n");
      return VARIANT_FALSE;
   }

//---------------------------------------------------------------------------
// Построение и прохождение по доверенной цепочке сертификатов.

   IChain2Ptr pChain = NULL;
   HRESULT hr = pChain.CreateInstance(__uuidof(Chain));
   if (FAILED(hr))
   {
      printf("Can't instantiate a trust chain.\n");
      return VARIANT_FALSE;
   }

   if (VARIANT_FALSE == pChain->Build(pCert))
   {
      printf("broken trust chain.\n");
      return VARIANT_FALSE;
   }

   printf("Examining certificate chain:\n");
   long count = pChain->Certificates->Count;
   for (long i=1; i<=count; i++)
   {
      printf("  Certificate No. %d:\n", i);
      if (pCert)
      {
         pCert.Release();
         pCert=NULL;
      }
      pCert = pChain->Certificates->Item[i];
      if (pCert == NULL)
      {
         printf("Can't get the %d-th certificate.\n",i);
         return VARIANT_FALSE;
      }
      printf("     subject: %s\n",(LPSTR)pCert->SubjectName);
      printf("     issuer:  %s\n\n",(LPSTR)pCert->IssuerName);
   }
//---------------------------------------------------------------------------
// Проверка корневого сертификата в цепочке.

   if (pCert)
   {
      pCert.Release();
      pCert=NULL;
   }

   pCert = pChain->Certificates->Item[count];
   if (pCert == NULL)
   {
      printf("Can't get root certificate.\n");
      return VARIANT_FALSE;
   }
   printf("Display the Root certificate:\n");
   printf("   subject:  %s\n",(LPSTR)pCert->SubjectName);
   printf("   issuer:   %s\n\n",(LPSTR)pCert->IssuerName);

   if (pCert) pCert.Release();
   if (pChain) pChain.Release();

   return VARIANT_TRUE;
}// Конец описания IsCertificateValid

//---------------------------------------------------------------------------
// Описание функции проверки подписи XML-документа.
//---------------------------------------------------------------------------

VARIANT_BOOL VerifyXML(XMLDSIG_WRITEKEYINFO fWriteKeyInfo)
{
    MSXML2::IXMLDOMNodePtr pKeyInfo, pNode;
    IXMLDSigKeyPtr pKey, pKeyOut;

    if (xmldsig->signature == NULL)
    {
      printf("Invalid signature.\n");
      return VARIANT_FALSE;
    }

//---------------------------------------------------------------------------
// Проверка DOM узла <ds:KeyInfo> XML-документа.

   switch (fWriteKeyInfo & CERTIFICATES)
   {
      case CERTIFICATES:
         pKeyInfo = xmldoc->selectSingleNode(
                  ".//ds:KeyInfo/ds:X509Data");
         break;
      case KEYVALUE:
         pKeyInfo = xmldoc->selectSingleNode(
                  ".//ds:KeyInfo/ds:KeyValue");
         break;
   }

   if (pKeyInfo == NULL)
   {
      printf("Invalid <ds:KeyInfo>\n");
      return VARIANT_FALSE;
   }

//---------------------------------------------------------------------------
// Получение ключа проверки подписи из DOM узла <ds:KeyInfo> XML-документа.

   pKey = xmldsig->createKeyFromNode(pKeyInfo);
   if (pKey== NULL)
   {
      printf("Invalid key from <ds:KeyInfo>\n");
      return VARIANT_FALSE;
   }
//---------------------------------------------------------------------------
// Получение ключа проверки цепочки сертификатов и проверка подписи.

   pKeyOut = xmldsig->verify(pKey);
   if (pKeyOut== NULL)
   {
      printf("Invalid signature.\n");
      return VARIANT_FALSE;
   }

   printf("Signature verified on the data.\n\n");

//---------------------------------------------------------------------------
// Проверка цепочки сертификатов, начиная с сертификата, на котором осуществлялась подпись.

   if ( (fWriteKeyInfo & CERTIFICATES) == CERTIFICATES)
   {
      if (IsCertificateValid(pKeyOut))
      {
         printf("Certificate used is valid.\n");
      }
   }

   return VARIANT_TRUE;
}// Конец описания VerifyXML

//-------------------------------------------------------------------------------
// Описание функции инициализации объектов.
//-------------------------------------------------------------------------------

VARIANT_BOOL initObjects()
{
   if (FAILED(xmldsig.CreateInstance(__uuidof(MXDigitalSignature50)) ))
   {
      printf("Installation of msxml5 is required to run this app.\n");
      return VARIANT_FALSE;
   }

   if (FAILED(xmldoc.CreateInstance(__uuidof(DOMDocument50)) ))
   {
      printf("Installation of msxml5 is required to run this app.\n");
      return VARIANT_FALSE;
   }
   xmldoc->async = VARIANT_FALSE;
   xmldoc->validateOnParse = VARIANT_FALSE;
   xmldoc->preserveWhiteSpace = VARIANT_TRUE;
   xmldoc->resolveExternals = VARIANT_FALSE;
   objectsAreInitialized = VARIANT_TRUE;

   return VARIANT_TRUE;
}// Конец описания initObjects

//------------------------------------------------------------------------------
// Описание функции очистки объектов.
//-------------------------------------------------------------------------------

void cleanObjects()
{
   if (xmldoc) xmldoc.Release();
   if (xmldsig) xmldsig.Release();
}// Конец описания cleanObjects

//------------------------------------------------------------------------------
// Проверка подписи XML-документа.
//------------------------------------------------------------------------------

void _tmain(int argc, TCHAR **argv)

{
//------------------------------------------------------------------------------
// Инициализация COM библиотеки.

    if ( CoInitialize(NULL) == E_FAIL)
    {
        printf("can't initialize COM Lib\n");
        exit(-1);
    }

//------------------------------------------------------------------------------
// Инициализация объектов.

    if (!initObjects())
    {
        cleanObjects();
        exit(-1);
    }

//------------------------------------------------------------------------------
// Разбор командной строки.

    if (argc < 1)
        {
            printf("Please, enter tne name of xml-file name!\n");
            exit(-1);
        }
    fileName = argv[1];

    printf("Verifying %s\n\n", fileName);

//------------------------------------------------------------------------------
// Проверка подписи XML-документа.
    if (VARIANT_TRUE == LoadXML(fileName))
    {
        VerifyXML(CERTIFICATES);
    }

//------------------------------------------------------------------------------
// Очистка.
    cleanObjects();
    CoUninitialize();

}// Конец main

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше и MSXML 5.0.


Крипто-Про CSP

В данном примере осуществляется создание и проверка двух независимых подписей XML-документа, а также осуществляется проверка цепочки сертификатов, начиная с сертификата, на котором осуществлялась подпись. Этот пример демонстрирует использование следующих функций

  • CertOpenStore в MS CryptoAPI 2.0 World Wide Web link
  • CertFindCertificateInStore в MS CryptoAPI 2.0 World Wide Web link
  • CertGetCertificateContextProperty в MS CryptoAPI 2.0 World Wide Web link
  • CertFreeCertificateContext в MS CryptoAPI 2.0 World Wide Web link
  • CertCloseStore в MS CryptoAPI 2.0 World Wide Web link

//--------------------------------------------------------------------
// Пример создания и проверки двух независимых подписей документа MSXML 5.0.
// Ключ подписи получается по имени ключевого контейнера. Имя контейнера, в свою очередь,
// получается из расширенных свойств заданного сертификата.
// Ключ проверки подписи получается из DOM узла <ds:KeyInfo> подписанного XML-документа.
// Имя подписанного XML-документа задается по умолчанию ("out_signature.xml").
// Данная программа имеет три аргумента командной строки:
// 1) Имя исходного XML-документа (документ должен соответствовать
// шаблону, приведенному в примере).
// 2) Имя сертификата для первой подписи.
// 3) Имя сертификата для второй подписи.
//--------------------------------------------------------------------

#include <windows.h>
#include <wincrypt.h>
#include <tchar.h>
#include "wincryptex.h"
#include <stdio.h>

#import <msxml5.dll>
using namespace MSXML2;

#import <capicom.dll>
using namespace CAPICOM;

#define DSIGNS "xmlns:ds='http://www.w3.org/2000/09/xmldsig#'"
#define OUTFILE "out_signatures.xml"

#undef CERT_FIND_SUBJECT_STR
#ifdef UNICODE
#define CERT_FIND_SUBJECT_STR  CERT_FIND_SUBJECT_STR_W
#else
#define CERT_FIND_SUBJECT_STR  CERT_FIND_SUBJECT_STR_A
#endif // !UNICODE
//-------------------------------------------------------------
// Объявление и инициализация переменных.

_bstr_t outfile;
IXMLDOMDocument3Ptr xmldoc = NULL;
IXMLDigitalSignaturePtr xmldsig = NULL;
VARIANT_BOOL objectsAreInitialized = VARIANT_FALSE;
void HandleError(char *s);
PCCERT_CONTEXT pContext = NULL ;
HCERTSTORE hStore = NULL;
HCRYPTPROV hProv = 0 ;
DWORD dwPropId = CERT_KEY_PROV_INFO_PROP_ID;
BYTE  *pbData;
DWORD cbData;
TCHAR* fileName = NULL; //имя xml-документа для подписи
TCHAR* userName = NULL; //имя сертификата, который используется для подписи
TCHAR* userName1 = NULL; //имя сертификата для первой подписи
TCHAR* userName2 = NULL; //имя сертификата для второй подписи
int COUNT; //счётчик
HRESULT hr; //переменная, которая используются для получения XML документа

//---------------------------------------------------------------------------
// Описание функции загрузки XML-документа.
//---------------------------------------------------------------------------

VARIANT_BOOL LoadXML(_bstr_t sigFile)
{
   if (!objectsAreInitialized) {
      printf("Must initialize objects before loading signature.\n");
      return VARIANT_FALSE;
   }

   xmldoc->setProperty("SelectionNamespaces", DSIGNS);

   if( COUNT == 1 )
   {
        if (xmldoc->load(sigFile) == VARIANT_FALSE)
        {
          printf("Can't load %s\n", (LPCSTR)sigFile);
          return VARIANT_FALSE;
        }

//------------------------------------------------------------------------------
// Определение свойств первой подписи в соответствии с DOM узлом <ds:Signature>
// XML-документа.
   xmldsig->signature = xmldoc->selectSingleNode(".//ds:Signature[@Id='FirstSignature']");

    }
    else if( COUNT == 2 )
    {
//------------------------------------------------------------------------------
// Определение свойств второй подписи в соответствии с DOM узлом <ds:Signature>
// XML-документа.
        xmldsig->signature = xmldoc->selectSingleNode(".//ds:Signature[@Id='SecondSignature']");
    }
    else
          printf("COUNT !=1 and COUNT!=2, COUNT is %d\n", COUNT);

 if (xmldsig->signature == NULL)
 {
      printf("Failed to set the signature property.\n");
      return VARIANT_FALSE;
 }

   return VARIANT_TRUE;

}// Конец описания функции LoadXML

//---------------------------------------------------------------------------
// Описание функции подписи XML-документа.
//---------------------------------------------------------------------------

VARIANT_BOOL SignXML(XMLDSIG_WRITEKEYINFO fwWriteKeyInfo)
{
    if (xmldsig->signature == NULL)
    {
      printf("Invalid signature template\n");
      return false;
    }

//------------------------------------------------------------------------------
// Открытие хранилища сертификатов "MY" текущего пользователя.

    hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM,
                            0,
                            0,
                                CERT_STORE_OPEN_EXISTING_FLAG|CERT_STORE_READONLY_FLAG|
                            CERT_SYSTEM_STORE_CURRENT_USER,
                            _TEXT("MY"));
  if (!hStore)
   {
        HandleError("The store could not be opened!\n");
   }
  else
  {
        printf("The store is open!\n");
  }
//-----------------------------------------------------------------
// Определение сертификата, используемого для подписи в данный момент

  if( COUNT == 1)
  {
         userName = userName1;
  }
  else if( COUNT == 2 )
  {
         userName = userName2;
  }
  else
          printf("COUNT !=1 and COUNT!=2, COUNT is %d\n", COUNT);

//-----------------------------------------------------------------
// Получение сертификата с заданным именем из хранилища сертификатов.
  pContext = CertFindCertificateInStore( hStore,
                                         X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
                                         0,
                                         CERT_FIND_SUBJECT_STR,
                                         userName,
                                         NULL);
        if(pContext == NULL)
        {
            HandleError("There is no such a certificate in the store\n");
        }

//--------------------------------------------------------------------------
// Указатель на структуру CRYPT_KEY_PROV_INFO, содержащую подробную информацию
// о ключевом контейнере.
CRYPT_KEY_PROV_INFO *pbData;

//--------------------------------------------------------------------------
// Получение информации из расширенных свойств контекста сертификата. Определение размера
// возвращаемых данных.

  if(CertGetCertificateContextProperty( pContext,
                                        dwPropId,
                                        NULL,
                                        &cbData))
  {
          printf("CertGetCertificateContextProperty was started for the 1-st time\n");
  }
  else
  {
          printf("CertGetCertificateContextProperty was started for the 1-st time\n");
          HandleError("It's impossible to get the certificate property!\n ");
  }

//-------------------------------------------------------------------------
// Выделение памяти.

  pbData = (CRYPT_KEY_PROV_INFO*)malloc(cbData);
  if(pbData)
  {
        printf("Memory has been allocated.\n");
  }
  else
  {
        HandleError("Malloc operation failed. ");
  }
//------------------------------------------------------------------------
// Получение подробной информации о ключевом контейнере из расширенных свойств
// контекста сертификата.

    if(CertGetCertificateContextProperty( pContext,
                                        dwPropId,
                                        pbData,
                                        &cbData))
    {
        printf("CertGetCertificateContextProperty was started for the 2-nd time\n");
        printf( "ContainerName is  %S\n", pbData->pwszContainerName);
    }
    else
    {
          printf("CertGetCertificateContextProperty was started for the 2-nd time\n");
          HandleError("It's impossible to get the certificate property!\n ");
    }

//--------------------------------------------------------------------------
// Освобождение контекста сертификата.

  if (pContext)
        CertFreeCertificateContext(pContext);

//--------------------------------------------------------------------------
// Закрытие хранилища сертификатов.

  if (CertCloseStore( hStore,
                      0))
  {
        printf("Store was closed successfully!\n");
        printf("\n");
  }
  else
  {
        printf("Attempt to close the store is failed\n");
        exit(1);
  }

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

    IXMLDSigKeyPtr pKey = xmldsig->createKeyFromCSP(pbData->dwProvType, pbData->pwszProvName, pbData->pwszContainerName, 0);

   if (pKey==NULL)
   {
      printf("Invalid key\n");
      return false;
   }

//----------------------------------------------------
// Подпись XML-документа на полученном ключе.

   IXMLDSigKeyPtr pKeyOut = xmldsig->sign(pKey, fwWriteKeyInfo);
   if (NULL == pKeyOut)
   {
      printf("sign failed.\n");
      return false;
   }
   printf("The specified data was signed successfully.\n");
   printf("Resultant signature:\n");

   printf((LPCSTR)xmldoc->xml);
   printf("\n");

//----------------------------------------------------
// Запись подписи в файл outfile.

   hr = xmldoc->save(outfile);
   if (FAILED(hr)) {
      printf("can't save the signed signature file.\n");
      return false;
   }

 //-----------------------------------------------------------------------
   return true;
}// Конец описания SignXML

//---------------------------------------------------------------------------
// Описание функции проверки цепочки сертификатов, начиная с сертификата, на
// котором осуществлялась подпись XML-документа.
//---------------------------------------------------------------------------
VARIANT_BOOL IsCertificateValid(IXMLDSigKeyPtr pKey)
{
   if (pKey == NULL)
   {
      printf("invalid key object.\n");
      return VARIANT_FALSE;
   }

//---------------------------------------------------------------------------
// Получение сертификата, на котором осуществлялась подпись, из ключа проверки.

   ICertificatePtr pCert=NULL;
   pCert = pKey->getVerifyingCertificate();
   if (pCert == NULL)
   {
      printf ("Can't get verifying certificate\n");
      return VARIANT_FALSE;
   }

 //---------------------------------------------------------------------------
// Построение и прохождение по доверенной цепочке сертификатов.

   IChain2Ptr pChain = NULL;
   HRESULT hr = pChain.CreateInstance(__uuidof(Chain));
   if (FAILED(hr))
   {
      printf("Can't instantiate a trust chain.\n");
      return VARIANT_FALSE;
   }

   if (VARIANT_FALSE == pChain->Build(pCert))
   {
      printf("broken trust chain.\n");
      return VARIANT_FALSE;
   }

   printf("Examining certificate chain:\n");
   long count = pChain->Certificates->Count;
   for (long i=1; i<=count; i++)
   {
      printf("  Certificate No. %d:\n", i);
      if (pCert)
      {
         pCert.Release();
         pCert=NULL;
      }
      pCert = pChain->Certificates->Item[i];
      if (pCert == NULL)
      {
         printf("Can't get the %d-th certificate.\n",i);
         return VARIANT_FALSE;
      }
      printf("     subject: %s\n",(LPSTR)pCert->SubjectName);
      printf("     issuer:  %s\n\n",(LPSTR)pCert->IssuerName);
   }

//---------------------------------------------------------------------------
// Проверка корневого сертификата в цепочке.

   if (pCert)
   {
      pCert.Release();
      pCert=NULL;
   }

   pCert = pChain->Certificates->Item[count];
   if (pCert == NULL)
   {
      printf("Can't get root certificate.\n");
      return VARIANT_FALSE;
   }
   printf("Display the Root certificate:\n");
   printf("   subject:  %s\n",(LPSTR)pCert->SubjectName);
   printf("   issuer:   %s\n\n",(LPSTR)pCert->IssuerName);

   if (pCert) pCert.Release();
   if (pChain) pChain.Release();

   return VARIANT_TRUE;
}// Конец описания IsCertificateValid

//---------------------------------------------------------------------------
// Описание функции проверки подписи XML-документа.
//---------------------------------------------------------------------------

VARIANT_BOOL VerifyXML(XMLDSIG_WRITEKEYINFO fWriteKeyInfo)
{
   MSXML2::IXMLDOMNodePtr pKeyInfo, pNode;
   IXMLDSigKeyPtr pKey, pKeyOut;

   if (xmldsig->signature == NULL)
   {
      printf("Invalid signature.\n");
      return VARIANT_FALSE;
   }

//---------------------------------------------------------------------------
// Проверка DOM узла <ds:KeyInfo> XML-документа.

   if(COUNT==1) // для первой подписи
                  {
            pKeyInfo = xmldoc->selectSingleNode(
              ".//ds:Signature[@Id='FirstSignature']/ds:KeyInfo/ds:X509Data");
                  }
   else if( COUNT == 2 ) // для второй подписи
                  {
                          pKeyInfo = xmldoc->selectSingleNode(
               ".//ds:Signature[@Id='SecondSignature']/ds:KeyInfo/ds:X509Data");
                  }
   else
           printf("COUNT !=1 and COUNT!=2, COUNT is %d\n", COUNT);

   if (pKeyInfo == NULL)
   {
      printf("Invalid <ds:KeyInfo>\n");
      return VARIANT_FALSE;
   }

//---------------------------------------------------------------------------
// Получение ключа проверки подписи из DOM узла <ds:KeyInfo> XML-документа.

   pKey = xmldsig->createKeyFromNode(pKeyInfo);
   if (pKey== NULL)
   {
      printf("Invalid key from <ds:KeyInfo>\n");
      return VARIANT_FALSE;
   }

//---------------------------------------------------------------------------
// Получение ключа проверки цепочки сертификатов и проверка подписи.

   pKeyOut = xmldsig->verify(pKey);
   if (pKeyOut== NULL) {
      printf("Invalid signature.\n");
      return VARIANT_FALSE;
   }

   printf("\n");
   printf("Signature verified on the data.\n\n");

//---------------------------------------------------------------------------
// Проверка цепочки сертификатов, начиная с сертификата, на котором осуществлялась подпись.

   if (fWriteKeyInfo == CERTIFICATES)
   {
      if (IsCertificateValid(pKeyOut))
          {
         printf("Certificate used is valid.\n");
      }
   }

   return VARIANT_TRUE;
}// Конец описания VerifyXML

//-------------------------------------------------------------------------------
// Описание функции инициализации объектов.
//-------------------------------------------------------------------------------

VARIANT_BOOL initObjects()
{
   if (FAILED(xmldsig.CreateInstance(__uuidof(MXDigitalSignature50)) ))
   {
      printf("Installation of msxml5 is required to run this app.\n");
      return VARIANT_FALSE;
   }

   if (FAILED(xmldoc.CreateInstance(__uuidof(DOMDocument50)) ))
   {
      printf("Installation of msxml5 is required to run this app.\n");
      return VARIANT_FALSE;
   }
   xmldoc->async = VARIANT_FALSE;
   xmldoc->validateOnParse = VARIANT_FALSE;
   xmldoc->preserveWhiteSpace = VARIANT_TRUE;
   xmldoc->resolveExternals = VARIANT_FALSE;

   objectsAreInitialized = VARIANT_TRUE;

   return VARIANT_TRUE;
}// Конец описания initObjects

//------------------------------------------------------------------------------
// Описание функции очистки объектов.
//-------------------------------------------------------------------------------

void cleanObjects()
{
   if (xmldoc) xmldoc.Release();
   if (xmldsig) xmldsig.Release();
}// Конец описания cleanObjects

//------------------------------------------------------------------------------
// Создание и проверка двух независимых подписей XML-документа.
//------------------------------------------------------------------------------

void _tmain(int argc, TCHAR **argv)
{
//------------------------------------------------------------------------------
// Инициализация COM библиотеки.

    if ( CoInitialize(NULL) == E_FAIL)
   {
      printf("can't initialize COM Lib\n");
      exit(-1);
   }

//------------------------------------------------------------------------------
// Инициализация объектов.

   if (!initObjects())
   {
      cleanObjects();
      exit(-1);
   }

//------------------------------------------------------------------------------
// Разбор командной строки.

   if (argc < 4)
        {
                printf("Please, enter tne name of xml-file and two certificate's names!\n");
                exit(-1);
        }
   fileName = argv[1];
   userName1 = argv[2];
   userName2 = argv[3];

   printf("Verifying %S\n\n", fileName);
   outfile = OUTFILE;
   COUNT=1;

//------------------------------------------------------------------------------
// Создание двух независимых подписей XML-документа.
   for(int i=0;i<2;i++)
   {
       if (VARIANT_TRUE == LoadXML((_bstr_t)fileName))
          {
             printf("\n");
             printf("Sign with fwWriteKeyInfo = CERTIFICATES:\n");
             SignXML(CERTIFICATES);
                 COUNT++;
           }
   }

   COUNT=1;
//------------------------------------------------------------------------------
// Проверка двух независимых подписей XML-документа.
   for(i=0;i<2;i++)
   {
       if (VARIANT_TRUE == LoadXML(outfile))
        {
                        printf("\n");
                        printf("Verify with fwWriteKeyInfo = CERTIFICATES:\n");
            VerifyXML(CERTIFICATES);
                        COUNT++;
        }
   }

//------------------------------------------------------------------------------
// Очистка.

   cleanObjects();
   CoUninitialize();

}// Конец main

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше и MSXML 5.0.


Примеры использования криптопровайдера совместно с функциями CAPICOM.

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

  • Пример подписи и проверки подписи при помощи CAPICOM
  • Пример зашифрования и расшифрования при помощи CAPICOM


Крипто-Про CSP

Данный пример демонстрирует осуществление подписи и проверки подписи текстового документа при помощи инструментария CAPICOM.

'-----------------------------------------------------------------------------
'
' В данном script-примере осуществляется подпись и проверка подписи
' содержимого файла при помощи инструментария CAPICOM.
'
'******************************************************************************

Option Explicit

Const ForReading = 1, ForWriting = 2

' Команды.
Const Unknown                                               = 0
Const Sign                                                           = 1
Const CoSign                                                = 2
Const Verify                                                = 3

' CAPICOM константы.
Const CAPICOM_CURRENT_USER_STORE                            = 2

Const CAPICOM_CERTIFICATE_FIND_EXTENDED_PROPERTY            = 6
Const CAPICOM_CERTIFICATE_FIND_TIME_VALID                   = 9

Const CAPICOM_VERIFY_SIGNATURE_ONLY                         = 0

Const CAPICOM_CERTIFICATE_INCLUDE_CHAIN_EXCEPT_ROOT         = 0

Const CAPICOM_PROPID_KEY_PROV_INFO                          = 2

' Аргументы командной строки.
Dim Command          : Command                              = Unknown
Dim StoreLocation    : StoreLocation                        = Null
Dim VerifyFlag       : VerifyFlag                           = CAPICOM_VERIFY_SIGNATURE_ONLY
Dim IncludeOption    : IncludeOption                        = CAPICOM_CERTIFICATE_INCLUDE_CHAIN_EXCEPT_ROOT
Dim bDetached        : bDetached                            = False

' Фильтр.
Dim FileNames()

' В первую очередь осуществляется проверка того, что script выполняется при помощи CScript.exe.
If InStr(1, UCase(Wscript.FullName), "CSCRIPT.EXE", vbTextCompare) = 0 Then
   Wscript.Echo "This script can only be executed by CScript.exe." & vbCRLF & vbCRLF &_
                "You can either:" & vbCRLF & vbCRLF & _
                "1. Set CScript.exe as the default (Run CScript //h:cscript), or" & vbCRLF & _
                "2. Run CScript.exe directly as in, CScript " & Wscript.ScriptName & "."
   Wscript.Quit(-1)
End If

' Разбор командной сроки.
ParseCommandLine

' Поиск сертификата, на котором будет осуществляться операция подписи.
Dim Signer
Set Signer = CreateObject("CAPICOM.Signer")

' Определение свойств операции подписи.
If Command = Sign OR Command = CoSign Then
      Dim iIndex
      Dim Store
      Dim Certificates
      Dim StoreName : StoreName = "MY"

      ' Открытие соответствующего хранилища.
      Set Store = CreateObject("CAPICOM.Store")

      StoreLocation = CAPICOM_CURRENT_USER_STORE

      Store.Open StoreLocation, StoreName

      ' В качестве кандитатов на сертификат, на котором будет осуществлена подпись,
      ' изначально определяются все сертификаты хранилища.
      Set Certificates = Store.Certificates

      ' Из них не рассматриваются сертификаты, в которых отсутствует закрытый ключ.
      If Certificates.Count > 0 Then
         Set Certificates = Certificates.Find(CAPICOM_CERTIFICATE_FIND_EXTENDED_PROPERTY, CAPICOM_PROPID_KEY_PROV_INFO)
      End If

      ' Из них выбираются только сертификаты, действительные в настоящее время.
      If Certificates.Count > 0 Then
         Set Certificates = Certificates.Find(CAPICOM_CERTIFICATE_FIND_TIME_VALID, Now)
      End If

      ' Выбор сертификата для подписи. Если после проведенной фильтрации осталось несколько кандидатов,
      ' то пользователю предоставляется выбор одного из них (при помощи диалогового окна).
      Select Case Certificates.Count
      Case 0
         Wscript.Stdout.Writeline "Error: No signing certificate can be found."
         Wscript.Quit(1)

      Case 1
         Signer.Certificate = Certificates(1)

      Case Else
         Set Certificates = Certificates.Select("CSignData.vbs", "Please select a certificate to sign " & FileNames(0) & ".")
         If Certificates.Count = 0 Then
            Wscript.Stdout.Writeline "Error: Certificate selection dialog was cancelled."
            Wscript.Quit(2)
         End If
         Signer.Certificate = Certificates(1)

      End Select

      Set Certificates = Nothing
      Set Store = Nothing

   Signer.Options = IncludeOption

   End If

' Выполнение требуемой операции.
Select Case Command
Case Sign
   DoSignCommand FileNames, bDetached, Signer

Case CoSign
   DoCoSignCommand FileNames, bDetached, Signer

Case Verify
   DoVerifyCommand FileNames, bDetached, VerifyFlag

End Select

' Освобождение ресурсов.
Set Signer = Nothing

Wscript.Quit(0)

' Конец main

'******************************************************************************
' Функиция DoSignCommand  подписывает содержимое файла FileNames(0)
' и записывает подписанные данные в FileNames(1).
'******************************************************************************

Sub DoSignCommand (FileNames, bDetached, Signer)
   Dim Content
   Dim Message
   Dim SignedData

   ' Создание объекта SignedData.
   Set SignedData = CreateObject("CAPICOM.SignedData")

   ' Распечатка информативного сообщения.
   Wscript.Stdout.Writeline "Signing text file " & FileNames(0) & "."
   Wscript.Stdout.Writeline

   ' Загрузка содержимого файла для подписи.
   LoadFile FileNames(0), Content

   ' Подпись.
   SignedData.Content = Content
   Message = SignedData.Sign(Signer, bDetached)

   ' Сохранение подписанных данных в FileNames(1).
   SaveFile FileNames(1), Message
   Wscript.Stdout.Writeline "Successful - Signed message saved to " & FileNames(1) & "."

   ' Освобождение ресурсов.
   Set SignedData = Nothing

End Sub 'Конец DoSignCommand

'******************************************************************************
' Функция DoCoSignCommand подписывает текстовый файл FileNames(0)и сохраняет
' заново подписанное содержимое в FileNames(1).
'******************************************************************************

Sub DoCoSignCommand (FileNames, bDetached, Signer)
   Dim Content
   Dim Message
   Dim SignedData

   ' Создание объекта SignedData.
   Set SignedData = CreateObject("CAPICOM.SignedData")

   ' Распечатка информативного сообщения.
   Wscript.Stdout.Writeline "CoSigning text file " & FileNames(0) & "."
   Wscript.Stdout.Writeline

   ' Загрузка подписанных данных.
   LoadFile FileNames(0), Message

   ' Проверка подписанных данных.
   SignedData.Verify Message, bDetached, VerifyFlag

   ' Повторная подпись.
   Message = SignedData.CoSign(Signer, bDetached)

   ' Сохранение внось подписанных данных в FileNames(0).
      SaveFile FileNames(0), Message
      Wscript.Stdout.Writeline "Successful - CoSigned message saved to " & FileNames(0) & "."

   ' Освобождение ресурсов.
   Set SignedData = Nothing

End Sub ' Конец DoCoSignCommand

'******************************************************************************
' Функция DoVerifyCommand проверяется подписанный текстовый файл.
'******************************************************************************

Sub DoVerifyCommand (FileNames, bDetached, VerifyFlag)
   Dim Content
   Dim Message
   Dim SignedData

   ' Создание объекта SignedData.
   Set SignedData = CreateObject("CAPICOM.SignedData")

   ' Распечатка информативного сообщения.
   Wscript.Stdout.Writeline "Verifying signed text file " & FileNames(0) & ", please wait..."
   Wscript.Stdout.Writeline

   ' Загрузка подписанных данных для проверки.
   LoadFile FileNames(0), Message

   ' Проверка подписи.
   SignedData.Verify Message, bDetached, VerifyFlag

   ' Сохранение проверенного содержимого в FileNames(1).
      SaveFile FileNames(1), SignedData.Content
      Wscript.Stdout.Writeline "Successful - Verified content saved to " & FileNames(1) & "."

   ' Освобождение ресурсов.
   Set SignedData = Nothing

End Sub ' Конец DoVerifyCommand

'******************************************************************************
'Функция LoadFile читает содержимое текстового файла.
'******************************************************************************

Sub LoadFile (FileName, Buffer)
    Dim fso
    Set fso = CreateObject("Scripting.FileSystemObject")

    If Not fso.FileExists(FileName) Then
        Wscript.Stdout.Writeline "Error: File " & FileName & " not found."
        Wscript.Quit(-5)
    End If

    Dim ts
    Set ts = fso.OpenTextFile(FileName, ForReading)
    Buffer = ts.ReadAll

End Sub ' Конец LoadFile

'******************************************************************************
' Функция SaveFile сохраняет строку в файл.
'******************************************************************************

Sub SaveFile (FileName, Buffer)
    Dim fso
    Set fso = CreateObject("Scripting.FileSystemObject")

    Dim ts
    Set ts = fso.OpenTextFile(FileName, ForWriting, True)
    ts.Write Buffer

End Sub ' Конец SaveFile

'******************************************************************************
' Функция ParseCommandLine разбирает командную строку и устанавливает
' опции согласно ей.
'******************************************************************************

Sub ParseCommandLine

   ' Константы для разбора состояний, задаваемых командной строкой.
   Const ARG_STATE_COMMAND                   = 0
   Const ARG_STATE_OPTIONS                   = 1
   Const ARG_STATE_FILENAME                  = 13

   ' Разбор командной строки.
   Dim Arg
   Dim ArgState : ArgState = ARG_STATE_COMMAND

   For Each Arg In Wscript.Arguments
      Select Case ArgState
      Case ARG_STATE_COMMAND
         Select Case UCase(Arg)
         Case "SIGN"
            Command = Sign

         Case "COSIGN"
            Command = CoSign

         Case "VERIFY"
            Command = Verify

         Case Else
            DisplayUsage

         End Select

         ArgState = ARG_STATE_OPTIONS

      Case ARG_STATE_OPTIONS
         Select Case UCase(Arg)
         Case "-?", "/?"
            DisplayUsage

         Case Else
            If Left(Arg, 1) = "-"  OR Left(Arg, 1) = "/" Then
               DisplayUsage
            Else
               ReDim FileNames(0)
               FileNames(0) = Arg
            End If
            ArgState = ARG_STATE_FILENAME

         End Select

      Case ARG_STATE_FILENAME
         If Left(Arg, 1) = "-"  OR Left(Arg, 1) = "/" Then
            DisplayUsage
         Else
            ReDim Preserve FileNames(UBound(FileNames) + 1)
         End If
         FileNames(UBound(FileNames)) = Arg

      Case Else
         Wscript.Stdout.Writeline "Internal script error: Unknown argument state (" & CStr(ArgState) & ") encountered."
         Wscript.Quit(-3)

      End Select
   Next

   ' Проверка правильности состояния.
   If ArgState <> ARG_STATE_FILENAME Then
      DisplayUsage
   End If

   ' Проверка опций.
   Select Case Command
   Case Sign
      ' Функция подписи должна иметь входной и выходной файлы.
      If (UBound(FileNames) - LBound(FileNames) + 1) <> 2 Then
         DisplayUsage
      End If

   Case Verify
      ' Функция проверки подписи должна иметь входной и выходной файлы.
      If (UBound(FileNames) - LBound(FileNames) + 1) <> 2 Then
         DisplayUsage
      End If

   End Select

End Sub ' Конец ParseCommandLine

'******************************************************************************
' Функция DisplayUsage распечатывает информацию об использовании данного
' примера, и затем осуществляет выход с ошибкой.
'******************************************************************************

Sub DisplayUsage

   Select Case Command
      Case Unknown
         Wscript.Stdout.Writeline "Usage: CSignData Command File1 [File2]"
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "Command:"
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "  Sign                   -- Sign a text file"
         Wscript.Stdout.Writeline "  CoSign                 -- CoSign a signed text file"
         Wscript.Stdout.Writeline "  Verify                 -- Verify a signed text file"
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "For help on a specific command, enter ""CSignData Command -?"""

      Case Sign
         Wscript.Stdout.Writeline "Usage: CSignData Sign ContentFile SignedFile"
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "The Sign command is used to sign a text file. Signing protects a file from"
         Wscript.Stdout.Writeline "tampering, and allows user to verify the signer based on signing certificate."
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "For non-detached signing, both the content and signature will be saved to"
         Wscript.Stdout.Writeline "SignedFile. For detached signing, only the signature is saved to SignedFile."
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "Parameters:"
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "  -?                     -- This help screen"
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "  ContentFile            -- Text file to be signed"
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "  SignedFile             -- Signed file (contains signature only if detached)"
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "Note: All non-fatal invalid options for this specific command will be ignored,"
         Wscript.Stdout.Writeline "      and the ** symbol indicates option can be listed multiple times."
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "      If there is only one certificate found in the MY store or PFX that"
         Wscript.Stdout.Writeline "      matches the requirement, that particular certificate will be used."
                   Wscript.Stdout.Writeline "      However, if there is more than one certificate matching the requirement,"
         Wscript.Stdout.Writeline "      a dialog will be displayed to allow selection of the signing certificate."
         Wscript.Stdout.Writeline

      Case CoSign
         Wscript.Stdout.Writeline "Usage: CSignData CoSign SignedFile [ContentFile]"
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "The CoSign command is used to cosign a signed text file. CoSigning provides the"
         Wscript.Stdout.Writeline "same type of benefits as signing, with an additional signature."
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "For non-detached cosigning, both the content and signatures will be saved to"
         Wscript.Stdout.Writeline "SignedFile. For detached cosigning, only the signatures are saved to"
         Wscript.Stdout.Writeline "SignedFile."
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "Parameters:"
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "  -?                     -- This help screen"
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "  SignedFile             -- Signed file (contains signature only if detached)"
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "  ContentFile            -- Text file (required if detached)"
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "Note: All non-fatal invalid options for this specific command will be ignored,"
         Wscript.Stdout.Writeline "      and the ** symbol indicates option can be listed multiple times."
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "      If there is only one certificate found in the MY store or PFX that"
         Wscript.Stdout.Writeline "      matches the requirement, that particular certificate will be used."
                   Wscript.Stdout.Writeline "      However, if there is more than one certificate matching the requirement,"
         Wscript.Stdout.Writeline "      a dialog will be displayed to allow selection of the signing certificate."
         Wscript.Stdout.Writeline

       Case Verify
         Wscript.Stdout.Writeline "Usage: CSignData Verify SignedFile ContentFile"
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "The Verify command is used to verify signed text file. Verification checks"
         Wscript.Stdout.Writeline "integrity of the signed file and determines if the signing certificate is"
         Wscript.Stdout.Writeline "valid and issued by a trusted party."
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "For non-detached signed file, the content will be extracted and saved to"
         Wscript.Stdout.Writeline "ContentFile. For detached signed file, the ContentFile is not modified."
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "Parameters:"
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "  -?                     -- This help screen"
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "  SignedFile             -- Signed file (contains signature only if detached)"
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "  ContentFile            -- Text file (will not be over written if detached)"
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "Note: All non-fatal invalid options for this specific command will be ignored."
         Wscript.Stdout.Writeline

      Case Else
         Wscript.Stdout.Writeline "Internal script error: Unknown help state (Command = " & CStr(Command) & ")."
         Wscript.Quit(-2)

   End Select

   Wscript.Quit(-1)

End Sub ' Конец DisplayUsage

Требования:

Windows 2000/XP/2003: Отдельный пакет распотраняемый Microsoft для Windows 2000, XP, 2003.


Крипто-Про CSP

Данный пример демонстрирует зашифрование и расшифрование текстового документа при помощи инструментария CAPICOM.

'-----------------------------------------------------------------------------
'
' В данном script-примере осуществляется зашифрование и расшифрование
' содержимого файла при помощи инструментария CAPICOM.
'
'******************************************************************************

Option Explicit

Const ForReading = 1, ForWriting = 2

' Команды.
Const Unknown                                      = 0
Const Encrypt                                      = 1
Const Decrypt                                      = 2

' CAPICOM константы.
Const CAPICOM_CURRENT_USER_STORE                   = 2

Const CAPICOM_CERTIFICATE_FIND_TIME_VALID          = 9

Const CAPICOM_ENCRYPTION_ALGORITHM_RC2             = 0

Const CAPICOM_ENCRYPTION_KEY_LENGTH_MAXIMUM        = 0

' Аргументы командной строки.
Dim Command       : Command        = Unknown
Dim StoreLocation : StoreLocation  = CAPICOM_CURRENT_USER_STORE
Dim StoreName     : StoreName      = "MY"
Dim CertFile      : CertFile       = Null
Dim Algorithm     : Algorithm      = Null 'CAPICOM_ENCRYPTION_ALGORITHM_RC2 - в CryptoPro CSP не поддерживается
Dim KeyLength     : KeyLength      = Null 'CAPICOM_ENCRYPTION_KEY_LENGTH_MAXIMUM - в CryptoPro CSP не поддерживается
Dim FileNames()

' В первую очередь осуществляется проверка того, что script выполняется при помощи CScript.exe.
If InStr(1, UCase(Wscript.FullName), "CSCRIPT.EXE", vbTextCompare) = 0 Then
   Wscript.Echo "This script can only be executed by CScript.exe." & vbCRLF & vbCRLF &_
                "You can either:" & vbCRLF & vbCRLF & _
                "1. Set CScript.exe as the default (Run CScript //h:cscript), or" & vbCRLF & _
                "2. Run CScript.exe directly as in, CScript " & Wscript.ScriptName & "."
   Wscript.Quit(-1)
End If

' Разбор командной сроки.
ParseCommandLine

' Поиск сертификата (сертификатов) получателя.
Dim Certificates
If Command = Encrypt Then

   ' Открытие хранилища сертификатов.
   Dim Store
   Set Store = CreateObject("CAPICOM.Store")
   Store.Open StoreLocation, StoreName

  ' В качестве кандитатов на сертификаты получателя
  ' изначально определяются все сертификаты хранилища.
   Set Certificates = Store.Certificates

   ' Из них выбираются только сертификаты, действительные в настоящее время.
   If Certificates.Count > 0 Then
      Set Certificates = Certificates.Find(CAPICOM_CERTIFICATE_FIND_TIME_VALID, Now)
   End If

   ' Выбор сертификата (сертификатов). Если после проведенной фильтрации осталось несколько кандидатов,
   ' то пользователю предоставляется выбор одного из них или нескольких (при помощи диалогового окна).
   Select Case Certificates.Count
   Case 0
      Wscript.Stdout.Writeline "Error: No recipient's certificate can be found."
      Wscript.Quit(1)

   Case 1
      ' Остался только один, потому он и будет использоваться.

   Case Else
      ' Пользователь выбирает сертификат (сертификаты) получателя.
      Set Certificates = Certificates.Select("CEnvelop.vbs", "Please select one or more recipient's certificate(s).", True)
      If Certificates.Count = 0 Then
         Wscript.Stdout.Writeline "Error: Certificate selection dialog was cancelled."
         Wscript.Quit(2)
      End If

   End Select

   ' Освобождение ресурсов.
   Set Store = Nothing
End If

' Выполнение требуемой операции.
Select Case Command
Case Encrypt
   DoEncryptCommand FileNames, Certificates, Algorithm, KeyLength

Case Decrypt
   DoDecryptCommand FileNames

End Select

' Освобождение ресурсов.
Set Certificates = Nothing

Wscript.Quit(0)

' Конец Main

'******************************************************************************
' Функиция DoSignCommand  зашифровывает содержимое файла FileNames(0)
' и записывает зашифрованные данные в FileNames(1).
'******************************************************************************

Sub DoEncryptCommand (FileNames, Certificates, Algorithm, KeyLength)
   Dim Content
   Dim Message
   Dim EnvelopedData

   ' Создание объекта EnvelopedData.
   Set EnvelopedData = CreateObject("CAPICOM.EnvelopedData")

   ' Определение алгоритма и размера ключа зашифрования.
   'EnvelopedData.Algorithm.Name = Algorithm - в CryptoPro CSP не поддерживается
   'EnvelopedData.Algorithm.KeyLength = KeyLength - - в CryptoPro CSP не поддерживается

   ' Добавление получателей.
   Dim Recipient
   For Each Recipient In Certificates
      EnvelopedData.Recipients.Add Recipient
   Next

   ' Распечатка информативного сообщения.
   Wscript.Stdout.Writeline "Enveloping text file " & FileNames(0) & "."
   Wscript.Stdout.Writeline

   ' Загрузка содержимого текстового файла для зашифрования.
   LoadFile FileNames(0), Content

   ' Зашифрование.
   EnvelopedData.Content = Content
   Message = EnvelopedData.Encrypt

   ' Сохранение зашифрованных данных в FileNames(1).
   SaveFile FileNames(1), Message
   Wscript.Stdout.Writeline "Successful - Enveloped message saved to " & FileNames(1) & "."

   ' Освобождение ресурсов.
   Set EnvelopedData = Nothing

End Sub ' Конец DoEncryptCommand

'******************************************************************************
' Функция DoCoSignCommand расшифровывает зашифрованный файл FileNames(0)и сохраняет
' расшифрвоанные данные в FileNames(1).
'******************************************************************************

Sub DoDecryptCommand (FileNames)
   Dim Message
   Dim EnvelopedData

   ' Создание объекта EnvelopedData.
   Set EnvelopedData = CreateObject("CAPICOM.EnvelopedData")

   ' Распечатка информативного сообщения.
   Wscript.Stdout.Writeline "Decrypting enveloped text file " & FileNames(0) & "."
   Wscript.Stdout.Writeline

   ' Загрузка зашифрованных данных.
   LoadFile FileNames(0), Message

   ' Расшифрование.
   EnvelopedData.Decrypt(Message)

   ' Сохранение расшифрованных данных в FileNames(1).
   SaveFile FileNames(1), EnvelopedData.Content
   Wscript.Stdout.Writeline "Successful - Decrypted content saved to " & FileNames(1) & "."

   ' Освобождение ресурсов.
   Set EnvelopedData = Nothing

End Sub ' Конец DoDecryptCommand

'******************************************************************************
'Функция LoadFile читает содержимое текстового файла.
'******************************************************************************

Sub LoadFile (FileName, Buffer)
    Dim fso
    Set fso = CreateObject("Scripting.FileSystemObject")

    If Not fso.FileExists(FileName) Then
        Wscript.Stdout.Writeline "Error: File " & FileName & " not found."
        Wscript.Quit(-5)
    End If

    Dim ts
    Set ts = fso.OpenTextFile(FileName, ForReading)
    Buffer = ts.ReadAll

End Sub ' Конец LoadFile

'******************************************************************************
' Функция SaveFile сохраняет строку в файл.
'******************************************************************************

Sub SaveFile (FileName, Buffer)
    Dim fso
    Set fso = CreateObject("Scripting.FileSystemObject")

    Dim ts
    Set ts = fso.OpenTextFile(FileName, ForWriting, True)
    ts.Write Buffer

End Sub ' End SaveFile

'******************************************************************************
' Функция ParseCommandLine разбирает командную строку и устанавливает
' опции согласно ей.
'******************************************************************************

Sub ParseCommandLine

   ' Константы для разбора состояний, задаваемых командной строкой.
   Const ARG_STATE_COMMAND    = 0
   Const ARG_STATE_OPTIONS    = 1
   Const ARG_STATE_FILENAME   = 8

   ' Разбор командной строки.
   Dim Arg
   Dim ArgState : ArgState = ARG_STATE_COMMAND

   For Each Arg In Wscript.Arguments
      Select Case ArgState
      Case ARG_STATE_COMMAND
         Select Case UCase(Arg)
         Case "ENCRYPT"
            Command = Encrypt

         Case "DECRYPT"
            Command = Decrypt

         Case Else
            DisplayUsage

         End Select

         ArgState = ARG_STATE_OPTIONS

      Case ARG_STATE_OPTIONS
         Select Case UCase(Arg)

         Case "-?", "/?"
            DisplayUsage

         Case Else
            If Left(Arg, 1) = "-"  OR Left(Arg, 1) = "/" Then
               DisplayUsage
            Else
               ReDim FileNames(0)
               FileNames(0) = Arg
            End If
            ArgState = ARG_STATE_FILENAME

         End Select

      Case ARG_STATE_FILENAME
         If Left(Arg, 1) = "-"  OR Left(Arg, 1) = "/" Then
            DisplayUsage
         Else
            ReDim Preserve FileNames(UBound(FileNames) + 1)
         End If

         FileNames(UBound(FileNames)) = Arg

      Case Else
         Wscript.Stdout.Writeline "Internal script error: Unknown argument state (" & CStr(ArgState) & ") encountered."
         Wscript.Quit(-3)

      End Select
   Next

   ' Проверка правильности состояния.
   If ArgState <> ARG_STATE_FILENAME Then
      DisplayUsage
   End If

   ' Проверка опций.
   Select Case Command
   Case Encrypt

      ' Функция зашифрвоаниядолжна иметь входной и выходной файлы.
      If (UBound(FileNames) - LBound(FileNames) + 1) <> 2 Then
         DisplayUsage
      End If

   Case Decrypt
      ' Функция расшифрования должна иметь входной и выходной файлы.
      If (UBound(FileNames) - LBound(FileNames) + 1) <> 2 Then
         DisplayUsage
      End If

   End Select

End Sub ' Конец ParseCommandLine

'******************************************************************************
' Функция DisplayUsage распечатывает информацию об использовании данного
' примера, и затем осуществляет выход с ошибкой.
'******************************************************************************

Sub DisplayUsage

   Select Case Command
      Case Unknown
         Wscript.Stdout.Writeline "Usage: CEnvelop Command InFile OutFile"
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "Command:"
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "  Encrypt                    -- Envelop a text file"
         Wscript.Stdout.Writeline "  Decrypt                    -- Decrypt an enveloped text file"
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "For help on a specific command, enter ""CEnvelop Command -?"""

      Case Encrypt
         Wscript.Stdout.Writeline "Usage: CEnvelop Encrypt ContentFile EnvelopedFile"
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "The Encrypt command is used to envelop a text file to multiple recipients, of"
         Wscript.Stdout.Writeline "which the certificates must either reside in the AddressBook store, or in the"
         Wscript.Stdout.Writeline "specified certificate file. Enveloping protects the data from being read by"
         Wscript.Stdout.Writeline "others except the intended recipients."
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "Parameters:"
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "  -?                         -- This help screen"
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "  ContentFile                -- Text file to be enveloped"
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "  EnvelopedFile              -- Enveloped text file"
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "Note: All non-fatal invalid options for this specific command will be ignored,"
         Wscript.Stdout.Writeline "      and the ** symbol indicates option can be listed multiple times."
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "      If there is only one certificate found matching the requirement, that"
         Wscript.Stdout.Writeline "      particular certificate will be used as the recipient's certificate."
                   Wscript.Stdout.Writeline "      However, if there is more than one certificate matching the requirement,"
         Wscript.Stdout.Writeline "      a dialog will be displayed to allow selection of multiple recipient's"
         Wscript.Stdout.Writeline "      certificates."
         Wscript.Stdout.Writeline

       Case Decrypt
         Wscript.Stdout.Writeline "Usage: CEnvelop Decrypt EnvelopedFile ContentFile"
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "The Decrypt command is used to decrypt an enveloped text file. The decryption"
         Wscript.Stdout.Writeline "process will automatically search for the recipient's certificate in MY store"
         Wscript.Stdout.Writeline "(Current User or Local Machine)."
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "Parameters:"
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "  -?                         -- This help screen"
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "  EnvelopedFile              -- Enveloped text file"
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "  ContentFile                -- Decrypted text file"
         Wscript.Stdout.Writeline
         Wscript.Stdout.Writeline "Note: All non-fatal invalid options for this specific command will be ignored."
         Wscript.Stdout.Writeline

      Case Else
         Wscript.Stdout.Writeline "Internal script error: Unknown help state (Command = " & CStr(Command) & ")."
         Wscript.Quit(-2)

   End Select

   Wscript.Quit(-1)

End Sub ' Конец DisplayUsage

Требования:

Windows 2000/XP/2003: Отдельный пакет распотраняемый Microsoft для Windows 2000, XP, 2003.


Примеры использования криптопровайдера совместно с функциями CEnroll.

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

  • Пример создания запроса на сертификат


Крипто-Про CSP

Данный пример демонстрирует осуществление создания запроса на сертификат при помощи инструментария CEnroll.

'-----------------------------------------------------------------------------
'
' В данном script-примере создается запрос на сертификат
' в кодировке base64 PKCS10 при помощи инструментария CEnroll.
'
'******************************************************************************

' Идентификационное имя запроса.
Dim strDN

' Запрос.
Dim strReq

' CEnroll Объект
Dim objXen

' Обработка ошибок.
On Error Resume Next

' Создание объекта.
Set objXen = CreateObject("CEnroll.CEnroll.1")

' Создание идентификационного имени.
strDN =  "CN=UserName" _
      & ",OU=UserUnit" _
      & ",O=CRYPTO-PRO" _
      & ",L=MOSCOW" _
      & ",S=WA" _
      & ",C=RU"

'Опредление типа провайдера
objXen.ProviderType = 75

'Определение имени провайдера
objXen.ProviderName = "Crypto-Pro GOST R 34.10-2001 Cryptographic Service Provider"

' Создание запроса PKCS #10.
MsgBox("Creating PKCS #10 " & strDN)
strReq = objXen.createPKCS10( strDN, "1.3.6.1.4.1.311.2.1.21")

' Если запрос не создан - сообщение об ошибке.
if ( Err.Number <> 0 ) then
    MsgBox("Error in call to createPKCS10 " & Err.Number)
    err.clear
else
' Если запрос создан - вывод на экран и запись в файл этого запроса.
    MsgBox("Submitting request " & strReq)
    Dim fso, MyFile
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set MyFile = fso.CreateTextFile("c:\testfile.txt", True)
    MyFile.Write strReq
    MyFile.Close
end if

Wscript.Quit(0)
' Окончание программы

Требования:

Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.


Список требований

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

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Файл описания: Прототип описан в файле WinCryptEx.h.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

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

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Файл описания: Прототип описан в файле WinCryptEx.h.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

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

  • Windows NT/2000: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows 95/98/ME: CSP 3.0 не поддерживает (см. ?).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше.

    Linux: RedHat 7.3, RedHad 9.0.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

    Файл описания: Windows прототип описан в файле Wincrypt.h, Solaris - CSP_Wincrypt.h

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

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Файл описания: Прототип описан в файле WinCryptEx.h.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

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

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Файл описания: Прототип описан в файле WinCryptEx.h.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

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

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Файл описания: Прототип описан в файле WinCryptEx.h.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

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

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Файл описания: Прототип описан в файле WinCryptEx.h.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

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

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Файл описания: Прототип описан в файле WinCryptEx.h.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

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

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Файл описания: Прототип описан в файле WinCryptEx.h.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

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

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Файл описания: Прототип описан в файле WinCryptEx.h.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

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

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Файл описания: Прототип описан в файле WinCryptEx.h.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

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

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Файл описания: Прототип описан в файле WinCryptEx.h.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

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

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Файл описания: Прототип описан в файле WinCryptEx.h.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

    • Глобальный CPAcquireContext (HCRYPTPROV *phProv, CHAR *pszContainer, DWORD dwFlags, PVTABLEPROVSTRUC pVTable)

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Файл описания: Прототип описан в файле wincsp.h.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

    Ядро ОС: При использовании в ядре ОС CPAcquireContext допустимо вызывать только с флагами CRYPT_VERIFYCONTEXT|CRYPT_SILENT.

    • Глобальный CPGetProvParam (HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData, DWORD *pdwDataLen, DWORD dwFlags)

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Файл описания: Прототип описан в файле wincsp.h.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

    • Глобальный CPReleaseContext (HCRYPTPROV hProv, DWORD dwFlags)

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Файл описания: Прототип описан в файле wincsp.h.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

    • Глобальный CPSetProvParam (HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData, DWORD dwFlags)

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Файл описания: Прототип описан в файле wincsp.h.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

    • Глобальный CPDeriveKey (HCRYPTPROV hProv, ALG_ID AlgId, HCRYPTHASH hBaseData, DWORD dwFlags, HCRYPTKEY *phKey)

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Файл описания: Прототип описан в файле wincsp.h.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

    • Глобальный CPDestroyKey (HCRYPTPROV hProv, HCRYPTKEY hKey)

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Файл описания: Прототип описан в файле wincsp.h.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

    • Глобальный CPDuplicateKey (HCRYPTPROV hProv, HCRYPTKEY hKey, DWORD *pdwReserved, DWORD dwFlags, HCRYPTKEY *phKey)

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Файл описания: Прототип описан в файле wincsp.h.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

    • Глобальный CPExportKey (HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTKEY hExpKey, DWORD dwBlobType, DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Файл описания: Прототип описан в файле wincsp.h.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

    Ядро ОС: Поддерживается только типы SIMPLEBLOB и DIVERSKEYBLOB.

    • Глобальный CPGenKey (HCRYPTPROV hProv, ALG_ID AlgId, DWORD dwFlags, HCRYPTKEY *phKey)

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Файл описания: Прототип описан в файле wincsp.h.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

    Ядро ОС: При использовании в ядре ОС CPGenKey допустимо вызывать только для производства ключей сессии.

    • Глобальный CPGenRandom (HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer)

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Файл описания: Прототип описан в файле wincsp.h.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

    Ядро ОС: Перед получением случайных чисел требуется инициализировать ДСЧ контекста криптопровайдера hProv с помощью параметра PP_RANDOM функции CPSetProvParam().

    • Глобальный CPGetKeyParam (HCRYPTPROV hProv, HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData, DWORD *pdwDataLen, DWORD dwFlags)

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Файл описания: Прототип описан в файле wincsp.h.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

    • Глобальный CPGetUserKey (HCRYPTPROV hProv, DWORD dwKeySpec, HCRYPTKEY *phUserKey)

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Файл описания: Прототип описан в файле wincsp.h.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

    • Глобальный CPImportKey (HCRYPTPROV hProv, WINCSP_CONST BYTE *pbData, DWORD dwDataLen, HCRYPTKEY hImpKey, DWORD dwFlags, HCRYPTKEY *phKey)

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Файл описания: Прототип описан в файле wincsp.h.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

    Ядро ОС: Поддерживается только типы SIMPLEBLOB и DIVERSKEYBLOB.

    • Глобальный CPSetKeyParam (HCRYPTPROV hProv, HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData, DWORD dwFlags)

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Файл описания: Прототип описан в файле wincsp.h.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

    • Глобальный CPDecrypt (HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final, DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Файл описания: Прототип описан в файле wincsp.h.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

    • Глобальный CPEncrypt (HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final, DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen, DWORD dwBufLen)

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Файл описания: Прототип описан в файле wincsp.h.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

    • Глобальный CPCreateHash (HCRYPTPROV hProv, ALG_ID AlgId, HCRYPTKEY hKey, DWORD dwFlags, HCRYPTHASH *phHash)

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Файл описания: Прототип описан в файле wincsp.h.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

    • Глобальный CPDestroyHash (HCRYPTPROV hProv, HCRYPTHASH hHash)

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Файл описания: Прототип описан в файле wincsp.h.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

    • Глобальный CPDuplicateHash (HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD *pdwReserved, DWORD dwFlags, HCRYPTHASH *phHash)

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Файл описания: Прототип описан в файле wincsp.h.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

    • Глобальный CPGetHashParam (HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData, DWORD *pdwDataLen, DWORD dwFlags)

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Файл описания: Прототип описан в файле wincsp.h.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

    • Глобальный CPHashData (HCRYPTPROV hProv, HCRYPTHASH hHash, WINCSP_CONST BYTE *pbData, DWORD dwDataLen, DWORD dwFlags)

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Файл описания: Прототип описан в файле wincsp.h.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

    • Глобальный CPHashSessionKey (HCRYPTPROV hProv, HCRYPTHASH hHash, HCRYPTKEY hKey, DWORD dwFlags)

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Файл описания: Прототип описан в файле wincsp.h.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

    • Глобальный CPSetHashParam (HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData, DWORD dwFlags)

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Файл описания: Прототип описан в файле wincsp.h.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

    • Глобальный CPSignHash (HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD dwKeySpec, LPCWSTR sDescription, DWORD dwFlags, BYTE *pbSignature, DWORD *pdwSigLen)

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Файл описания: Прототип описан в файле wincsp.h.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

    Ядро ОС: В ядре ОС эта функция не поддерживается.

    • Глобальный CPVerifySignature (HCRYPTPROV hProv, HCRYPTHASH hHash, WINCSP_CONST BYTE *pbSignature, DWORD dwSigLen, HCRYPTKEY hPubKey, LPCWSTR sDescription, DWORD dwFlags)

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Файл описания: Прототип описан в файле wincsp.h.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

    Ядро ОС: "Ядро ОС:" В ядре ОС эта функция не поддерживается.

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

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Ядро Windows NT: IRQL < DISPATCH_LEVEL

    • Страница Пример на создание ключевого контейнера и генерацию ключей

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Ядро Windows NT: не поддерживает.

    • Страница Пример использования функции CryptAcquireContext

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Ядро Windows NT: не поддерживает.

    • Страница Пример на перечисление криптопровайдеров

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Ядро Windows NT: не поддерживает.

    • Страница Пример на получение сессионного ключа из пароля

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Ядро Windows NT: не поддерживает.

    • Страница Пример на дублирование сессионного ключа

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Ядро Windows NT: не поддерживает.

    • Страница Пример на установку и получение сессионного ключа

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Ядро Windows NT: не поддерживает.

    • Страница Пример на экспортирование сессионного ключа с использованием структуры BLOB

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Ядро Windows NT: не поддерживает.

    • Страница Пример на экспортирование сессионного ключа с использованием сертификатами

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Ядро Windows NT: не поддерживает.

    • Страница Пример на закодирование и раскодирование данных

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Ядро Windows NT: не поддерживает.

    • Страница Пример на CryptEncryptMessage и CryptDecryptMessage

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Ядро Windows NT: не поддерживает.

    • Страница Пример на копирование закрытого ключа

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Ядро Windows NT: не поддерживает.

    • Страница Пример на работу в режиме SILENT, без окон

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Ядро Windows NT: не поддерживает.

    • Страница Непосредственный вызов функций криптопровайдера

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Ядро Windows NT: не поддерживает.

    • Страница Пример на создание хеша

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Ядро Windows NT: не поддерживает.

    • Страница Пример на подпись объекта функции хеширования и проверку подписи

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Ядро Windows NT: не поддерживает.

    • Страница Пример на дублирование хеша

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Ядро Windows NT: не поддерживает.

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

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Ядро Windows NT: не поддерживает.

    • Страница Пример на зашифрование файла

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Ядро Windows NT: не поддерживает.

    • Страница Пример на расшифрование файла

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Solaris: 9 Update 4 или выше.

    FreeBSD: FreeBSD 5.2 или выше

    Linux: RedHat 7.3, RedHad 9.0.

    Ядро Windows NT: не поддерживает.

    • Страница Пример на зашифрование сообщения в драйвере

  • Ядро Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Ядро Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Ядро Solaris: 9 Update 4 или выше.

    Ядро FreeBSD: FreeBSD 5.2 или выше

    Ядро Linux: RedHat 7.3, RedHad 9.0.

    • Страница Пример на проверку подписи в драйвере

  • Ядро Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    Ядро Windows NT/95/98/ME: CSP 3.0 не поддерживает (см. КриптоПро CSP 2.0 World Wide Web link ).

    Ядро Solaris: 9 Update 4 или выше.

    Ядро FreeBSD: FreeBSD 5.2 или выше

    Ядро Linux: RedHat 7.3, RedHad 9.0.

    • Страница Шаблон XML-документа на подпись

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше и MSXML 5.0.

    • Страница Шаблон XML-документа для создания двух подписей

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше и MSXML 5.0.

    • Страница Пример создания подписи XML-документа

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше и MSXML 5.0.

    • Страница Пример проверки подписи XML-документа

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше и MSXML 5.0.

    • Страница Пример создания и проверки двух подписей XML-документа

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше и MSXML 5.0.

    • Страница Пример подписи и проверки подписи при помощи CAPICOM

  • Windows 2000/XP/2003: Отдельный пакет распотраняемый Microsoft для Windows 2000, XP, 2003.

    • Страница Пример зашифрования и расшифрования при помощи CAPICOM

  • Windows 2000/XP/2003: Отдельный пакет распотраняемый Microsoft для Windows 2000, XP, 2003.

    • Страница Пример создания запроса на сертификат

  • Windows 2000/XP/2003: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.

    • Крипто-Про CSP Версия: 3.0 Сборка 3293


Требования

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

Формат 1

Требования
Клиент: Требования содержатся в "ВерсииОперационнойСистемы" .
Сервер: Требования содержатся в "ВерсииОперационнойСистемы" .
Дополнительное программное обеспечение: Требования Дополнительного программного обеспечения в "ВерсииОперационнойСистемы" .
Заголовок: Элемент описан в файле "ЗаголовочныйФайл" ; необходимо подключить файл "ВключаемыйЗаголовочныйФайл" .
Библиотека: Необходимо использовать библиотеку "БиблиотечныйФайл" .
Unicode: Элемент реализован в Unicode и ANSI версиях.

Формат 2

Требования
Windows NT/2000/XP: Требования содержатся в "ВерсииОперационнойСистемы" .
Windows 95/98/Me: Требования содержатся в "ВерсииОперационнойСистемы" .
Дополнительное программное обеспечение: Требования Дополнительного программного обеспечения для "ВерсииОперационнойСистемы" .
Заголовок: Элемент описан в файле "ЗаголовочныйФайл" ; необходимо подключить файл "ВключаемыйЗаголовочныйФайл" .
Библиотека: Необходимо использовать библиотеку "БиблиотечныйФайл" .
Unicode: Элемент реализован в Unicode и ANSI версиях.

В строке Клиент приводится список тех клиентских платформ, которые имеют встроенную поддержку данного элемента API. Например, Windows XP, Windows 2000 Professional, Windows NT Workstation, Windows Me, Windows 98 и Windows 95 - все они являются клиентскими платформами.

В строке Сервер указывается список серверных платформ, имеющих встроенную поддержку данного элемента API. Например, Windows Server 2003, Windows 2000 Server, и Windows NT Server - все они являются серверными платформами. Для каждой платформы возможны различные варианты SKU. Если элемент поддерживается только некоторыми из них, это указывается отдельно. В противном случае указываются все SKU. Например, Windows 2000 Server поддерживается платформами Windows 2000 Server, Windows 2000 Advanced Server и Windows 2000 Datacenter Server.

В строке Windows NT/2000/XP указано, имеется ли встроенная поддержка данного элемента в операционных системах Windows Server 2003, Windows XP, Windows 2000 или Windows NT, все из которых написаны на основе кода Windows NT. Если элемент на этих платформах не поддерживается, в данной строке будет указано: "Не поддерживается".

В строке Windows 95/98/Me указывается, имеется ли встроенная поддержка данного элемента в Windows 95, Windows 98 или Windows Me. Если элемент на этих платформах не поддерживается, в данной строке будет указано "Не поддерживается.", либо эта строка будет опущена.

В строке Дополнительное программное обеспечение указываются дополнительные требования для поддержки данного элемента API, не имеющие встроенной поддержки в той или иной версии Windows. Для тех элементов, которые имеют только встроенную поддержку, эта строка опускается.

В строке Заголовок приводится имя заголовочного файла, в котором определен данный элемент API. Это может быть .h-, .idl- или .odl-файл. В этой строке может также указываться, что в пользовательском коде должен использоваться другой заголовочный файл (файл, включающий тот, в котором описан данный элемет API, а также другие необходимые заголовочные файлы и определения). Если заголовочный файл определяется пользователем, или если он вообще не требуется, эта строка опускается.

В строке Библиотека указывается имя библиотечного файла, вызываемого при обращениях к функции или ее элементам. Это может быть .lib-, .dll- или .tlb файл. Если библиотечный файл определяется пользователем, или если он вообще не требуется, эта строка опускается.

В строке Unicode указывается, существует ли элемент как в Unicode (W) версии, так и в ANSI (A) версии. В противном случае, эта строка опускается.

Пример

Ниже описан пример блока требований.

Windows NT/2000/XP: Требования для Windows NT 4.0 и выше.
Windows 95/98/Me: Требования для Windows 98 и выше.
Дополнительное программное обеспечение: Требования IE 4.01 или выше для Windows 95.
Заголовок: Элемент описан в файле Winuser.h; include Windows.h.
Библиотека: Необходимо использовать библиотеку User32.lib.
Unicode: Элемент реализован в Unicode и ANSI версиях.

Функция, к которой относятся эти требования, имеет встроенную поддержку в операционных системах Windows Server 2003, Windows XP, Windows 2000, Windows NT 4.0, Windows Me и Windows 98. Для вызова этой функции в системе Windows 95, необходимо установить Internet Explorer 4.01 или выше. Для компиляции кода, в котором используется эта функция, в него должен быть включен заголовочный файл Windows.h (хотя для того, чтобы просмотреть объявление функции необходимо обратиться к файлу Winuser.h). Для линковщика необходимо указать библиотеку User32.lib.