【问题标题】:How to add certificate in store?如何在商店中添加证书?
【发布时间】:2021-05-17 12:53:53
【问题描述】:

我正在尝试将证书添加到存储中,但我是新手。我一直在搜索有关如何安装证书以存储而不从存储中找到证书上下文的信息(我没有存储中的证书)。我发现的所有东西都在下面的代码中使用过。但它似乎不起作用,即使在安装了证书的消息之后我也无法在商店中找到证书。

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

【问题讨论】:

    标签: c++ winapi certificate cryptoapi wincrypt


    【解决方案1】:

    最好用makecertopenssl等专用工具创建证书,然后根据Serializing Certificates添加到证书存储中。
    编辑

    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
    

    【讨论】:

    • 感谢您的回复。我已经检查了您发布的链接,但似乎它不适合我的情况。我没有证书,所以如何使用CertEnumCertificatesInStore 找到任何上下文?第二,我已经有了从容器中获取的 .cer 文件,所以我不需要创建它。
    • 我已成功将public_v2.crt证书添加到系统存储和文件存储中,您可以参考我更新的答案。
    • 感谢您的回答,但它不符合我的需求。我已经有.cer 文件并且我不能使用任何其他文件扩展名(如果有问题的话),除了我不会在 Windows 中使用我的代码,它是用于 Sailfish 操作系统的,所以我没有 CreateFileReadFile职能。我已经从这个链接link 看到了与您类似的示例,但它不适合。但也许您可以就如何更改代码以使其正常工作提出一些建议?
    • 也许您需要在 WinAPI 中保存 CertSaveStore 的证书存储更改。
    • 首先,您使用.cer文件在单独的平台(例如Windows)上成功地将证书添加到证书存储区,以检查一切是否正常。
    猜你喜欢
    • 1970-01-01
    • 2014-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-24
    • 1970-01-01
    相关资源
    最近更新 更多