//-------------------------------------------------------------------- // Пример кода, использующего CryptAcquireContext. //-------------------------------------------------------------------- #define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING) static HCRYPTPROV hCryptProv = 0; static HCRYPTKEY hKey = 0; static void CleanUp(void); static void HandleError(char *s); int main(int argc, char *argv[]) { // Объявление и инициализация переменных. BYTE pbData[MAX_CONTAINER_NAME_LEN+1]; DWORD cbData; BOOL bSilent = FALSE; // Флаг режима без окон if (argc > 1 && strcmp(argv[1], "-silent") == 0) bSilent = TRUE; printf("Mode: %s\n", bSilent ? "SILENT" : "NORMAL"); // Получение дескриптора криптопровайдера. if(!CryptAcquireContext( &hCryptProv, CONTAINER, NULL, PROV_GOST_2012_256, (bSilent ? CRYPT_SILENT : 0))) { if(GetLastError() != (DWORD)NTE_BAD_KEYSET && GetLastError() != (DWORD)NTE_KEYSET_NOT_DEF) { HandleError("A general error occurred running CryptAcquireContext"); } 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"); CleanUp(); exit(1); } printf("CryptAcquireContext succeeded.\n"); // Чтение имени CSP. cbData = MAX_CONTAINER_NAME_LEN; if(!CryptGetProvParam( hCryptProv, PP_NAME, NULL, &cbData, 0)) { HandleError("Error reading CSP name. \n"); } if(cbData > MAX_CONTAINER_NAME_LEN) HandleError("CSP name length is too long"); pbData[MAX_CONTAINER_NAME_LEN] = 0; if(!CryptGetProvParam( hCryptProv, PP_NAME, pbData, &cbData, 0)) { HandleError("Error reading CSP name. \n"); } printf("CryptGetProvParam succeeded.\n"); printf("Provider name: %s\n", pbData); // Чтение имени ключевого контейнера. cbData = MAX_CONTAINER_NAME_LEN; if(!CryptGetProvParam( hCryptProv, PP_CONTAINER, pbData, &cbData, 0)) { HandleError("Error reading key container name. \n"); } if(cbData > MAX_CONTAINER_NAME_LEN) HandleError("Container name length is too long"); if(!CryptGetProvParam( hCryptProv, PP_CONTAINER, pbData, &cbData, 0)) { HandleError("Error reading key container name. \n"); } printf("CryptGetProvParam succeeded. \n"); printf("Key Container name: %s\n", pbData); // Выполнение криптографических операций. // Увеличение счетчика ссылок на криптопровайдер. Когда счетчик ссылок на // криптопровайдер становится больше 1, CryptReleaseContext уменьшает // счетчик ссылок, но не освобождает криптопровайдер. if(!CryptContextAddRef( hCryptProv, NULL, 0)) { HandleError("Error during CryptContextAddRef!\n"); } printf("CryptContextAddRef succeeded. \n"); // Счетчик ссылок на hCryptProv сейчас больше 1. Первый вызов // функции CryptReleaseContext не освободит дескриптор криптопровайдера. // Однократное освобождение контекста. if(!CryptReleaseContext(hCryptProv, 0)) { HandleError("Error during CryptReleaseContext! #1"); } printf("The first call to CryptReleaseContext succeeded. \n"); // Повторное освобождение дескриптора криптопровайдера. if(!CryptReleaseContext(hCryptProv, 0)) { HandleError("Error during CryptReleaseContext! #2"); } printf("The second call to CryptReleaseContext succeeded. \n"); // Получение дескриптора криптопровайдера и // создание ключевого контейнера с именем "KC1_test". if(!CryptAcquireContext( &hCryptProv, #ifdef _WIN32 _TEXT("\\\\.\\REGISTRY\\KC1_test"), #else _TEXT("\\\\.\\HDIMAGE\\KC1_test"), #endif NULL, PROV_GOST_2012_256, CRYPT_NEWKEYSET | (bSilent ? CRYPT_SILENT : 0))) { HandleError("Error during CryptAcquireContext for a new key " "container. A container with this name probably " "already exists"); } printf("CryptAcquireContext (CRYPT_NEWKEYSET) succeeded. \n"); // begin Особенность КриптоПро CSP // Особенностью КриптоПро CSP является то, что криптопровайдер // физически не создает (записывает) контейнер, если в нем // нет закрытых ключей. Поэтому необходимо создать ключ. if(!CryptGenKey( hCryptProv, AT_SIGNATURE, 0, &hKey)) { HandleError("Error occurred creating a signature key.\n"); } printf("Created a signature key pair.\n"); // end Особенность КриптоПро CSP // Выполнение криптографических операций. // Освобождение дескриптора криптопровайдера и ключевого контейнера KC1. if(!CryptReleaseContext(hCryptProv, 0)) { HandleError("Error during CryptReleaseContext!\n"); } printf("CryptReleaseContext succeeded. \n"); hCryptProv = 0; hKey = 0; // Получение дескриптора криптопровайдера, используя новый ключевой контейнер. // Замечание: Этот ключевой контейнер будет пустым до тех пор, пока ключи // не будут явно созданы с помощью функции CryptGenKey. if(!CryptAcquireContext( &hCryptProv, _TEXT("KC1_test"), NULL, PROV_GOST_2012_256, 0)) { HandleError("Error during CryptAcquireContext!\n"); } printf("Acquired the key set just created. \n"); // Выполнение криптографических операций. // Освобождение дескриптора криптопровайдера и ключевого контейнера KC1. if(!CryptReleaseContext(hCryptProv, 0)) { HandleError("Error during CryptReleaseContext!\n"); } printf("CryptReleaseContext succeeded. \n"); hCryptProv = 0; // Для повторного испоьзования этого примера необходимо удалить созданный // ключей контейнер с именем "КС1". Контейнер можно удалить при помощи // контрольной панели КриптоПро CSP или следующим образом: if(!CryptAcquireContext( &hCryptProv, _TEXT("KC1_test"), NULL, PROV_GOST_2012_256, CRYPT_DELETEKEYSET)) { HandleError("Error during CryptAcquireContext(CRYPT_DELETEKEYSET)!\n"); } printf("CryptAcquireContext (CRYPT_DELETEKEYSET) succeeded. \n"); CleanUp(); return 0; } // Конец примера
AIX: 5/6/7 или выше.
FreeBSD: 7/8/9 или выше.
Linux: LSB 3.1 (RHEL 4, SuSE 10) или выше.
Solaris: 10 или выше.
Mac OSX: 10.7/8 или выше.
iOS: 6/7 или выше.
Windows 2000 или выше: Необходимо Windows 2000 SP4 или старше с Internet Explorer 6.0 или старше.
Ядро Windows NT: не поддерживает.