Verwendung und Problembehandlung für CryptAcquireContext()

Dieser Artikel enthält Informationen dazu, wann bestimmte Flags verwendet werden sollen, wenn Sie CryptAcquireContext aufrufen, und die Gründe für die Verwendung dieser Flags.

Gilt für: Windows Server 2012 R2
Ursprüngliche KB-Nummer: 238187

Zusammenfassung

Aufrufe der CryptAcquireContext Funktion können verschiedene Flags enthalten. Es ist wichtig zu wissen, wann diese Flags verwendet werden sollten. Dieser Artikel enthält Informationen dazu, wann bestimmte Flags verwendet werden sollen, wenn Sie aufrufen CryptAcquireContext , und die Gründe für die Verwendung dieser Flags.

Weitere Informationen

Vorgänge mit privaten Schlüsseln werden nicht ausgeführt

Wenn Sie keinen persistenten privaten Schlüssel verwenden, kann das CRYPT_VERIFYCONTEXT-Flag (0xF0000000) verwendet werden, wenn CryptAcquireContext aufgerufen wird. Dadurch wird CryptoAPI aufgefordert, einen Schlüsselcontainer im Arbeitsspeicher zu erstellen, der freigegeben wird, wenn CryptReleaseContext aufgerufen wird. Wenn dieses Flag verwendet wird, muss der pszContainer-Parameter NULL sein. Das CRYPT_VERIFYCONTEXT-Flag kann in den folgenden Szenarien verwendet werden:

  • Sie erstellen einen Hash.

  • Sie generieren einen symmetrischen Schlüssel zum Verschlüsseln oder Entschlüsseln von Daten.

  • Sie leiten einen symmetrischen Schlüssel von einem Hash ab, um Daten zu verschlüsseln oder zu entschlüsseln.

  • Sie überprüfen eine Signatur. Es ist möglich, einen öffentlichen Schlüssel aus einem PUBLICKEYBLOB oder aus einem Zertifikat mithilfe von CryptImportKey oder CryptImportPublicKeyInfo zu importieren.

  • Sie planen, einen symmetrischen Schlüssel zu exportieren, ihn aber nicht innerhalb der Lebensdauer des Kryptokontexts zu importieren.

    Hinweis

    Ein Kontext kann mithilfe des CRYPT_VERIFYCONTEXT-Flags abgerufen werden, wenn Sie nur den öffentlichen Schlüssel für die letzten beiden Szenarien importieren möchten.

  • Sie führen Vorgänge mit privaten Schlüsseln aus, verwenden jedoch keinen persistenten privaten Schlüssel, der in einem Schlüsselcontainer gespeichert ist.

Vorgänge mit privatem Schlüssel werden ausgeführt

Wenn Sie Vorgänge mit privaten Schlüsseln durchführen möchten, müssen Sie viele Probleme berücksichtigen.

Die beste Möglichkeit zum Abrufen eines Kontexts besteht darin, zu versuchen, den Container zu öffnen. Wenn dieser Versuch mit "NTE_BAD_KEYSET" fehlschlägt, erstellen Sie den Container mithilfe des flags CRYPT_NEWKEYSET.

Hinweis

Anwendungen dürfen den Standardschlüsselcontainer nicht verwenden, indem sie NULL für den Containernamen übergeben, um private Schlüssel zu speichern. Wenn mehrere Anwendungen denselben Container verwenden, kann eine Anwendung die Schlüssel ändern oder zerstören, die für eine andere Anwendung verfügbar sein müssen. Wenn Anwendungen Schlüsselcontainer mit einem eindeutigen Namen verwenden, verringert sich das Risiko, dass andere Anwendungen Schlüssel manipulieren, die für die ordnungsgemäße Funktion erforderlich sind.

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

Verwenden des CRYPT_MACHINE_KEYSET-Flags

Wenn Sie keine Vorgänge mit privaten Schlüsseln pro Benutzer ausführen und globale Vorgänge für private Schlüssel benötigen, sollten CRYPT_MACHINE_KEYSET verwendet werden. Mit dieser Methode wird das Private/Public-Schlüsselpaar auf Computerbasis erstellt. Einige spezifische Szenarien, in denen CRYPT_MACHINE_KEYSET verwendet werden sollten, sind:

  • Sie schreiben einen Dienst.
  • Ihre Komponente wird auf einer ASP-Seite (Active Server Pages) ausgeführt.
  • Ihre Komponente ist eine MtS-Komponente (Microsoft Transaction Server). In diesen Beispielen wird CRYPT_MACHINE_KEYSET verwendet, da der Sicherheitskontext, in dem die Anwendung ausgeführt wird, keinen Zugriff auf ein Benutzerprofil hat. Beispielsweise kann ein MTS-Client die Identität eines Benutzers annehmen, aber das Profil des Benutzers ist nicht verfügbar, da der Benutzer nicht angemeldet ist. Das gleiche gilt für eine Komponente, die unter einer ASP-Seite ausgeführt wird.

Bereitstellen des Zugriffs auf Ihren Container

Wenn ein Schlüsselcontainer erstellt wird, sind das lokale System und der Ersteller standardmäßig die einzigen Benutzer, die Zugriff auf den Container haben. Eine Ausnahme besteht darin, dass ein Administrator den Schlüsselcontainer erstellt. Das lokale System und alle anderen Administratoren haben Zugriff auf den Schlüsselcontainer. Jeder andere Sicherheitskontext kann den Container nicht öffnen.

Wenn Ihr Code unter mehreren Sicherheitskontexten ausgeführt wird, müssen Sie den entsprechenden Benutzern Zugriff auf Ihren Container gewähren.

Um die Sicherheit für den Container festzulegen, rufen Sie die Funktion CryptSetProvParam mit dem flag PP_KEYSET_SEC_DESCR auf, nachdem der Container erstellt wurde. Mit dieser Methode können Sie den Sicherheitsdeskriptor für den Container festlegen.

Der folgende Code veranschaulicht, wie CryptSetProvParam aufgerufen wird. Dies erfolgt unmittelbar nach der Erstellung des Schlüsselcontainers.

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

CryptAcquireContext-Fehler

Im Folgenden finden Sie die häufigsten Fehlercodes und mögliche Ursachen für den Fehler.

  • NTE_BAD_KEYSET (0x80090016)
    • Der Schlüsselcontainer ist nicht vorhanden.
    • Sie haben keinen Zugriff auf den Schlüsselcontainer.
    • Der geschützte Speicherdienst wird nicht ausgeführt.
  • NTE_EXISTS (0x8009000F)
    • Der Schlüsselcontainer ist bereits vorhanden, aber Sie versuchen, ihn zu erstellen. Wenn ein vorheriger Versuch, den Schlüssel zu öffnen, mit NTE_BAD_KEYSET fehlgeschlagen ist, bedeutet dies, dass der Zugriff auf den Schlüsselcontainer verweigert wird.
  • NTE_KEYSET_NOT_DEF (0x80090019)
    • Der Crypto Service Provider (CSP) ist möglicherweise nicht ordnungsgemäß eingerichtet. Die Verwendung von Regsvr32.exe für CSP-DLLs (Rsabase.dll oder Rsaenh.dll) kann das Problem je nach verwendetem Anbieter beheben.