Функция CryptAcquireContextA (wincrypt.h)

Важно Этот API не рекомендуется использовать. Новое и существующее программное обеспечение должно начать использовать API-интерфейсы шифрования следующего поколения. Корпорация Майкрософт может удалить этот API в будущих выпусках.
 
Функция CryptAcquireContext используется для получения дескриптора определенного контейнера ключей в определенном поставщике служб шифрования (CSP). Этот возвращенный дескриптор используется в вызовах функций CryptoAPI , использующих выбранный поставщик служб CSP.

Эта функция сначала пытается найти CSP с характеристиками, описанными в параметрах dwProvType и pszProvider . Если поставщик служб конфигурации найден, функция пытается найти в CSP контейнер ключей, соответствующий имени, указанному параметром pszContainer . Чтобы получить контекст и контейнер ключей закрытого ключа , связанного с открытым ключом сертификата, используйте CryptAcquireCertificatePrivateKey.

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

Синтаксис

BOOL CryptAcquireContextA(
  [out] HCRYPTPROV *phProv,
  [in]  LPCSTR     szContainer,
  [in]  LPCSTR     szProvider,
  [in]  DWORD      dwProvType,
  [in]  DWORD      dwFlags
);

Параметры

[out] phProv

Указатель на дескриптор CSP. Завершив использование CSP, отпустите дескриптор, вызвав функцию CryptReleaseContext .

[in] szContainer

Имя контейнера ключа. Это строка, заканчивающаяся null, которая определяет контейнер ключей для CSP. Это имя не зависит от метода, используемого для хранения ключей. Некоторые поставщики служб конфигурации хранят контейнеры ключей внутри (на оборудовании), некоторые используют системный реестр, а другие — файловую систему. В большинстве случаев, когда dwFlags имеет значение CRYPT_VERIFYCONTEXT, pszContainer должен иметь значение NULL. Однако для аппаратных CSP, таких как смарт-карта CSP, можно получить доступ к общедоступной информации в конкретном контейнере.

Дополнительные сведения об использовании параметра pszContainer см. в разделе Примечания.

[in] szProvider

Строка, заканчивающаяся null, которая содержит имя используемого поставщика служб CSP.

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

Приложение может получить имя используемого CSP с помощью функции CryptGetProvParam для чтения значения PP_NAME CSP в параметре dwParam .

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

[in] dwProvType

Указывает тип поставщика для получения. Определенные типы поставщиков рассматриваются в разделе Типы поставщиков шифрования.

[in] dwFlags

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

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

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

Если параметр pszContainer имеет значение NULL или пусто для аппаратных поставщиков служб, таких как смарт-карта CSP, этот флаг означает, что доступ к ключам не требуется, а пользователю не следует представлять пользовательский интерфейс. Эта форма используется для подключения к CSP для запроса его возможностей, но не для фактического использования ключей. Если параметр pszContainer не равен NULL и не пуст, то этот флаг означает, что требуется доступ только к общедоступным сведениям в указанном контейнере. Поставщик служб CSP не должен запрашивать ПИН-код. Попытки получить доступ к личной информации (например, функции CryptSignHash ) завершатся ошибкой.

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

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

Windows XP: Доступ к контейнеру ключей, созданному без этого флага администратором, может получить только пользователь, создающий контейнер ключей и учетную запись локальной системы.

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

Флаг CRYPT_MACHINE_KEYSET можно объединить со всеми другими флагами, чтобы указать, что контейнер ключей является контейнером ключей компьютера, а поставщик служб CSP обрабатывает его как таковой. Для базовых поставщиков это означает, что ключи хранятся локально на компьютере, на который был создан контейнер ключей. Если контейнер ключей должен быть контейнером компьютера, флаг CRYPT_MACHINE_KEYSET должен использоваться для всех вызовов CryptAcquireContext , ссылающихся на контейнер компьютера. Доступ к контейнеру ключей, созданному с помощью CRYPT_MACHINE_KEYSET администратором, может получить только его создатель и пользователь с правами администратора, если только права доступа к контейнеру не предоставлены с помощью CryptSetProvParam.

Windows XP: Контейнер ключей, созданный с помощью CRYPT_MACHINE_KEYSET администратором, может быть доступен только его создателю и учетной записи локальной системы, если только права доступа к контейнеру не предоставлены с помощью CryptSetProvParam.

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

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

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

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

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

CRYPT_SILENT предназначена для приложений, для которых поставщик служб CSP не может отображать пользовательский интерфейс.

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

Windows Server 2003 и Windows XP: Этот флаг не поддерживается.

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

Если функция выполняется успешно, функция возвращает ненулевое значение (TRUE).

Если функция завершается сбоем, она возвращает ноль (FALSE). Чтобы получить дополнительные сведения об ошибке, вызовите Метод GetLastError.

Коды ошибок, предваряемые NTE, создаются конкретным поставщиком служб CSP. Ниже приведены некоторые возможные коды ошибок, определенные в Winerror.h.

Возвращаемый код или значение Описание
ERROR_BUSY
107L
Некоторые поставщики служб конфигурации устанавливают эту ошибку, если задано значение флага CRYPT_DELETEKEYSET, а другой поток или процесс использует этот контейнер ключей.
ERROR_FILE_NOT_FOUND
2L
Профиль пользователя не загружен и не найден. Это происходит, когда приложение олицетворяет пользователя, например учетную запись IUSR_ComputerName .
ERROR_INVALID_PARAMETER
87L
Один из параметров содержит недопустимое значение. Чаще всего это недопустимый указатель.
ERROR_NOT_ENOUGH_MEMORY
8L
Во время операции в операционной системе не хватает памяти.
NTE_BAD_FLAGS
0x80090009L
Параметр dwFlags имеет недопустимое значение.
NTE_BAD_KEY_STATE
0x8009000BL
Пароль пользователя изменился с момента шифрования закрытых ключей.
NTE_BAD_KEYSET
0x80090016L
Не удалось открыть контейнер ключей. Распространенная причина этой ошибки заключается в том, что контейнер ключей не существует. Чтобы создать контейнер ключей, вызовите CryptAcquireContext , используя флаг CRYPT_NEWKEYSET. Этот код ошибки также может указывать на то, что доступ к существующему контейнеру ключей запрещен. Права доступа к контейнеру могут быть предоставлены создателем набора ключей с помощью CryptSetProvParam.
NTE_BAD_KEYSET_PARAM
0x8009001FL
Параметру pszContainer или pszProvider присваивается недопустимое значение.
NTE_BAD_PROV_TYPE
0x80090014L
Значение параметра dwProvType выходит за пределы диапазона. Все типы поставщиков должны быть от 1 до 999 включительно.
NTE_BAD_SIGNATURE
0x80090006L
Не удалось проверить подпись поставщика DLL. Либо библиотека DLL, либо цифровая подпись были изменены.
NTE_EXISTS
0x8009000FL
Параметр dwFlags CRYPT_NEWKEYSET, но контейнер ключей уже существует.
NTE_KEYSET_ENTRY_BAD
0x8009001AL
Контейнер ключей pszContainer найден, но поврежден.
NTE_KEYSET_NOT_DEF
0x80090019L
Запрошенный поставщик не существует.
NTE_NO_MEMORY
0x8009000EL
Во время операции у поставщика служб CSP не хватает памяти.
NTE_PROV_DLL_NOT_FOUND
0x8009001EL
DLL-файл поставщика не существует или не находится по текущему пути.
NTE_PROV_TYPE_ENTRY_BAD
0x80090018L
Тип поставщика, указанный параметром dwProvType , поврежден. Эта ошибка может относиться либо к списку CSP по умолчанию пользователя, либо к списку CSP компьютера по умолчанию.
NTE_PROV_TYPE_NO_MATCH
0x8009001BL
Тип поставщика, указанный параметром dwProvType , не соответствует найденной типу поставщика. Обратите внимание, что эта ошибка может возникать только в том случае, если pszProvider указывает фактическое имя CSP.
NTE_PROV_TYPE_NOT_DEF
0x80090017L
Для типа поставщика, указанного dwProvType, не существует записи.
NTE_PROVIDER_DLL_FAIL
0x8009001DL
Не удалось загрузить или инициализировать DLL-файл поставщика.
NTE_SIGNATURE_FILE_BAD
0x8009001CL
Ошибка при загрузке образа DLL-файла перед проверкой его подписи.

Комментарии

Параметр pszContainer указывает имя контейнера, используемого для хранения ключа. Каждый контейнер может содержать один ключ. Если при создании ключей указать имя существующего контейнера, новый ключ перезапишет предыдущий.

Сочетание имени CSP и имени контейнера ключей однозначно идентифицирует один ключ в системе. Если одно приложение пытается изменить контейнер ключей, когда другое приложение использует его, может привести к непредсказуемому поведению.

Если для параметра pszContainer задано значение NULL, используется имя контейнера ключей по умолчанию. При таком вызове поставщиков программного обеспечения Майкрософт при каждом вызове функции CryptAcquireContext создается новый контейнер. Однако разные поставщики служб конфигурации могут вести себя по-разному в этом отношении. В частности, поставщик служб CSP может иметь один контейнер по умолчанию, который используется всеми приложениями, обращаюющимися к CSP. Поэтому приложения не должны использовать контейнер ключей по умолчанию для хранения закрытых ключей. Вместо этого либо запретите хранение ключей, передав флаг CRYPT_VERIFYCONTEXT в параметре dwFlags , либо используйте контейнер приложения, который вряд ли будет использоваться другим приложением.

Приложение может получить имя используемого контейнера ключей с помощью функции CryptGetProvParam для чтения значения PP_CONTAINER.

Для повышения производительности рекомендуется задать для параметра pszContainerзначение NULL , а параметру dwFlags— значение CRYPT_VERIFYCONTEXT во всех ситуациях, когда не требуется сохранять ключ. В частности, рекомендуется задать для параметра pszContainerзначение NULL , а параметру dwFlags— значение CRYPT_VERIFYCONTEXT для следующих сценариев:

  • Вы создаете хэш.
  • Вы создаете симметричный ключ для шифрования или расшифровки данных.
  • Вы наследуете симметричный ключ из хэша для шифрования или расшифровки данных.
  • Вы проверяете подпись. Можно импортировать открытый ключ из PUBLICKEYBLOB или из сертификата с помощью CryptImportKey или CryptImportPublicKeyInfo. Контекст можно получить с помощью флага CRYPT_VERIFYCONTEXT , если вы планируете импортировать только открытый ключ.
  • Вы планируете экспортировать симметричный ключ, но не импортировать его в течение времени существования контекста шифрования. Контекст можно получить с помощью флага CRYPT_VERIFYCONTEXT , если вы планируете импортировать открытый ключ только для двух последних сценариев.
  • Вы выполняете операции с закрытым ключом, но не используете сохраненный закрытый ключ, хранящийся в контейнере ключей.
Если вы планируете выполнять операции с закрытым ключом, лучший способ получить контекст — попытаться открыть контейнер. Если эта попытка завершается сбоем с NTE_BAD_KEYSET, создайте контейнер с помощью флага CRYPT_NEWKEYSET .

Примеры

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

Пример, включающий полный контекст для этого примера, см. в разделе Пример программы C: создание контейнера ключей и создание ключей. Дополнительные примеры см. в разделе Пример программы C: использование CryptAcquireContext.

//-------------------------------------------------------------------
// Declare and initialize variables.

HCRYPTPROV hCryptProv = NULL;        // handle for a cryptographic
                                     // provider context
LPCSTR UserName = "MyKeyContainer";  // name of the key container
                                     // to be used
//-------------------------------------------------------------------
// Attempt to acquire a context and a key
// container. The context will use the default CSP
// for the RSA_FULL provider type. DwFlags is set to zero
// to attempt to open an existing key container.

if(CryptAcquireContext(
   &hCryptProv,               // handle to the CSP
   UserName,                  // container name 
   NULL,                      // use the default provider
   PROV_RSA_FULL,             // provider type
   0))                        // flag values
{
    printf("A cryptographic context with the %s key container \n", 
  UserName);
    printf("has been acquired.\n\n");
}
else
{ 
//-------------------------------------------------------------------
// An error occurred in acquiring the context. This could mean
// that the key container requested does not exist. In this case,
// the function can be called again to attempt to create a new key 
// container. Error codes are defined in Winerror.h.
 if (GetLastError() == NTE_BAD_KEYSET)
 {
   if(CryptAcquireContext(
      &hCryptProv, 
      UserName, 
      NULL, 
      PROV_RSA_FULL, 
      CRYPT_NEWKEYSET)) 
    {
      printf("A new key container has been created.\n");
    }
    else
    {
      printf("Could not create a new key container.\n");
      exit(1);
    }
  }
  else
  {
      printf("A cryptographic service handle could not be "
          "acquired.\n");
      exit(1);
   }
  
} // End of else.
//-------------------------------------------------------------------
// A cryptographic context and a key container are available. Perform
// any functions that require a cryptographic provider handle.

//-------------------------------------------------------------------
// When the handle is no longer needed, it must be released.

if (CryptReleaseContext(hCryptProv,0))
{
  printf("The handle has been released.\n");
}
else
{
  printf("The handle could not be released.\n");
}

Примечание

Заголовок wincrypt.h определяет CryptAcquireContext в качестве псевдонима, который автоматически выбирает версию ANSI или Юникод этой функции на основе определения константы препроцессора UNICODE. Сочетание использования псевдонима, не зависящий от кодировки, с кодом, не зависящим от кодировки, может привести к несоответствиям, которые приводят к ошибкам компиляции или среды выполнения. Дополнительные сведения см. в разделе Соглашения для прототипов функций.

Требования

Требование Значение
Минимальная версия клиента Windows XP [только классические приложения]
Минимальная версия сервера Windows Server 2003 [только классические приложения]
Целевая платформа Windows
Header wincrypt.h
Библиотека Advapi32.lib
DLL Advapi32.dll

См. также раздел

CryptGenKey

CryptGetProvParam

CryptReleaseContext

Функции поставщика услуг

Проблемы потоков с поставщиками служб шифрования