Obtención del certificado KeyContainerName para inicializar CspParameters

1

¿Cómo puedo obtener el nombre de un contenedor de claves que se encuentra en una tarjeta inteligente requerida para la inicialización de parámetros de Csp?

CspParameters^ cspa = gcnew CspParameters(ProviderType, ProviderName, keyContainerName, cryptoSecurityKey, securityString);

RSACryptoServiceProvider^ csp = gcnew RSACryptoServiceProvider(cspa);

Como los certificados de tarjetas inteligentes se instalan automáticamente en un almacén de certificados personales, he intentado buscar keyContainerName en X509Certificate2 y no lo encontré allí.

Logré encontrar un nombre de contenedor de una de las claves fuera de C ++ usando certutils.exe, y de esa manera, acabo de ingresar ese nombre y logré generar una firma digital usando el RSACryptoServiceProvider mencionado anteriormente. Funciona a la perfección. ¿Qué puedo hacer con otros certificados con los que se podría usar el software? No puedo pedir a los usuarios que ingresen el nombre del contenedor manualmente.

Pero, por lo que entiendo, si no proporciono el nombre del contenedor (lo dejo vacío), no funciona. Así que necesito una forma de encontrar / obtener un nombre de contenedor clave para cualquier certificado en cualquier tarjeta inteligente dentro del código del programa.

Desafortunadamente, la mayoría de los ejemplos que he visto en Internet proporcionan un nombre de contenedor predefinido constante (como "ejemplo" o "prueba", como aquí enlace ), que es inútil en la vida real.

    
pregunta Jenny D 24.02.2015 - 17:42
fuente

2 respuestas

0

¿Esto es lo que estás buscando? (perdón por el código desordenado, soy un tipo de Java que está incluido en el código VC ++)

    HCRYPTPROV hProv = NULL;
    DWORD status;

    if (FALSE == CryptAcquireContext(
        &hProv, 
        NULL, 
        MS_SCARD_PROV, 
        PROV_RSA_FULL, 
        CRYPT_MACHINE_KEYSET | CRYPT_SILENT)
    ){
        status = GetLastError();
    } else {
        PBYTE pbData = (PBYTE)Alloc(256);  // formally, you should check the max size
        DWORD tmp = 256;
        PDWORD pdwDataLen = &tmp;
        status = 0;
        bool is_first = TRUE;
        // PP_ENUMCONTAINERS does an enumeration over all containers available to the MS_SCARD_PROV crypto provider 
        // (which should be just all containers on the smartcard in case of single smartcard and single reader)
        while (status == 0) {
            if (FALSE == CryptGetProvParam(hProv, PP_ENUMCONTAINERS, pbData, pdwDataLen, (is_first ? CRYPT_FIRST : CRYPT_NEXT)))
            {
                status = GetLastError();
                //__leave;
            }

            OutputDebugStringA((LPSTR)pbData); // or std::cout in a console application
            OutputDebugStringA("\n");
            is_first = FALSE;
        }
    }
    
respondido por el Martin Pecka 04.01.2016 - 03:09
fuente
-1

Tendrá que saber algo sobre el certificado en cuestión ... nombre del sujeto o emisor, por ejemplo, obtenga un identificador del objeto X509Certificate2 Desde allí, puede obtener el nombre único del contenedor, que generalmente se encuentra en C: \ ProgramData \ Microsoft \ crypto \ RSA \ MachineKeys.

Esto es para c #, pero se puede adaptar para C ++ con la suficiente facilidad.

            try
            {
                RSACryptoServiceProvider rsa = cert.PrivateKey as RSACryptoServiceProvider;

                if (rsa != null)
                {
                    string keyfilepath = FindKeyLocation(rsa.CspKeyContainerInfo.UniqueKeyContainerName);

                    string fullPrivateKeyPath = (keyfilepath + "\" + rsa.CspKeyContainerInfo.UniqueKeyContainerName);

                    //Inform the user of the specific privatekey path.
                    Console.WriteLine(fullPrivateKeyPath);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception occurred while trying to decrypt rsa key and find locaiton in file system:" + ex);
            }

Para obtener un identificador, generalmente busco por nombre de sujeto (si es un nombre conocido):

X509Certificate2Collection CACerts = castore.Certificates.Find(X509FindType.FindBySubjectName, "Test-Certificate-Authority", true);
                        if (CACerts.Count <= 0)
                        {
                            MessageBox.Show("No existing Certificate Authority was found on this machine. Please either import one or select 'no' to generate a new one.");
                            return;
                        }
                        ca2 = CACerts[0];
    
respondido por el mumbles 30.12.2016 - 03:28
fuente

Lea otras preguntas en las etiquetas