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

Cet article fournit des informations sur le moment où utiliser des indicateurs spécifiques lorsque vous appelez CryptAcquireContext et les raisons de l’utilisation de ces indicateurs.

Version du produit d’origine :   Windows Server 2012 R2
Numéro de la base de connaissances initiale :   238187

Résumé

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

Informations supplémentaires

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é dans la 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 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 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 dans la durée de vie du contexte crypto.

    Notes

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

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

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

Si vous envisagez d’effectuer des opérations de clés privées, 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 .

Notes

Les applications ne doivent pas utiliser le conteneur de clé par défaut en transmettant null comme nom de conteneur pour 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 pour être disponible. Si les applications utilisent des conteneurs de clés avec un nom unique, le risque est réduit d’autres applications falsifiant des clés nécessaires pour une fonction correcte.

// 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és privées par utilisateur et si vous avez besoin d’opérations de clés privées globales, CRYPT_MACHINE_KEYSET doit être utilisé. Cette méthode crée la paire de clés publique/privée au niveau de chaque ordinateur. Voici quelques scénarios spécifiques dans lesquels les 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 MTS (Microsoft Transaction Server). Pour ces exemples, CRYPT_MACHINE_KEYSET est utilisé, car le contexte de sécurité dans lequel l’application est en cours d’exécution 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 est de même pour un composant qui s’exécute sous une page ASP.

Fourniture d’un accès à votre conteneur

Par défaut, lors de la création d’un conteneur de clés, le système local et le créateur sont les seuls utilisateurs qui ont accès au conteneur. L’exception à cette méthode 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. Pour plus d’informations, cliquez sur le numéro ci-dessous pour afficher l’article correspondant dans la base de connaissances Microsoft :

318825 modifications apportées au comportement de la liste de contrôle d’accès discrétionnaire (DACL) par défaut pour les administrateurs sur un système Windows XP

Si votre code s’exécute dans plus d’un contexte de sécurité, vous devez donner 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 une fois le conteneur créé. Cette méthode vous permet de définir le descripteur de sécurité sur le conteneur. Pour plus d’informations sur la manipulation des descripteurs de sécurité, cliquez sur le numéro ci-dessous pour afficher l’article correspondant dans la base de connaissances Microsoft :

106387 comment partager des objets de noyau entre des processus

Le code suivant montre comment appeler CryptSetProvParam. Cette opération est exécuté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 tentez de le créer. Si une précédente tentative 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) n’est peut-être pas configuré correctement. L’utilisation de Regsvr32.exe sur les dll des fournisseurs de services de chiffrement (Rsabase.dll ou Rsaenh.dll) peut résoudre le problème, en fonction du fournisseur utilisé.