Ottieni certificato KeyContainerName per inizializzare CspParameters

1

Come posso ottenere il nome di un Key Container che è in una smart card richiesta per l'inizializzazione di CspParameters?

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

RSACryptoServiceProvider^ csp = gcnew RSACryptoServiceProvider(cspa);

Poiché i certificati delle smart card vengono installati automaticamente in un archivio di certificati personali, ho provato a cercare keyContainerName in X509Certificate2 e non sono riuscito a trovarlo lì.

Sono riuscito a trovare un nome contenitore di una delle chiavi al di fuori di C ++ usando certutils.exe, e in questo modo, ho appena inserito quel nome e sono riuscito a generare una firma digitale utilizzando il summenzionato RSACryptoServiceProvider. Funziona magnificamente. Cosa posso fare con altri certificati con cui il software potrebbe essere utilizzato? Non posso chiedere agli utenti di inserire manualmente il nome del contenitore.

Ma, da quello che ho capito, se non fornisco il nome del contenitore (lascialo vuoto), non funziona. Quindi ho bisogno di un modo per trovare / ottenere un nome di contenitore chiave per qualsiasi certificato in qualsiasi smart card all'interno del codice del programma.

Sfortunatamente, la maggior parte degli esempi che ho visto su Internet forniscono un nome di contenitore predefinito costante (come "esempio" o "test" - come qui link ), che è inutile nella vita reale.

    
posta Jenny D 24.02.2015 - 17:42
fonte

2 risposte

0

È questo quello che stai cercando? (scusate per il codice disordinato, sono un ragazzo di Java gettato nel codice 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;
        }
    }
    
risposta data 04.01.2016 - 03:09
fonte
-1

Dovrai sapere qualcosa sul certificato in questione ... nome soggetto o emittente, ad esempio, ottenere un handle sull'oggetto X509Certificate2. Da lì, è possibile ottenere il nome del contenitore univoco, generalmente ubicato in C: \ ProgramData \ Microsoft \ crypto \ RSA \ MachineKeys.

Questo è per c #, ma può essere adattato abbastanza facilmente al C ++.

            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);
            }

Per ottenere un handle, generalmente ricerca per nome soggetto (se un nome conosciuto):

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];
    
risposta data 30.12.2016 - 03:28
fonte

Leggi altre domande sui tag