Funzione CryptAcquireContextW (wincrypt.h)

Importante Questa API è deprecata. Il software nuovo ed esistente deve iniziare a usare le API cryptography next generation. Microsoft potrebbe rimuovere questa API nelle versioni future.
 
La funzione CryptAcquireContext viene usata per acquisire un handle in un contenitore di chiavi specifico all'interno di un provider di servizi di crittografia specifico. Questo handle restituito viene usato nelle chiamate alle funzioni CryptoAPI che usano il CSP selezionato.

Questa funzione tenta prima di tutto di trovare un provider di servizi di configurazione con le caratteristiche descritte nei parametri dwProvType e pszProvider . Se viene trovato il provider di servizi di configurazione, la funzione tenta di trovare un contenitore di chiavi all'interno del CSP che corrisponde al nome specificato dal parametro pszContainer . Per acquisire il contesto e il contenitore di chiavi di una chiave privata associata alla chiave pubblica di un certificato, usare CryptAcquireCertificatePrivateKey.

Con l'impostazione appropriata di dwFlags, questa funzione può anche creare ed eliminare contenitori di chiavi e può fornire l'accesso a un provider di servizi di configurazione con un contenitore di chiavi temporanee se l'accesso a una chiave privata non è necessario.

Sintassi

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

Parametri

[out] phProv

Puntatore a un handle di un provider di servizi di configurazione. Al termine dell'uso del provider di servizi di configurazione, rilasciare l'handle chiamando la funzione CryptReleaseContext .

[in] szContainer

Nome del contenitore di chiavi. Si tratta di una stringa con terminazione Null che identifica il contenitore di chiavi nel CSP. Questo nome è indipendente dal metodo usato per archiviare le chiavi. Alcuni provider di servizi di configurazione archiviano i contenitori di chiavi internamente (in hardware), alcuni usano il Registro di sistema e altri usano il file system. Nella maggior parte dei casi, quando dwFlags è impostato su CRYPT_VERIFYCONTEXT, pszContainer deve essere impostato su NULL. Tuttavia, per i provider di servizi di configurazione basati su hardware, ad esempio un provider di servizi di configurazione per smart card, è possibile accedere alle informazioni disponibili pubblicamente nel contenitore specificato.

Per altre informazioni sull'utilizzo del parametro pszContainer , vedere Osservazioni.

[in] szProvider

Stringa con terminazione Null contenente il nome del provider di servizi di configurazione da usare.

Se questo parametro è NULL, viene usato il provider predefinito dell'utente. Per altre informazioni, vedere Contesti del provider di servizi di crittografia. Per un elenco dei provider di crittografia disponibili, vedere Cryptographic Provider Names.For a list of available cryptographic providers providers, see Cryptographic Provider Names.

Un'applicazione può ottenere il nome del CSP in uso usando la funzione CryptGetProvParam per leggere il valore PP_NAME CSP nel parametro dwParam .

Il provider di servizi di configurazione predefinito può cambiare tra le versioni del sistema operativo. Per garantire l'interoperabilità su piattaforme del sistema operativo diverse, il provider di servizi di configurazione deve essere impostato in modo esplicito usando questo parametro anziché usare il provider di servizi di configurazione predefinito.

[in] dwProvType

Specifica il tipo di provider da acquisire. I tipi di provider definiti sono descritti in Tipi di provider di crittografia.

[in] dwFlags

Uno o più dei flag seguenti. Si noti che la maggior parte delle applicazioni deve impostare il flag CRYPT_VERIFYCONTEXT a meno che non debbano creare firme digitali o decrittografare i messaggi.

Valore Significato
CRYPT_VERIFYCONTEXT
Il chiamante non deve accedere alle chiavi private persistenti. Le app che usano chiavi temporanee o che eseguono solo l'hashing, la crittografia e la verifica della firma digitale devono impostare questo flag. Solo le applicazioni che creano firme o decrittografano i messaggi devono accedere a una chiave privata (e non devono impostare questo flag).

Per i provider di servizi di configurazione basati su file, quando questo flag è impostato, il parametro pszContainer deve essere impostato su NULL. L'applicazione non ha accesso alle chiavi private persistenti delle coppie di chiavi pubbliche/private. Quando questo flag è impostato, è possibile creare coppie di chiavi pubbliche/private temporanee , ma non persistenti.

Per i provider di servizi di configurazione basati su hardware, ad esempio un provider di servizi di configurazione della smart card, se il parametro pszContainer è NULL o vuoto, questo flag implica che non è necessario accedere ad alcuna chiave e che non deve essere presentata alcuna interfaccia utente all'utente. Questo modulo viene usato per connettersi al provider di servizi di configurazione per eseguire query sulle relative funzionalità, ma non per usare effettivamente le relative chiavi. Se il parametro pszContainer non è NULL e non è vuoto, questo flag implica l'accesso solo alle informazioni disponibili pubblicamente all'interno del contenitore specificato. Il provider di servizi di configurazione non deve richiedere un PIN. I tentativi di accesso alle informazioni private (ad esempio, la funzione CryptSignHash ) avranno esito negativo.

Quando viene chiamato CryptAcquireContext , molti provider di servizi di configurazione richiedono l'input dell'utente proprietario prima di concedere l'accesso alle chiavi private nel contenitore di chiavi. Ad esempio, le chiavi private possono essere crittografate, richiedendo una password dall'utente prima che possano essere usate. Tuttavia, se viene specificato il flag CRYPT_VERIFYCONTEXT , l'accesso alle chiavi private non è obbligatorio e l'interfaccia utente può essere ignorata.

CRYPT_NEWKEYSET
Crea un nuovo contenitore di chiavi con il nome specificato da pszContainer. Se pszContainer è NULL, viene creato un contenitore di chiavi con il nome predefinito.
CRYPT_MACHINE_KEYSET
Per impostazione predefinita, le chiavi e i contenitori di chiavi vengono archiviati come chiavi utente. Per i provider di base, ciò significa che i contenitori di chiavi utente vengono archiviati nel profilo dell'utente. È possibile accedere a un contenitore di chiavi creato senza questo flag da un amministratore solo dall'utente che crea il contenitore di chiavi e un utente con privilegi di amministrazione.

Windows XP: È possibile accedere a un contenitore di chiavi creato senza questo flag da un amministratore solo dall'utente che crea il contenitore di chiavi e l'account di sistema locale.

Un contenitore di chiavi creato senza questo flag da un utente che non è un amministratore può accedere solo dall'utente che crea il contenitore di chiavi e l'account di sistema locale.

Il flag CRYPT_MACHINE_KEYSET può essere combinato con tutti gli altri flag per indicare che il contenitore di chiavi di interesse è un contenitore di chiavi computer e il CSP lo considera come tale. Per i provider di base, ciò significa che le chiavi vengono archiviate localmente nel computer che ha creato il contenitore di chiavi. Se un contenitore di chiavi deve essere un contenitore di computer, il flag CRYPT_MACHINE_KEYSET deve essere usato con tutte le chiamate a CryptAcquireContext che fanno riferimento al contenitore del computer. Il contenitore di chiavi creato con CRYPT_MACHINE_KEYSET da un amministratore può essere accessibile solo dal creatore e da un utente con privilegi di amministratore, a meno che non vengano concessi diritti di accesso al contenitore tramite CryptSetProvParam.

Windows XP: Il contenitore di chiavi creato con CRYPT_MACHINE_KEYSET da un amministratore può essere accessibile solo dal creatore e dall'account di sistema locale, a meno che non vengano concessi diritti di accesso al contenitore usando CryptSetProvParam.

Il contenitore di chiavi creato con CRYPT_MACHINE_KEYSET da un utente che non è un amministratore può accedere solo dal creatore e dall'account di sistema locale, a meno che non vengano concessi diritti di accesso al contenitore tramite CryptSetProvParam.

Il flag CRYPT_MACHINE_KEYSET è utile quando l'utente accede da un servizio o da un account utente che non ha eseguito l'accesso in modo interattivo. Quando vengono creati i contenitori di chiavi, la maggior parte dei provider di servizi di configurazione non crea automaticamente coppie di chiavi pubbliche/private. Queste chiavi devono essere create come passaggio separato con la funzione CryptGenKey .

CRYPT_DELETEKEYSET
Eliminare il contenitore di chiavi specificato da pszContainer. Se pszContainer è NULL, il contenitore di chiavi con il nome predefinito viene eliminato. Tutte le coppie di chiavi nel contenitore delle chiavi vengono eliminate definitivamente.

Quando questo flag viene impostato, il valore restituito in phProv non è definito e pertanto la funzione CryptReleaseContext non deve essere chiamata in seguito.

CRYPT_SILENT
L'applicazione richiede che il CSP non visualizzi alcuna interfaccia utente per questo contesto. Se il provider di servizi di configurazione deve visualizzare l'interfaccia utente per il funzionamento, la chiamata ha esito negativo e il codice di errore NTE_SILENT_CONTEXT viene impostato come ultimo errore. Inoltre, se vengono effettuate chiamate a CryptGenKey con il flag CRYPT_USER_PROTECTED con un contesto acquisito con il flag CRYPT_SILENT, le chiamate hanno esito negativo e il CSP imposta NTE_SILENT_CONTEXT.

CRYPT_SILENT è destinato all'uso con le applicazioni per cui l'interfaccia utente non può essere visualizzata dal provider di servizi di configurazione.

CRYPT_DEFAULT_CONTAINER_OPTIONAL
Ottiene un contesto per un provider di servizi di configurazione della smart card che può essere usato per le operazioni di hashing e chiave simmetrica, ma non può essere usato per qualsiasi operazione che richiede l'autenticazione a una smart card usando un PIN. Questo tipo di contesto viene spesso usato per eseguire operazioni su una smart card vuota, ad esempio impostando il PIN usando CryptSetProvParam. Questo flag può essere usato solo con provider di servizi di configurazione della smart card.

Windows Server 2003 e Windows XP: Questo flag non è supportato.

Valore restituito

Se la funzione ha esito positivo, la funzione restituisce un valore diverso da zero (TRUE).

Se la funzione non riesce, restituisce zero (FALSE). Per informazioni sugli errori estesi, chiamare GetLastError.

I codici di errore preceduti dall'NTE vengono generati dal CSP specifico usato. Di seguito sono riportati alcuni codici di errore possibili definiti in Winerror.h.

Codice/valore restituito Descrizione
ERROR_BUSY
107L
Alcuni provider di servizi di configurazione impostano questo errore se il valore del flag CRYPT_DELETEKEYSET è impostato e un altro thread o processo usa questo contenitore di chiavi.
ERROR_FILE_NOT_FOUND
2L
Il profilo dell'utente non viene caricato e non è stato trovato. Ciò si verifica quando l'applicazione rappresenta un utente, ad esempio l'account IUSR_ComputerName .
ERROR_INVALID_PARAMETER
87L
Uno dei parametri contiene un valore non valido. Si tratta più spesso di un puntatore che non è valido.
ERROR_NOT_ENOUGH_MEMORY
8L
Il sistema operativo ha esaurito la memoria durante l'operazione.
NTE_BAD_FLAGS
0x80090009L
Il parametro dwFlags ha un valore non valido.
NTE_BAD_KEY_STATE
0x8009000BL
La password utente è stata modificata dopo la crittografia delle chiavi private.
NTE_BAD_KEYSET
0x80090016L
Impossibile aprire il contenitore di chiavi. Una causa comune di questo errore è che il contenitore di chiavi non esiste. Per creare un contenitore di chiavi, chiamare CryptAcquireContext usando il flag CRYPT_NEWKEYSET. Questo codice di errore può anche indicare che l'accesso a un contenitore di chiavi esistente è negato. I diritti di accesso al contenitore possono essere concessi dall'autore del set di chiavi usando CryptSetProvParam.
NTE_BAD_KEYSET_PARAM
0x8009001FL
Il parametro pszContainer o pszProvider è impostato su un valore non valido.
NTE_BAD_PROV_TYPE
0x80090014L
Il valore del parametro dwProvType non è compreso nell'intervallo. Tutti i tipi di provider devono essere compresi tra 1 e 999 inclusi.
NTE_BAD_SIGNATURE
0x80090006L
Impossibile verificare la firma della DLL del provider. La DLL o la firma digitale è stata manomessa.
NTE_EXISTS
0x8009000FL
Il parametro dwFlags è CRYPT_NEWKEYSET, ma il contenitore di chiavi esiste già.
NTE_KEYSET_ENTRY_BAD
0x8009001AL
Il contenitore di chiavi pszContainer è stato trovato ma è danneggiato.
NTE_KEYSET_NOT_DEF
0x80090019L
Il provider richiesto non esiste.
NTE_NO_MEMORY
0x8009000EL
Il provider di servizi di configurazione ha esaurito la memoria durante l'operazione.
NTE_PROV_DLL_NOT_FOUND
0x8009001EL
Il file DLL del provider non esiste o non è presente nel percorso corrente.
NTE_PROV_TYPE_ENTRY_BAD
0x80090018L
Il tipo di provider specificato da dwProvType è danneggiato. Questo errore può essere correlato all'elenco CSP predefinito dell'utente o all'elenco CSP predefinito del computer.
NTE_PROV_TYPE_NO_MATCH
0x8009001BL
Il tipo di provider specificato da dwProvType non corrisponde al tipo di provider trovato. Si noti che questo errore può verificarsi solo quando pszProvider specifica un nome CSP effettivo.
NTE_PROV_TYPE_NOT_DEF
0x80090017L
Non esiste alcuna voce per il tipo di provider specificato da dwProvType.
NTE_PROVIDER_DLL_FAIL
0x8009001DL
Impossibile caricare il file DLL del provider o non è stato possibile inizializzare.
NTE_SIGNATURE_FILE_BAD
0x8009001CL
Errore durante il caricamento dell'immagine del file DLL prima di verificarne la firma.

Commenti

Il parametro pszContainer specifica il nome del contenitore usato per contenere la chiave. Ogni contenitore può contenere una chiave. Se si specifica il nome di un contenitore esistente durante la creazione di chiavi, la nuova chiave sovrascriverà quella precedente.

La combinazione del nome CSP e del nome del contenitore di chiavi identifica in modo univoco una singola chiave nel sistema. Se un'applicazione tenta di modificare un contenitore di chiavi mentre un'altra applicazione la usa, può verificarsi un comportamento imprevedibile.

Se si imposta il parametro pszContainer su NULL, viene usato il nome del contenitore di chiavi predefinito. Quando i CSP software Microsoft vengono chiamati in questo modo, viene creato un nuovo contenitore ogni volta che viene chiamata la funzione CryptAcquireContext . Tuttavia, i diversi provider di servizi di configurazione possono comportarsi in modo diverso in questo senso. In particolare, un provider di servizi di configurazione può avere un singolo contenitore predefinito condiviso da tutte le applicazioni che accedono al provider di servizi di configurazione. Pertanto, le applicazioni non devono usare il contenitore di chiavi predefinito per archiviare le chiavi private. In alternativa, impedire l'archiviazione delle chiavi passando il flag CRYPT_VERIFYCONTEXT nel parametro dwFlags o usando un contenitore specifico dell'applicazione che probabilmente verrà usato da un'altra applicazione.

Un'applicazione può ottenere il nome del contenitore di chiavi in uso usando la funzione CryptGetProvParam per leggere il valore PP_CONTAINER.

Per motivi di prestazioni, è consigliabile impostare il parametro pszContainer su NULL e il parametro dwFlags su CRYPT_VERIFYCONTEXT in tutte le situazioni in cui non è necessaria una chiave persistente. In particolare, è consigliabile impostare il parametro pszContainer su NULL e il parametro dwFlags su CRYPT_VERIFYCONTEXT per gli scenari seguenti:

  • Si sta creando un hash.
  • Si sta generando una chiave simmetrica per crittografare o decrittografare i dati.
  • Si sta derivando una chiave simmetrica da un hash per crittografare o decrittografare i dati.
  • Si sta verificando una firma. È possibile importare una chiave pubblica da un PUBLICKEYBLOB o da un certificato usando CryptImportKey o CryptImportPublicKeyInfo. È possibile acquisire un contesto usando il flag CRYPT_VERIFYCONTEXT se si prevede di importare solo la chiave pubblica.
  • Si prevede di esportare una chiave simmetrica, ma non importarla entro la durata del contesto di crittografia. È possibile acquisire un contesto usando il flag CRYPT_VERIFYCONTEXT se si prevede di importare solo la chiave pubblica per gli ultimi due scenari.
  • Si eseguono operazioni di chiave privata, ma non si usa una chiave privata persistente archiviata in un contenitore di chiavi.
Se si prevede di eseguire operazioni di chiave privata, il modo migliore per acquisire un contesto consiste nel provare ad aprire il contenitore. Se questo tentativo ha esito negativo con NTE_BAD_KEYSET, creare il contenitore usando il flag CRYPT_NEWKEYSET .

Esempio

L'esempio seguente illustra l'acquisizione di un contesto di crittografia e l'accesso a coppie di chiavi pubbliche/private in un contenitore di chiavi. Se il contenitore di chiavi richiesto non esiste, viene creato.

Per un esempio che include il contesto completo per questo esempio, vedere Esempio di programma C: Creazione di un contenitore di chiavi e generazione di chiavi. Per altri esempi, vedere Esempio di programma C: Uso di 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");
}

Nota

L'intestazione wincrypt.h definisce CryptAcquireContext come alias che seleziona automaticamente la versione ANSI o Unicode di questa funzione in base alla definizione della costante del preprocessore UNICODE. La combinazione dell'utilizzo dell'alias indipendente dalla codifica con il codice che non è indipendente dalla codifica può causare mancate corrispondenze che generano errori di compilazione o di runtime. Per altre informazioni, vedere Convenzioni per i prototipi di funzioni.

Requisiti

Requisito Valore
Client minimo supportato Windows XP [solo app desktop]
Server minimo supportato Windows Server 2003 [solo app desktop]
Piattaforma di destinazione Windows
Intestazione wincrypt.h
Libreria Advapi32.lib
DLL Advapi32.dll

Vedi anche

CryptGenKey

CryptGetProvParam

CryptReleaseContext

Funzioni del provider di servizi

Problemi di threading con i provider di servizi di crittografia