Função CryptAcquireContextA (wincrypt.h)

Importante Essa API foi preterida. O software novo e existente deve começar a usar APIs de Criptografia de Próxima Geração. A Microsoft pode remover essa API em versões futuras.
 
A função CryptAcquireContext é usada para adquirir um identificador para um contêiner de chave específico em um CSP ( provedor de serviço criptográfico ) específico. Esse identificador retornado é usado em chamadas para funções CryptoAPI que usam o CSP selecionado.

Essa função primeiro tenta encontrar um CSP com as características descritas nos parâmetros dwProvType e szProvider . Se o CSP for encontrado, a função tentará encontrar um contêiner de chave dentro do CSP que corresponda ao nome especificado pelo parâmetro szContainer . Para adquirir o contexto e o contêiner de chave de uma chave privada associada à chave pública de um certificado, use CryptAcquireCertificatePrivateKey.

Com a configuração apropriada de dwFlags, essa função também pode criar e destruir contêineres de chave e pode fornecer acesso a um CSP com um contêiner de chave temporário se o acesso a uma chave privada não for necessário.

Sintaxe

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

Parâmetros

[out] phProv

Um ponteiro para um identificador de um CSP. Quando terminar de usar o CSP, solte o identificador chamando a função CryptReleaseContext .

[in] szContainer

O nome do contêiner de chave. Essa é uma cadeia de caracteres terminada em nulo que identifica o contêiner de chaves para o CSP. Esse nome é independente do método usado para armazenar as chaves. Alguns CSPs armazenam seus contêineres de chave internamente (em hardware), alguns usam o registro do sistema e outros usam o sistema de arquivos. Na maioria dos casos, quando dwFlags é definido como CRYPT_VERIFYCONTEXT, szContainer deve ser definido como NULL. No entanto, para CSPs baseados em hardware, como um CSP de cartão inteligente, pode ser acessado informações disponíveis publicamente no contêiner especificado.

Para obter mais informações sobre o uso do parâmetro szContainer , consulte Comentários.

[in] szProvider

Uma cadeia de caracteres terminada em nulo que contém o nome do CSP a ser usado.

Se esse parâmetro for NULL, o provedor padrão do usuário será usado. Para obter mais informações, consulte Contextos do provedor de serviços criptográficos. Para obter uma lista de provedores criptográficos disponíveis, consulte Nomes de provedor criptográfico.

Um aplicativo pode obter o nome do CSP em uso usando a função CryptGetProvParam para ler o valor do CSP PP_NAME no parâmetro dwParam .

O CSP padrão pode mudar entre as versões do sistema operacional. Para garantir a interoperabilidade em diferentes plataformas do sistema operacional, o CSP deve ser definido explicitamente usando esse parâmetro em vez de usar o CSP padrão.

[in] dwProvType

Especifica o tipo de provedor a ser adquirido. Os tipos de provedor definidos são discutidos em Tipos de Provedor criptográfico.

[in] dwFlags

Valores de sinalizador. Esse parâmetro geralmente é definido como zero, mas alguns aplicativos definem um ou mais dos sinalizadores a seguir.

Valor Significado
CRYPT_VERIFYCONTEXT
Essa opção destina-se a aplicativos que estão usando chaves efêmeras ou aplicativos que não exigem acesso a chaves privadas persistentes, como aplicativos que executam apenas hash, criptografia e verificação de assinatura digital . Somente aplicativos que criam assinaturas ou descriptografam mensagens precisam de acesso a uma chave privada. Na maioria dos casos, esse sinalizador deve ser definido.

Para CSPs baseados em arquivo, quando esse sinalizador é definido, o parâmetro szContainer deve ser definido como NULL. O aplicativo não tem acesso às chaves privadas persistentes de pares de chaves públicas/privadas. Quando esse sinalizador é definido, pares temporários de chaves públicas/privadas podem ser criados, mas não são persistidos.

Para CSPs baseados em hardware, como um CSP de cartão inteligente, se o parâmetro szContainer for NULL ou em branco, esse sinalizador implica que nenhum acesso a nenhuma chave é necessário e que nenhuma interface do usuário deve ser apresentada ao usuário. Esse formulário é usado para se conectar ao CSP para consultar seus recursos, mas não para realmente usar suas chaves. Se o parâmetro szContainer não for NULL e não estiver em branco, esse sinalizador implicará que o acesso apenas às informações disponíveis publicamente dentro do contêiner especificado será necessário. O CSP não deve solicitar um PIN. As tentativas de acessar informações privadas (por exemplo, a função CryptSignHash ) falharão.

Quando CryptAcquireContext é chamado, muitos CSPs exigem entrada do usuário proprietário antes de conceder acesso às chaves privadas no contêiner de chaves. Por exemplo, as chaves privadas podem ser criptografadas, exigindo uma senha do usuário antes que elas possam ser usadas. No entanto, se o sinalizador CRYPT_VERIFYCONTEXT for especificado, o acesso às chaves privadas não será necessário e a interface do usuário poderá ser ignorada.

CRYPT_NEWKEYSET
Cria um novo contêiner de chave com o nome especificado por szContainer. Se szContainer for NULL, um contêiner de chaves com o nome padrão será criado.
CRYPT_MACHINE_KEYSET
Por padrão, chaves e contêineres de chave são armazenados como chaves de usuário. Para provedores base, isso significa que os contêineres de chave de usuário são armazenados no perfil do usuário. Um contêiner de chaves criado sem esse sinalizador por um administrador só pode ser acessado pelo usuário que cria o contêiner de chaves e um usuário com privilégios de administração.

Windows XP: Um contêiner de chaves criado sem esse sinalizador por um administrador só pode ser acessado pelo usuário que cria o contêiner de chaves e a conta do sistema local.

Um contêiner de chaves criado sem esse sinalizador por um usuário que não é um administrador só pode ser acessado pelo usuário que cria o contêiner de chaves e a conta do sistema local.

O sinalizador CRYPT_MACHINE_KEYSET pode ser combinado com todos os outros sinalizadores para indicar que o contêiner de chave de interesse é um contêiner de chave de computador e o CSP o trata como tal. Para provedores base, isso significa que as chaves são armazenadas localmente no computador que criou o contêiner de chaves. Se um contêiner de chave for um contêiner de computador, o sinalizador CRYPT_MACHINE_KEYSET deverá ser usado com todas as chamadas para CryptAcquireContext que fazem referência ao contêiner do computador. O contêiner de chave criado com CRYPT_MACHINE_KEYSET por um administrador só pode ser acessado por seu criador e por um usuário com privilégios de administrador, a menos que os direitos de acesso ao contêiner sejam concedidos usando CryptSetProvParam.

Windows XP: O contêiner de chave criado com CRYPT_MACHINE_KEYSET por um administrador só pode ser acessado por seu criador e pela conta do sistema local, a menos que os direitos de acesso ao contêiner sejam concedidos usando CryptSetProvParam.

O contêiner de chave criado com CRYPT_MACHINE_KEYSET por um usuário que não é um administrador só pode ser acessado por seu criador e pela conta do sistema local, a menos que os direitos de acesso ao contêiner sejam concedidos usando CryptSetProvParam.

O sinalizador CRYPT_MACHINE_KEYSET é útil quando o usuário está acessando de um serviço ou conta de usuário que não fez logon interativamente. Quando os contêineres de chave são criados, a maioria dos CSPs não cria automaticamente nenhum par de chaves pública/privada. Essas chaves devem ser criadas como uma etapa separada com a função CryptGenKey .

CRYPT_DELETEKEYSET
Exclua o contêiner de chaves especificado por szContainer. Se szContainer for NULL, o contêiner de chaves com o nome padrão será excluído. Todos os pares de chaves no contêiner de chaves também são destruídos.

Quando esse sinalizador é definido, o valor retornado em phProv é indefinido e, portanto, a função CryptReleaseContext não precisa ser chamada posteriormente.

CRYPT_SILENT
O aplicativo solicita que o CSP não exiba nenhuma interface do usuário (interface do usuário) para esse contexto. Se o CSP precisar exibir a interface do usuário para operar, a chamada falhará e o código de erro NTE_SILENT_CONTEXT será definido como o último erro. Além disso, se forem feitas chamadas para CryptGenKey com o sinalizador CRYPT_USER_PROTECTED com um contexto que foi adquirido com o sinalizador CRYPT_SILENT, as chamadas falharão e o CSP definirá NTE_SILENT_CONTEXT.

CRYPT_SILENT destina-se ao uso com aplicativos para os quais a interface do usuário não pode ser exibida pelo CSP.

CRYPT_DEFAULT_CONTAINER_OPTIONAL
Obtém um contexto para um CSP de cartão inteligente que pode ser usado para operações de hash e chave simétrica, mas não pode ser usado para qualquer operação que exija autenticação em um cartão inteligente usando um PIN. Esse tipo de contexto geralmente é usado para executar operações em um cartão inteligente vazio, como definir o PIN usando CryptSetProvParam. Esse sinalizador só pode ser usado com CSPs de cartão inteligente.

Windows Server 2003 e Windows XP: Não há suporte para esse sinalizador.

Retornar valor

Se a função for bem-sucedida, a função retornará diferente de zero (TRUE).

Se a função falhar, ela retornará zero (FALSE). Para obter informações de erro estendidas, chame GetLastError.

Os códigos de erro precedidos pelo NTE são gerados pelo CSP específico que está sendo usado. Alguns códigos de erro possíveis definidos em Winerror.h seguem.

Valor/código retornado Descrição
ERROR_BUSY
107L
Alguns CSPs definem esse erro se o valor do sinalizador CRYPT_DELETEKEYSET estiver definido e outro thread ou processo estiver usando esse contêiner de chave.
ERROR_FILE_NOT_FOUND
2L
O perfil do usuário não é carregado e não pode ser encontrado. Isso acontece quando o aplicativo representa um usuário, por exemplo, a conta IUSR_ComputerName .
ERROR_INVALID_PARAMETER
87L
Um dos parâmetros contém um valor que não é válido. Geralmente, esse é um ponteiro que não é válido.
ERROR_NOT_ENOUGH_MEMORY
8L
O sistema operacional ficou sem memória durante a operação.
NTE_BAD_FLAGS
0x80090009L
O parâmetro dwFlags tem um valor que não é válido.
NTE_BAD_KEY_STATE
0x8009000BL
A senha do usuário foi alterada desde que as chaves privadas foram criptografadas.
NTE_BAD_KEYSET
0x80090016L
Não foi possível abrir o contêiner de chaves. Uma causa comum desse erro é que o contêiner de chaves não existe. Para criar um contêiner de chaves, chame CryptAcquireContext usando o sinalizador CRYPT_NEWKEYSET. Esse código de erro também pode indicar que o acesso a um contêiner de chave existente foi negado. Os direitos de acesso ao contêiner podem ser concedidos pelo criador do conjunto de chaves usando CryptSetProvParam.
NTE_BAD_KEYSET_PARAM
0x8009001FL
O parâmetro szContainer ou szProvider é definido como um valor que não é válido.
NTE_BAD_PROV_TYPE
0x80090014L
O valor do parâmetro dwProvType está fora do intervalo. Todos os tipos de provedor devem ser de 1 a 999, inclusive.
NTE_BAD_SIGNATURE
0x80090006L
Não foi possível verificar a assinatura de DLL do provedor. A DLL ou a assinatura digital foram adulteradas.
NTE_EXISTS
0x8009000FL
O parâmetro dwFlags é CRYPT_NEWKEYSET, mas o contêiner de chave já existe.
NTE_KEYSET_ENTRY_BAD
0x8009001AL
O contêiner de chave szContainer foi encontrado, mas está corrompido.
NTE_KEYSET_NOT_DEF
0x80090019L
O provedor solicitado não existe.
NTE_NO_MEMORY
0x8009000EL
O CSP ficou sem memória durante a operação.
NTE_PROV_DLL_NOT_FOUND
0x8009001EL
O arquivo DLL do provedor não existe ou não está no caminho atual.
NTE_PROV_TYPE_ENTRY_BAD
0x80090018L
O tipo de provedor especificado por dwProvType está corrompido. Esse erro pode estar relacionado à lista CSP padrão do usuário ou à lista de CSP padrão do computador.
NTE_PROV_TYPE_NO_MATCH
0x8009001BL
O tipo de provedor especificado por dwProvType não corresponde ao tipo de provedor encontrado. Observe que esse erro só pode ocorrer quando szProvider especifica um nome CSP real.
NTE_PROV_TYPE_NOT_DEF
0x80090017L
Não existe nenhuma entrada para o tipo de provedor especificado por dwProvType.
NTE_PROVIDER_DLL_FAIL
0x8009001DL
O arquivo DLL do provedor não pôde ser carregado ou falhou ao inicializar.
NTE_SIGNATURE_FILE_BAD
0x8009001CL
Ocorreu um erro ao carregar a imagem do arquivo DLL, antes de verificar sua assinatura.

Comentários

O parâmetro szContainer especifica o nome do contêiner usado para manter a chave. Cada contêiner pode conter uma chave. Se você especificar o nome de um contêiner existente ao criar chaves, a nova chave substituirá uma anterior.

A combinação do nome do CSP e do nome do contêiner de chave identifica exclusivamente uma única chave no sistema. Se um aplicativo tentar modificar um contêiner de chaves enquanto outro aplicativo o estiver usando, um comportamento imprevisível poderá resultar.

Se você definir o parâmetro szContainer como NULL, o nome do contêiner de chave padrão será usado. Quando os CSPs de software da Microsoft são chamados dessa maneira, um novo contêiner é criado sempre que a função CryptAcquireContext é chamada. No entanto, CSPs diferentes podem se comportar de forma diferente nesse sentido. Em particular, um CSP pode ter um único contêiner padrão que é compartilhado por todos os aplicativos que acessam o CSP. Portanto, os aplicativos não devem usar o contêiner de chave padrão para armazenar chaves privadas. Em vez disso, evite o armazenamento de chaves passando o sinalizador CRYPT_VERIFYCONTEXT no parâmetro dwFlags ou use um contêiner específico do aplicativo que é improvável de ser usado por outro aplicativo.

Um aplicativo pode obter o nome do contêiner de chave em uso usando a função CryptGetProvParam para ler o valor PP_CONTAINER.

Por motivos de desempenho, recomendamos que você defina o parâmetro szContainer como NULL e o parâmetro dwFlags para CRYPT_VERIFYCONTEXT em todas as situações em que você não precisa de uma chave persistente. Em particular, considere definir o parâmetro szContainer como NULL e o parâmetro dwFlags como CRYPT_VERIFYCONTEXT para os seguintes cenários:

  • Você está criando um hash.
  • Você está gerando uma chave simétrica para criptografar ou descriptografar dados.
  • Você está derivando uma chave simétrica de um hash para criptografar ou descriptografar dados.
  • Você está verificando uma assinatura. É possível importar uma chave pública de um PUBLICKEYBLOB ou de um certificado usando CryptImportKey ou CryptImportPublicKeyInfo. Um contexto pode ser adquirido usando o sinalizador CRYPT_VERIFYCONTEXT se você planeja importar apenas a chave pública.
  • Você planeja exportar uma chave simétrica, mas não importá-la dentro do tempo de vida do contexto de criptografia. Um contexto pode ser adquirido usando o sinalizador CRYPT_VERIFYCONTEXT se você planeja importar apenas a chave pública para os dois últimos cenários.
  • Você está executando operações de chave privada, mas não está usando uma chave privada persistente armazenada em um contêiner de chaves.
Se você planeja executar operações de chave privada, a melhor maneira de adquirir um contexto é tentar abrir o contêiner. Se essa tentativa falhar com NTE_BAD_KEYSET, crie o contêiner usando o sinalizador CRYPT_NEWKEYSET .

Exemplos

O exemplo a seguir mostra a aquisição de um contexto criptográfico e o acesso a pares de chaves públicas/privadas em um contêiner de chaves. Se o contêiner de chave solicitado não existir, ele será criado.

Para obter um exemplo que inclui o contexto completo para este exemplo, consulte Exemplo de programa C: criando um contêiner de chave e gerando chaves. Para obter exemplos adicionais, consulte Exemplo de programa C: usando 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");
}

Observação

O cabeçalho wincrypt.h define CryptAcquireContext como um alias que seleciona automaticamente a versão ANSI ou Unicode dessa função com base na definição da constante de pré-processador UNICODE. Misturar o uso do alias neutro de codificação com código que não seja neutro em codificação pode levar a incompatibilidades que resultam em erros de compilação ou de runtime. Para obter mais informações, consulte Convenções para protótipos de função.

Requisitos

Requisito Valor
Cliente mínimo com suporte Windows XP [somente aplicativos da área de trabalho]
Servidor mínimo com suporte Windows Server 2003 [somente aplicativos da área de trabalho]
Plataforma de Destino Windows
Cabeçalho wincrypt.h
Biblioteca Advapi32.lib
DLL Advapi32.dll

Confira também

Cryptgenkey

Cryptgetprovparam

CryptReleaseContext

Funções do provedor de serviços

Problemas de threading com provedores de serviços criptográficos