Función CryptAcquireContextA (wincrypt.h)

Importante Esta API está en desuso. El software nuevo y existente debe empezar a usar las API cryptography Next Generation. Microsoft puede quitar esta API en futuras versiones.
 
La función CryptAcquireContext se usa para adquirir un identificador para un contenedor de claves determinado dentro de un proveedor de servicios criptográficos (CSP) determinado. Este identificador devuelto se usa en llamadas a funciones CryptoAPI que usan el CSP seleccionado.

Esta función intenta buscar primero un CSP con las características descritas en los parámetros dwProvType y pszProvider . Si se encuentra el CSP, la función intenta buscar un contenedor de claves dentro del CSP que coincida con el nombre especificado por el parámetro pszContainer . Para adquirir el contexto y el contenedor de claves de una clave privada asociada a la clave pública de un certificado, use CryptAcquireCertificatePrivateKey.

Con la configuración adecuada de dwFlags, esta función también puede crear y destruir contenedores de claves y puede proporcionar acceso a un CSP con un contenedor de claves temporal si no se requiere acceso a una clave privada.

Sintaxis

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

Parámetros

[out] phProv

Puntero a un identificador de UN CSP. Cuando haya terminado de usar el CSP, libere el identificador llamando a la función CryptReleaseContext .

[in] szContainer

Nombre del contenedor de claves. Se trata de una cadena terminada en null que identifica el contenedor de claves al CSP. Este nombre es independiente del método utilizado para almacenar las claves. Algunos CSP almacenan sus contenedores de claves internamente (en hardware), algunos usan el registro del sistema y otros usan el sistema de archivos. En la mayoría de los casos, cuando dwFlags se establece en CRYPT_VERIFYCONTEXT, pszContainer debe establecerse en NULL. Sin embargo, en el caso de los CSP basados en hardware, como un CSP de tarjeta inteligente, puede tener acceso a la información disponible públicamente en el contenedor especificado.

Para obtener más información sobre el uso del parámetro pszContainer , vea Comentarios.

[in] szProvider

Cadena terminada en null que contiene el nombre del CSP que se va a usar.

Si este parámetro es NULL, se usa el proveedor predeterminado del usuario. Para obtener más información, consulte Contextos del proveedor de servicios criptográficos. Para obtener una lista de proveedores criptográficos disponibles, consulte Nombres de proveedor criptográfico.

Una aplicación puede obtener el nombre del CSP en uso mediante la función CryptGetProvParam para leer el valor de CSP de PP_NAME en el parámetro dwParam .

El CSP predeterminado puede cambiar entre las versiones del sistema operativo. Para garantizar la interoperabilidad en diferentes plataformas del sistema operativo, el CSP debe establecerse explícitamente mediante este parámetro en lugar de usar el CSP predeterminado.

[in] dwProvType

Especifica el tipo de proveedor que se va a adquirir. Los tipos de proveedor definidos se describen en Tipos de proveedor criptográfico.

[in] dwFlags

Marcar valores. Este parámetro suele establecerse en cero, pero algunas aplicaciones establecen una o varias de las marcas siguientes.

Valor Significado
CRYPT_VERIFYCONTEXT
Esta opción está pensada para aplicaciones que usan claves efímeras o aplicaciones que no requieren acceso a claves privadas persistentes, como las aplicaciones que solo realizan la comprobación de hash, cifrado y firma digital . Solo las aplicaciones que crean firmas o descifran mensajes necesitan acceso a una clave privada. En la mayoría de los casos, se debe establecer esta marca.

En el caso de los CSP basados en archivos, cuando se establece esta marca, el parámetro pszContainer debe establecerse en NULL. La aplicación no tiene acceso a las claves privadas persistentes de pares de claves públicas y privadas. Cuando se establece esta marca, se pueden crear pares de claves públicas y privadas temporales, pero no se conservan.

En el caso de los CSP basados en hardware, como un CSP de tarjeta inteligente, si el parámetro pszContainer es NULL o está en blanco, esta marca implica que no se requiere acceso a ninguna clave y que no se debe presentar ninguna interfaz de usuario al usuario. Este formulario se usa para conectarse al CSP para consultar sus funcionalidades, pero no para usar realmente sus claves. Si el parámetro pszContainer no es NULL y no está en blanco, esta marca implica que solo se requiere el acceso a la información disponible públicamente dentro del contenedor especificado. El CSP no debe solicitar un PIN. Se producirá un error en los intentos de acceder a la información privada (por ejemplo, la función CryptSignHash ).

Cuando se llama a CryptAcquireContext , muchos CSP requieren la entrada del usuario propietario antes de conceder acceso a las claves privadas en el contenedor de claves. Por ejemplo, las claves privadas se pueden cifrar, lo que requiere una contraseña del usuario para poder usarlas. Sin embargo, si se especifica la marca CRYPT_VERIFYCONTEXT , no se requiere acceso a las claves privadas y se puede omitir la interfaz de usuario.

CRYPT_NEWKEYSET
Crea un nuevo contenedor de claves con el nombre especificado por pszContainer. Si pszContainer es NULL, se crea un contenedor de claves con el nombre predeterminado.
CRYPT_MACHINE_KEYSET
De forma predeterminada, las claves y los contenedores de claves se almacenan como claves de usuario. En el caso de los proveedores base, esto significa que los contenedores de claves de usuario se almacenan en el perfil del usuario. Solo el usuario que crea el contenedor de claves y un usuario con privilegios de administración puede tener acceso a un contenedor de claves creado sin esta marca.

Windows XP: Solo el usuario puede acceder a un contenedor de claves creado sin esta marca por parte del administrador al crear el contenedor de claves y la cuenta del sistema local.

Solo el usuario puede tener acceso a un contenedor de claves creado sin esta marca por parte de un usuario que no sea administrador al crear el contenedor de claves y la cuenta del sistema local.

La marca CRYPT_MACHINE_KEYSET se puede combinar con todas las demás marcas para indicar que el contenedor de claves de interés es un contenedor de claves de equipo y el CSP lo trata como tal. En el caso de los proveedores base, esto significa que las claves se almacenan localmente en el equipo que creó el contenedor de claves. Si un contenedor de claves va a ser un contenedor de equipos, se debe usar la marca CRYPT_MACHINE_KEYSET con todas las llamadas a CryptAcquireContext que hacen referencia al contenedor del equipo. El contenedor de claves creado con CRYPT_MACHINE_KEYSET por un administrador solo puede acceder a él y a un usuario con privilegios de administrador a menos que se concedan derechos de acceso al contenedor mediante CryptSetProvParam.

Windows XP: El contenedor de claves creado con CRYPT_MACHINE_KEYSET por un administrador solo puede acceder a él y a la cuenta del sistema local, a menos que se concedan derechos de acceso al contenedor mediante CryptSetProvParam.

El contenedor de claves creado con CRYPT_MACHINE_KEYSET por un usuario que no es un administrador solo puede acceder a él y a la cuenta del sistema local, a menos que se concedan derechos de acceso al contenedor mediante CryptSetProvParam.

La marca de CRYPT_MACHINE_KEYSET es útil cuando el usuario accede desde un servicio o una cuenta de usuario que no inicia sesión de forma interactiva. Cuando se crean contenedores de claves, la mayoría de los CSP no crean automáticamente ningún par de claves pública o privada. Estas claves se deben crear como un paso independiente con la función CryptGenKey .

CRYPT_DELETEKEYSET
Elimine el contenedor de claves especificado por pszContainer. Si pszContainer es NULL, se elimina el contenedor de claves con el nombre predeterminado. Todos los pares de claves del contenedor de claves también se destruyen.

Cuando se establece esta marca, el valor devuelto en phProv no está definido y, por tanto, la función CryptReleaseContext no se debe llamar después.

CRYPT_SILENT
La aplicación solicita que el CSP no muestre ninguna interfaz de usuario (UI) para este contexto. Si el CSP debe mostrar la interfaz de usuario para funcionar, se produce un error en la llamada y el código de error de NTE_SILENT_CONTEXT se establece como el último error. Además, si se realizan llamadas a CryptGenKey con la marca de CRYPT_USER_PROTECTED con un contexto que se ha adquirido con la marca CRYPT_SILENT, las llamadas producen un error y el CSP establece NTE_SILENT_CONTEXT.

CRYPT_SILENT está pensado para su uso con aplicaciones para las que el CSP no puede mostrar la interfaz de usuario.

CRYPT_DEFAULT_CONTAINER_OPTIONAL
Obtiene un contexto para un CSP de tarjeta inteligente que se puede usar para las operaciones de clave simétrica y hash, pero no se puede usar para ninguna operación que requiera autenticación en una tarjeta inteligente mediante un PIN. Este tipo de contexto se usa con más frecuencia para realizar operaciones en una tarjeta inteligente vacía, como establecer el PIN mediante CryptSetProvParam. Esta marca solo se puede usar con CSP de tarjeta inteligente.

Windows Server 2003 y Windows XP: Esta marca no se admite.

Valor devuelto

Si la función se ejecuta correctamente, la función devuelve un valor distinto de cero (TRUE).

Si se produce un error en la función, devuelve cero (FALSE). Para obtener información de error extendida, llame a GetLastError.

Los códigos de error precedidos por NTE se generan mediante el CSP en particular que se usa. Algunos códigos de error posibles definidos en Winerror.h siguen.

Código o valor devuelto Descripción
ERROR_BUSY
107L
Algunos CSP establecen este error si se establece el valor de marca de CRYPT_DELETEKEYSET y otro subproceso o proceso usa este contenedor de claves.
ERROR_FILE_NOT_FOUND
T2l
No se carga el perfil del usuario y no se encuentra. Esto sucede cuando la aplicación suplanta a un usuario, por ejemplo, la cuenta IUSR_ComputerName .
ERROR_INVALID_PARAMETER
87L
Uno de los parámetros contiene un valor que no es válido. Suele ser un puntero que no es válido.
ERROR_NOT_ENOUGH_MEMORY
8L
El sistema operativo se quedó sin memoria durante la operación.
NTE_BAD_FLAGS
0x80090009L
El parámetro dwFlags tiene un valor que no es válido.
NTE_BAD_KEY_STATE
0x8009000BL
La contraseña de usuario ha cambiado desde que se cifraron las claves privadas.
NTE_BAD_KEYSET
0x80090016L
No se pudo abrir el contenedor de claves. Una causa común de este error es que el contenedor de claves no existe. Para crear un contenedor de claves, llame a CryptAcquireContext mediante la marca CRYPT_NEWKEYSET. Este código de error también puede indicar que se deniega el acceso a un contenedor de claves existente. El creador del conjunto de claves puede conceder derechos de acceso al contenedor mediante CryptSetProvParam.
NTE_BAD_KEYSET_PARAM
0x8009001FL
El parámetro pszContainer o pszProvider se establece en un valor que no es válido.
NTE_BAD_PROV_TYPE
0x80090014L
El valor del parámetro dwProvType está fuera del intervalo. Todos los tipos de proveedor deben estar comprendidos entre 1 y 999, ambos incluidos.
NTE_BAD_SIGNATURE
0x80090006L
No se pudo comprobar la firma dll del proveedor. El archivo DLL o la firma digital se han alterado.
NTE_EXISTS
0x8009000FL
El parámetro dwFlags es CRYPT_NEWKEYSET, pero el contenedor de claves ya existe.
NTE_KEYSET_ENTRY_BAD
0x8009001AL
Se encontró el contenedor de claves pszContainer , pero está dañado.
NTE_KEYSET_NOT_DEF
0x80090019L
El proveedor solicitado no existe.
NTE_NO_MEMORY
0x8009000EL
El CSP se quedó sin memoria durante la operación.
NTE_PROV_DLL_NOT_FOUND
0x8009001EL
El archivo DLL del proveedor no existe o no está en la ruta de acceso actual.
NTE_PROV_TYPE_ENTRY_BAD
0x80090018L
El tipo de proveedor especificado por dwProvType está dañado. Este error puede relacionarse con la lista de CSP predeterminada del usuario o la lista de CSP predeterminada del equipo.
NTE_PROV_TYPE_NO_MATCH
0x8009001BL
El tipo de proveedor especificado por dwProvType no coincide con el tipo de proveedor encontrado. Tenga en cuenta que este error solo puede producirse cuando pszProvider especifica un nombre de CSP real.
NTE_PROV_TYPE_NOT_DEF
0x80090017L
No existe ninguna entrada para el tipo de proveedor especificado por dwProvType.
NTE_PROVIDER_DLL_FAIL
0x8009001DL
No se pudo cargar o no se pudo inicializar el archivo DLL del proveedor.
NTE_SIGNATURE_FILE_BAD
0x8009001CL
Error al cargar la imagen de archivo DLL antes de comprobar su firma.

Comentarios

El parámetro pszContainer especifica el nombre del contenedor que se usa para contener la clave. Cada contenedor puede contener una clave. Si especifica el nombre de un contenedor existente al crear claves, la nueva clave sobrescribirá una anterior.

La combinación del nombre de CSP y el nombre del contenedor de claves identifica de forma única una sola clave en el sistema. Si una aplicación intenta modificar un contenedor de claves mientras otra aplicación la usa, puede producirse un comportamiento impredecible.

Si establece el parámetro pszContainer en NULL, se usa el nombre del contenedor de claves predeterminado. Cuando se llama a los CSP de software de Microsoft de esta manera, se crea un nuevo contenedor cada vez que se llama a la función CryptAcquireContext . Sin embargo, los CSP diferentes pueden comportarse de forma diferente en este sentido. En concreto, un CSP puede tener un único contenedor predeterminado compartido por todas las aplicaciones que acceden al CSP. Por lo tanto, las aplicaciones no deben usar el contenedor de claves predeterminado para almacenar claves privadas. En su lugar, evite el almacenamiento de claves pasando la marca CRYPT_VERIFYCONTEXT en el parámetro dwFlags o use un contenedor específico de la aplicación que es poco probable que use otra aplicación.

Una aplicación puede obtener el nombre del contenedor de claves en uso mediante la función CryptGetProvParam para leer el valor de PP_CONTAINER.

Por motivos de rendimiento, se recomienda establecer el parámetro pszContainer en NULL y el parámetro dwFlags en CRYPT_VERIFYCONTEXT en todas las situaciones en las que no necesite una clave persistente. En concreto, considere la posibilidad de establecer el parámetro pszContainer en NULL y el parámetro dwFlags en CRYPT_VERIFYCONTEXT para los escenarios siguientes:

  • Está creando un hash.
  • Está generando una clave simétrica para cifrar o descifrar datos.
  • Deriva una clave simétrica de un hash para cifrar o descifrar datos.
  • Está comprobando una firma. Es posible importar una clave pública desde UN PUBLICKEYBLOB o desde un certificado mediante CryptImportKey o CryptImportPublicKeyInfo. Se puede adquirir un contexto mediante la marca CRYPT_VERIFYCONTEXT si solo tiene previsto importar la clave pública.
  • Tiene previsto exportar una clave simétrica, pero no importarla dentro de la duración del contexto criptográfico. Se puede adquirir un contexto mediante la marca CRYPT_VERIFYCONTEXT si solo tiene previsto importar la clave pública para los dos últimos escenarios.
  • Está realizando operaciones de clave privada, pero no usa una clave privada persistente almacenada en un contenedor de claves.
Si tiene previsto realizar operaciones de clave privada, la mejor manera de adquirir un contexto es intentar abrir el contenedor. Si se produce un error en este intento con NTE_BAD_KEYSET, cree el contenedor con la marca CRYPT_NEWKEYSET .

Ejemplos

En el ejemplo siguiente se muestra la adquisición de un contexto criptográfico y el acceso a pares de claves públicas y privadas en un contenedor de claves. Si el contenedor de claves solicitado no existe, se crea.

Para obtener un ejemplo que incluya el contexto completo de este ejemplo, vea Ejemplo de programa C: Creación de un contenedor de claves y generación de claves. Para obtener ejemplos adicionales, vea Ejemplo de programa C: uso de 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

El encabezado wincrypt.h define CryptAcquireContext como alias que selecciona automáticamente la versión ANSI o Unicode de esta función en función de la definición de la constante de preprocesador UNICODE. La combinación del uso del alias neutro de codificación con código que no es neutral de codificación puede provocar discrepancias que dan lugar a errores de compilación o en tiempo de ejecución. Para obtener más información, vea Convenciones para prototipos de función.

Requisitos

Requisito Value
Cliente mínimo compatible Windows XP [solo aplicaciones de escritorio]
Servidor mínimo compatible Windows Server 2003 [solo aplicaciones de escritorio]
Plataforma de destino Windows
Encabezado wincrypt.h
Library Advapi32.lib
Archivo DLL Advapi32.dll

Consulte también

CryptGenKey

CryptGetProvParam

CryptReleaseContext

Funciones del proveedor de servicios

Problemas de subprocesamiento con proveedores de servicios criptográficos