c++winapicertificatecryptoapiwincrypt

How to add certificate in store?


I am trying to add certificate to store, but I am new in it. I've been searching for information about how to install certificate to store without finding certificate context from store (I have no certificate in store). Everything I found I've been used in code below. But it seems like it doesn't work, and I can't find certificate in store even after message that certificate was installed.

static HCRYPTPROV hProv = 0;
static HCRYPTKEY hKey = 0;
static unsigned char *pbKeyBlob = nullptr;
static unsigned int cbKeyBlob;
static unsigned int cbCertBlob;
static unsigned char *pbCertBlob = nullptr;
LPCSTR szCont = "myCont";

    if(CryptAcquireContext(&hProv, szCont, nullptr, PROV_GOST_2012_256, 0))
    {
        qDebug() << "The key container \"%s\" has been acquired.\n" << szCont;
    }
    else
    {
        HandleError("Error during CryptAcquireContext.");
    }

    if(CryptGetUserKey(hProv, AT_KEYEXCHANGE, &hKey))
    {
        qDebug() << "The public key has been acquired. \n";
    }
    else
    {
        HandleError("Error during CryptGetUserKey public key.");
    }

    if(CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, nullptr, &cbKeyBlob))
    {
        qDebug() << "Size of the BLOB for the public key determined. \n";
    }
    else
    {
        HandleError("Error computing BLOB length.");
    }

    pbKeyBlob = static_cast<unsigned char*>(malloc(cbKeyBlob));
    if(!pbKeyBlob)
    {
        HandleError("Out of memory. \n");
    }

    if(CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, pbKeyBlob, &cbKeyBlob))
    {
        qDebug() << "Contents have been written to the BLOB. \n";
    }
    else
    {
        HandleError("Error during CryptExportKey.");
    }
    
    if(CryptGetKeyParam(hKey, KP_CERTIFICATE, nullptr, &cbCertBlob, 0))
    {
        pbCertBlob = static_cast<unsigned char*>(malloc(cbCertBlob));
        if(!pbCertBlob)
        {
            HandleError("Out of memory. \n");
        }

        szFileName = static_cast<char*>(malloc((strlen(szCont) + 5) * sizeof(char)));
        if(!szFileName)
        {
            HandleError("Out of memory. \n");
        }

        if(CryptGetKeyParam(hKey, KP_CERTIFICATE, pbCertBlob, &cbCertBlob, 0))
        {
            qDebug() << "Got certificate from container.\n";
        }
        else
        {
            HandleError("Error during CryptGetKeyParam.");
        }

        strcpy(szFileName, szCont);
        strcat(szFileName, ".cer");
        WriteBlobToFile(Cert, pbCertBlob, cbCertBlob);

        pDesiredCert = CertCreateCertificateContext(MY_ENCODING_TYPE, pbCertBlob, cbCertBlob);
    
        hCertStore = CertOpenSystemStore(0, "mRoot");

Here I didn't get any error and it even seems like it successfully installed, but I found nothing in certificate store.

        if (!CertAddEncodedCertificateToStore(hCertStore, MY_ENCODING_TYPE, pDesiredCert->pbCertEncoded, pDesiredCert->cbCertEncoded, CERT_STORE_ADD_NEW, &pDesiredCert))
        {
            qDebug() << "Cartificate installing failed.";
        }
        else
        {
            qDebug() << "Certificate was installed successfully to mRoot store.";
        }

Solution

  • It is better to create certificate with dedicated tools such as makecert, openssl, etc. Afterward, According to Serializing Certificates you can add it into a certificate store.
    Edit:

    makecert.exe -$ individual -n "CN=Test Signing Cert" -r C:\Users\public_v2.crt
    

    Then

    #pragma comment(lib, "crypt32.lib")
    
    #include <stdio.h>
    #include <windows.h>
    #include <Wincrypt.h>
    #define MY_ENCODING_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
    void MyHandleError(const char* s);
    
    int main()
    {
        // usage: CertExtract certpath
    
        char keyFile[] = "C:\\Users\\public_v2.crt";
        BYTE lp[65536];
    
        SECURITY_ATTRIBUTES sa;
        HANDLE hKeyFile;
        DWORD bytes;
    
        HCERTSTORE         hFileStore;
    
        PCCERT_CONTEXT  certContext;
        HCERTSTORE         hSystemStore;
    
        sa.nLength = sizeof(sa);
        sa.lpSecurityDescriptor = NULL;
        sa.bInheritHandle = FALSE;
    
        hKeyFile = CreateFile(keyFile, GENERIC_READ, FILE_SHARE_READ, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    
        if (hKeyFile) {
    
            if (ReadFile(hKeyFile, lp, GetFileSize(hKeyFile, NULL), &bytes, NULL) && bytes > 0) {
    
                certContext = CertCreateCertificateContext(X509_ASN_ENCODING, lp, bytes);
    
                if (certContext) {
    
                    printf("yay!");
    
                    /*if (hFileStore = CertOpenStore(
                        CERT_STORE_PROV_FILENAME,
                        MY_ENCODING_TYPE,
                        NULL,
                        0,
                        L"testStor.sto"))
                    {
                        printf("The file store is open. Continue.\n");
                    }
                    else
                    {
                        MyHandleError("The file store did not open.");
                    }*/
    
                    if (hSystemStore = CertOpenSystemStore(
                        0,
                        "CA"))
                    {
                        printf("The CA system store is open. Continue.\n");
                    }
                    else
                    {
                        MyHandleError("The first system store did not open.");
                    }
    
                    if (CertAddEncodedCertificateToStore(
                        hSystemStore,
                        MY_ENCODING_TYPE,
                        certContext->pbCertEncoded,
                        certContext->cbCertEncoded,
                        CERT_STORE_ADD_NEW,
                        &certContext))
                    {
                        printf("Another certificate is added to the file store.\n");
                    }
                    else
                    {
                        MyHandleError("The new certificate was not added to the "
                            "file store.");
                    }
    
                    /*if (CertSaveStore(
                    hFileStore,
                    MY_ENCODING_TYPE,
                    CERT_STORE_SAVE_AS_PKCS7,
                    CERT_STORE_SAVE_TO_FILENAME,
                    (void*)L"testStor.sto",
                    0))
                    {
                        printf("Another certificate is saved to the file store.\n");
                    }
                    else
                    {
                        MyHandleError("The new certificate was not added to the "
                        "file store.");
                    }*/
                    //-------------------------------------------------------------------
                    // Free memory.
    
                    CertCloseStore(hSystemStore, 0);
                    //CertCloseStore(hFileStore, 0);
                    printf("The program ran without error to the end.\n");
    
                    CertFreeCertificateContext(certContext);
                }
                else {
                    printf("Could not convert certificate to internal form\n");
                }
            }
            else {
                printf("Failed to read key file: %s\n", keyFile);
            }
        }
        else {
            printf("Failed to open key file: %s\n", keyFile);
        }
    
        CloseHandle(hKeyFile);
    
    
        return 0;
    }
    
    //-------------------------------------------------------------------
    //  This example uses the function MyHandleError, a simple error
    //  handling function, to print an error message to the standard  
    //  error (stderr) file and exit the program. 
    //  For most applications, replace this function with one 
    //  that does more extensive error reporting.
    
    void MyHandleError(const char* s)
    {
        fprintf(stderr, "An error occurred in running the program. \n");
        fprintf(stderr, "%s\n", s);
        fprintf(stderr, "Error number %x.\n", GetLastError());
        fprintf(stderr, "Program terminating. \n");
        exit(1);
    } // End of MyHandleError
    

    enter image description here