Uso e solução de problemas cryptAcquireContext()

Este artigo fornece informações sobre quando usar sinalizadores específicos quando você chama CryptAcquireContext e os motivos para usar esses sinalizadores.

Aplica-se a: Windows Server 2012 R2
Número de KB original: 238187

Resumo

As chamadas para a CryptAcquireContext função podem incluir vários sinalizadores. É importante saber quando usar esses sinalizadores. Este artigo fornece informações sobre quando usar sinalizadores específicos quando você chama CryptAcquireContext e os motivos para usar esses sinalizadores.

Mais informações

Operações de chave privada não são executadas

Quando você não estiver usando uma chave privada persistente, o sinalizador CRYPT_VERIFYCONTEXT (0xF0000000) pode ser usado quando CryptAcquireContext é chamado. Isso informa a CryptoAPI para criar um contêiner de chave na memória que será lançado quando CryptReleaseContext for chamado. Quando esse sinalizador é usado, o parâmetro pszContainer deve ser NULL. O sinalizador CRYPT_VERIFYCONTEXT pode ser usado nos 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.

  • Você planeja exportar uma chave simétrica, mas não importá-la no tempo de vida do contexto de criptografia.

    Observação

    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 chave.

Operações de chave privada são executadas

Se você planeja executar operações de chave privada, há muitos problemas que você deve considerar.

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.

Observação

Os aplicativos não devem usar o contêiner de chave padrão passando NULL para o nome do contêiner armazenar chaves privadas. Quando vários aplicativos usam o mesmo contêiner, um aplicativo pode alterar ou destruir as chaves que outro aplicativo precisa ter disponíveis. Se os aplicativos usarem contêineres de chave com um nome exclusivo, o risco será reduzido de outros aplicativos adulterarem chaves necessárias para a função adequada.

// Acquire Context of container that is unique to each user.
if (!CryptAcquireContext(&hProv,  
 "Container",  
 NULL,  
 PROV_RSA_FULL,  
 0))
{
 if (GetLastError() == NTE_BAD_KEYSET)
 {
 if (!CryptAcquireContext(&hProv,  
 "Container",  
 NULL,  
 PROV_RSA_FULL,  
 CRYPT_NEWKEYSET))
 {
 // Error ...
 }
 }
}

// Or, acquire Context of container that is shared across the machine.
if (!CryptAcquireContext(&hProv,  
 "Container",  
 NULL,  
 PROV_RSA_FULL,  
 CRYPT_MACHINE_KEYSET))
{
 if (GetLastError() == NTE_BAD_KEYSET)
 {
 if (!CryptAcquireContext(&hProv,  
 "Container",  
 NULL,  
 PROV_RSA_FULL,  
 CRYPT_NEWKEYSET|CRYPT_MACHINE_KEYSET)
 {
 // Error ...
 }
 }
}

Usando o sinalizador CRYPT_MACHINE_KEYSET

Se você não estiver executando operações de chave privada por usuário e precisar de operações de chave privada global, CRYPT_MACHINE_KEYSET deverá ser usado. Esse método cria o par de chaves privada/pública por computador. Alguns cenários específicos em que CRYPT_MACHINE_KEYSET devem ser usados são:

  • Você está escrevendo um serviço.
  • Seu componente está em execução em uma página ASP (Páginas do Servidor Ativo).
  • Seu componente é um componente MTS (Microsoft Transaction Server). Para esses exemplos, CRYPT_MACHINE_KEYSET é usado porque o contexto de segurança em que o aplicativo está em execução não tem acesso a um perfil de usuário. Por exemplo, um cliente MTS pode representar um usuário, mas o perfil do usuário não está disponível porque o usuário não está conectado. O mesmo é verdadeiro para um componente que está em execução em uma página ASP.

Fornecendo acesso ao seu contêiner

Por padrão, quando um contêiner de chave é criado, o sistema local e o criador são os únicos usuários que têm acesso ao contêiner. A exceção a isso é quando um administrador cria o contêiner de chave. O sistema local e todos os outros administradores terão acesso ao contêiner de chave. Qualquer outro contexto de segurança não pode abrir o contêiner.

Se o código for executado em mais de um contexto de segurança, você deverá dar aos usuários apropriados acesso ao seu contêiner.

Para definir a segurança no contêiner, chame a função CryptSetProvParam com o sinalizador PP_KEYSET_SEC_DESCR após a criação do contêiner. Esse método permite que você defina o descritor de segurança no contêiner.

O código a seguir demonstra como chamar CryptSetProvParam. Isso é feito imediatamente após a criação do contêiner de chave.

// Acquire Context  
if (!CryptAcquireContext(&hProv,  
 "Container",  
 NULL,  
 PROV_RSA_FULL,  
 0))
{
 if (GetLastError() == NTE_BAD_KEYSET)
 {
 if (!CryptAcquireContext(&hProv,  
 "Container",  
 NULL,  
 PROV_RSA_FULL,  
 CRYPT_NEWKEYSET))
 {
 // Error ...
 }

// Create Security Descriptor (pSD)...

// Set the Security Descriptor on the container
 if (!CryptSetProvParam(hProv,
 PP_KEYSET_SEC_DESCR,
 pSD,
 DACL_SECURITY_INFORMATION))
 {
 // Error ...
 }
 }
}

Erros de CryptAcquireContext

A seguir estão os códigos de erro mais comuns e os possíveis motivos para o erro.

  • NTE_BAD_KEYSET (0x80090016)
    • O contêiner de chaves não existe.
    • Você não tem acesso ao contêiner de chaves.
    • O Serviço de Armazenamento Protegido não está em execução.
  • NTE_EXISTS (0x8009000F)
    • O contêiner de chave já existe, mas você está tentando criá-lo. Se uma tentativa anterior de abrir a chave falhou com NTE_BAD_KEYSET, isso implica que o acesso ao contêiner de chave será negado.
  • NTE_KEYSET_NOT_DEF (0x80090019)
    • O CSP (Provedor de Serviços de Criptografia) pode não ser configurado corretamente. O uso de Regsvr32.exe em DLLs CSP (Rsabase.dll ou Rsaenh.dll) pode corrigir o problema, dependendo do provedor ser usado.