Utilisation et résolution des problèmes de CryptAcquireContext()

Cet article fournit des informations sur l’utilisation d’indicateurs spécifiques lorsque vous appelez CryptAcquireContext et les raisons de l’utilisation de ces indicateurs.

S’applique à : Windows Server 2012 R2
Numéro de la base de connaissances d’origine : 238187

Résumé

Les appels à la CryptAcquireContext fonction peuvent inclure différents indicateurs. Il est important de savoir quand utiliser ces indicateurs. Cet article fournit des informations sur l’utilisation d’indicateurs spécifiques lorsque vous appelez CryptAcquireContext et les raisons de l’utilisation de ces indicateurs.

Plus d’informations

Les opérations de clé privée ne sont pas effectuées

Lorsque vous n’utilisez pas de clé privée persistante, l’indicateur CRYPT_VERIFYCONTEXT (0xF0000000) peut être utilisé lorsque CryptAcquireContext est appelé. Cela indique à CryptoAPI de créer un conteneur de clé en mémoire qui sera libéré lors de l’appel de CryptReleaseContext. Lorsque cet indicateur est utilisé, le paramètre pszContainer doit être NULL. L’indicateur CRYPT_VERIFYCONTEXT peut être utilisé dans les scénarios suivants :

  • Vous créez un hachage.

  • Vous générez une clé symétrique pour chiffrer ou déchiffrer des données.

  • Vous dérivez une clé symétrique à partir d’un hachage pour chiffrer ou déchiffrer des données.

  • Vous vérifiez une signature. Il est possible d’importer une clé publique à partir d’un ÉLÉMENT PUBLICKEYBLOB ou d’un certificat à l’aide de CryptImportKey ou de CryptImportPublicKeyInfo.

  • Vous envisagez d’exporter une clé symétrique, mais pas de l’importer pendant la durée de vie du contexte de chiffrement.

    Remarque

    Un contexte peut être acquis à l’aide de l’indicateur CRYPT_VERIFYCONTEXT si vous envisagez uniquement d’importer la clé publique pour les deux derniers scénarios.

  • Vous effectuez des opérations de clé privée, mais vous n’utilisez pas de clé privée persistante stockée dans un conteneur de clés.

Les opérations de clé privée sont effectuées

Si vous envisagez d’effectuer des opérations de clé privée, vous devez prendre en compte de nombreux problèmes.

La meilleure façon d’acquérir un contexte consiste à essayer d’ouvrir le conteneur. Si cette tentative échoue avec « NTE_BAD_KEYSET », créez le conteneur à l’aide de l’indicateur CRYPT_NEWKEYSET.

Remarque

Les applications ne doivent pas utiliser le conteneur de clés par défaut en passant la valeur NULL pour le nom du conteneur afin de stocker les clés privées. Lorsque plusieurs applications utilisent le même conteneur, une application peut modifier ou détruire les clés dont une autre application a besoin. Si les applications utilisent des conteneurs de clés avec un nom unique, le risque est réduit que d’autres applications falsifient les clés nécessaires au bon fonctionnement.

// 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 ...
 }
 }
}

Utilisation de l’indicateur CRYPT_MACHINE_KEYSET

Si vous n’effectuez pas d’opérations de clé privée par utilisateur et que vous avez besoin d’opérations de clé privée globales, vous devez utiliser CRYPT_MACHINE_KEYSET. Cette méthode crée la paire de clés privée/publique sur une base par ordinateur. Voici quelques scénarios spécifiques dans lesquels CRYPT_MACHINE_KEYSET doivent être utilisés :

  • Vous écrivez un service.
  • Votre composant s’exécute sous une page ASP (Active Server Pages).
  • Votre composant est un composant Microsoft Transaction Server (MTS). Pour ces exemples, CRYPT_MACHINE_KEYSET est utilisé, car le contexte de sécurité dans lequel l’application s’exécute n’a pas accès à un profil utilisateur. Par exemple, un client MTS peut emprunter l’identité d’un utilisateur, mais le profil de l’utilisateur n’est pas disponible, car l’utilisateur n’est pas connecté. Il en va de même pour un composant qui s’exécute sous une page ASP.

Fournir l’accès à votre conteneur

Par défaut, lorsqu’un conteneur de clé est créé, le système local et le créateur sont les seuls utilisateurs qui ont accès au conteneur. L’exception à cela est lorsqu’un administrateur crée le conteneur de clé. Le système local et tous les autres administrateurs auront accès au conteneur de clé. Tout autre contexte de sécurité ne peut pas ouvrir le conteneur.

Si votre code s’exécute dans plusieurs contextes de sécurité, vous devez accorder aux utilisateurs appropriés l’accès à votre conteneur.

Pour définir la sécurité sur le conteneur, appelez la fonction CryptSetProvParam avec l’indicateur PP_KEYSET_SEC_DESCR après la création du conteneur. Cette méthode vous permet de définir le descripteur de sécurité sur le conteneur.

Le code suivant montre comment appeler CryptSetProvParam. Cette opération est effectuée immédiatement après la création du conteneur de clé.

// 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 ...
 }
 }
}

Erreurs CryptAcquireContext

Voici les codes d’erreur les plus courants et les raisons possibles de l’erreur.

  • NTE_BAD_KEYSET (0x80090016)
    • Le conteneur de clé n’existe pas.
    • Vous n’avez pas accès au conteneur de clé.
    • Le service de stockage protégé n’est pas en cours d’exécution.
  • NTE_EXISTS (0x8009000F)
    • Le conteneur de clé existe déjà, mais vous essayez de le créer. Si une tentative précédente d’ouverture de la clé a échoué avec NTE_BAD_KEYSET, cela signifie que l’accès au conteneur de clé est refusé.
  • NTE_KEYSET_NOT_DEF (0x80090019)
    • Le fournisseur de services de chiffrement (CSP) peut ne pas être configuré correctement. L’utilisation de Regsvr32.exe sur les DLL CSP (Rsabase.dll ou Rsaenh.dll) peut résoudre le problème, selon le fournisseur utilisé.