Как добавить сертификат в магазин?

Я пытаюсь добавить сертификат в хранилище, но я новичок в этом. Я искал информацию о том, как установить сертификат в хранилище, не находя контекст сертификата из хранилища (у меня нет сертификата в магазине). Все, что я нашел, я использовал в коде ниже. Но похоже, что это не работает, и я не могу найти сертификат в магазине даже после сообщения о том, что сертификат был установлен.

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

Здесь я не получил никакой ошибки, и даже кажется, что он успешно установлен, но я ничего не нашел в хранилище сертификатов.

        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.";
        }

person Jessica    schedule 17.05.2021    source источник


Ответы (1)


Лучше создавать сертификат с помощью специальных инструментов, таких как makecert. , openssl и т. д. Затем, согласно Сериализация сертификатов вы можете добавить его в сертификат store.
Изменить:

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

потом

#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

введите здесь описание изображения

person YangXiaoPo    schedule 18.05.2021
comment
Спасибо за ответ. Я проверил ссылку, которую вы разместили, но похоже, что она не соответствует моей ситуации. У меня нет сертификатов в магазине, так как я могу найти какой-либо контекст с помощью CertEnumCertificatesInStore? А во-вторых, у меня уже есть файл .cer, который я получил из контейнера, поэтому мне не нужно его создавать. - person Jessica; 18.05.2021
comment
Я успешно добавил сертификат public_v2.crt в системное хранилище и хранилище файлов, и вы можете обратиться к моему обновленному ответу. - person YangXiaoPo; 18.05.2021
comment
спасибо за ваш ответ, но он не соответствует моим потребностям. У меня уже есть файл .cer и я не могу использовать любое другое расширение файла (если это имеет значение), кроме того, я не собираюсь использовать свой код в Windows, он для ОС Sailfish, поэтому у меня нет функций CreateFile или ReadFile. Я уже видел пример, похожий на ваш, по этой ссылке , но не подходит. Но, может быть, вы можете посоветовать, как я могу изменить свой код, чтобы он работал? - person Jessica; 18.05.2021
comment
Возможно, вам нужно сохранить изменение хранилища сертификатов, которое CertSaveStore в WinAPI. - person YangXiaoPo; 19.05.2021
comment
спасибо, я пробовал, но не получилось - person Jessica; 19.05.2021
comment
Во-первых, вы успешно добавляете сертификат в хранилище сертификатов на отдельной платформе, такой как Windows, используя файл .cer, чтобы проверить, все ли в порядке. - person YangXiaoPo; 19.05.2021