Funzione CryptAcquireContextA (wincrypt.h)

Importante Questa API è deprecata. Il software nuovo e esistente deve iniziare a usare le API di nuova generazione di crittografia. Microsoft può rimuovere questa API nelle versioni future.
 
La funzione CryptAcquireContext viene usata per acquisire un handle a un determinato contenitore di chiavi 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 trovare un CSP con le caratteristiche descritte nei parametri dwProvType e pszProvider . Se il CSP viene trovato, la funzione tenta di trovare un contenitore di chiavi all'interno del CSP corrispondente 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 i contenitori delle chiavi e può fornire l'accesso a un provider di credenziali con un contenitore di chiavi temporaneo se l'accesso a una chiave privata non è obbligatorio.

Sintassi

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

Parametri

[out] phProv

Puntatore a un handle di un CSP. Al termine dell'uso del CSP, 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 chiave 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 rete basati su hardware, ad esempio un CSP smart card, è possibile accedere pubblicamente alle informazioni disponibili nel contenitore specifico.

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

[in] szProvider

Stringa con terminazione null contenente il nome del CSP da usare.

Se questo parametro è NULL, viene usato il provider predefinito dell'utente. Per altre informazioni, vedere Contesti del provider di servizi crittografici. Per un elenco dei provider di crittografia disponibili, vedere Nomi provider crittografici.

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

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

[in] dwProvType

Specifica il tipo di provider da acquisire. I tipi di provider definiti vengono illustrati nei tipi di provider crittografici.

[in] dwFlags

Contrassegna i valori. Questo parametro è in genere impostato su zero, ma alcune applicazioni impostano uno o più dei flag seguenti.

Valore Significato
CRYPT_VERIFYCONTEXT
Questa opzione è destinata alle applicazioni che usano chiavi temporanee o applicazioni che non richiedono l'accesso alle chiavi private persistenti, ad esempio le applicazioni che eseguono solo l'hashing, la crittografia e la verifica della firma digitale . Solo le applicazioni che creano firme o decrittografare i messaggi devono accedere a una chiave privata. Nella maggior parte dei casi, questo flag deve essere impostato.

Per i provider di servizi di rete 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 vengono mantenute.

Per i provider di servizi di rete basati su hardware, ad esempio un CSP per smart card, se il parametro pszContainer è NULL o vuoto, questo flag implica che non è necessario alcun accesso a alcuna chiave e che nessuna interfaccia utente deve essere presentata all'utente. Questo modulo viene usato per connettersi al CSP 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 che l'accesso solo alle informazioni disponibili pubblicamente all'interno del contenitore specificato è necessario. 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 delle 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 delle chiavi vengono archiviati come chiavi utente. Per i provider di base, ciò significa che i contenitori delle chiavi utente vengono archiviati nel profilo dell'utente. Un contenitore di chiavi creato senza questo flag da un amministratore può essere accessibile solo dall'utente che crea il contenitore chiave e un utente con privilegi di amministrazione.

Windows XP: Un contenitore di chiavi creato senza questo flag da un amministratore può essere accessibile solo dall'utente che crea il contenitore chiave e l'account di sistema locale.

Un contenitore di chiavi creato senza questo flag da un utente che non è un amministratore può essere accessibile solo dall'utente che crea il contenitore chiave 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 della chiave. Se un contenitore di chiavi deve essere un contenitore computer, il flag di 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 relativo creatore e da un utente con privilegi di amministratore, a meno che non vengano concessi diritti di accesso al contenitore usando CryptSetProvParam.

Windows XP: Il contenitore di chiavi creato con CRYPT_MACHINE_KEYSET da un amministratore può essere accessibile solo dal relativo 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ò essere accessibile solo dal relativo creatore e dall'account di sistema locale, a meno che non vengano concessi diritti di accesso al contenitore usando 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 delle chiavi, la maggior parte dei provider di servizi di sicurezza 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 chiave nel contenitore delle chiavi vengono eliminate anche.

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

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

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

CRYPT_DEFAULT_CONTAINER_OPTIONAL
Ottiene un contesto per un CSP smart card che può essere usato per le operazioni 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 i provider di servizi di rete smart card.

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

Valore restituito

Se la funzione ha esito positivo, la funzione restituisce non zero (TRUE).

Se la funzione ha esito negativo, restituisce zero (FALSE). Per informazioni sull'errore estese, chiamare GetLastError.

I codici di errore preceduti dall'NTE vengono generati dal particolare CSP usato. Alcuni codici di errore possibili definiti in Winerror.h seguono.

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 viene 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