如何使用 win32 以编程方式提取存储在证书存储中的证书的公钥

问题描述 投票:0回答:1

我已将 crt 文件导入到本地计算机中的个人证书中。 enter image description here

我可以使用 MMC 使用 Base 64 编码的 X509 .CER 选项提取相同的公钥。

我的目标是使用 win32 api 以编程方式获取此信息。

到目前为止,我已尝试过以下操作,但存储在 base64Cert 中的数据与公钥不匹配。

关于我可以尝试获取正确数据的任何想法吗?

HCERTSTORE hCertStore;
PCCERT_CONTEXT pCertContext = NULL;


if (!(hCertStore = CertOpenStore(
    CERT_STORE_PROV_SYSTEM,
    MY_ENCODING_TYPE,
    NULL,
    CERT_SYSTEM_STORE_LOCAL_MACHINE,
    L"MY")))
{
    std::cout<<"The MY system store did not open."<< std::endl;
}



while (pCertContext = CertEnumCertificatesInStore(
    hCertStore,
    pCertContext))
{
    LPTSTR pszString;
    LPTSTR pszName;
    DWORD cbSize;
    CERT_BLOB blobEncodedName;

    PBYTE pbPKEY = NULL;
    DWORD iPKEYSize;



    bool ret = CryptDecodeObjectEx(X509_ASN_ENCODING,
        RSA_CSP_PUBLICKEYBLOB,
        pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
        pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
        CRYPT_ENCODE_ALLOC_FLAG,
        NULL,
        &pbPKEY,
        &iPKEYSize);

    CERT_CONTEXT certcontext;
    certcontext.pbCertEncoded = pbPKEY;
    certcontext.cbCertEncoded = iPKEYSize;

    DWORD dwData;
    if (!CryptBinaryToStringA(certcontext.pbCertEncoded, certcontext.cbCertEncoded, CRYPT_STRING_BASE64HEADER, nullptr, &dwData))
    {
        std::cout << "error \n";
    }
    std::string base64Cert(dwData, '\0');
    CryptBinaryToStringA(certcontext.pbCertEncoded, certcontext.cbCertEncoded, CRYPT_STRING_BASE64HEADER, &base64Cert[0], &dwData);
    
    std::cout << base64Cert << "\n";
    
}
windows winapi ssl-certificate
1个回答
0
投票

您不需要解码

pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey
但需要编码
pCertContext->pCertInfo->SubjectPublicKeyInfo

template <typename T> 
T HR(HRESULT& hr, T t)
{
    hr = t ? NOERROR : GetLastError();
    return t;
}

HRESULT mm(PCSTR psz)
{
    ULONG cch = (ULONG)strlen(psz);
    if (cch > 32*2)
    {
        return ERROR_INVALID_PARAMETER;
    }

    CRYPT_HASH_BLOB hash {};

    HRESULT hr;

    while(HR(hr, CryptStringToBinaryA(psz, cch, CRYPT_STRING_HEX, hash.pbData, &hash.cbData, 0, 0)))
    {
        if (hash.pbData)
        {
            if (HCERTSTORE hCertStore = HR(hr, CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, 
                CERT_STORE_OPEN_EXISTING_FLAG|CERT_STORE_READONLY_FLAG|CERT_SYSTEM_STORE_CURRENT_USER, L"My")))
            {
                PCCERT_CONTEXT pCertContext = HR(hr, CertFindCertificateInStore(hCertStore, 0, 0, CERT_FIND_HASH, &hash, 0));
                
                CertCloseStore(hCertStore, 0);

                if (pCertContext)
                {
                    PBYTE pb = 0;
                    ULONG cb = 0;

                    if (HR(hr, CryptEncodeObjectEx(X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO, 
                        &pCertContext->pCertInfo->SubjectPublicKeyInfo, 
                        CRYPT_ENCODE_ALLOC_FLAG|CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG, 0, &pb, &cb)))
                    {
                        cch = 0, psz = 0;
                        PSTR buf = 0;
                        int len = 0;

                        static const char _____[] = "-----";
                        static const char PUBLIC_KEY[] = " PUBLIC KEY";
                        static const char BEGIN[] = "BEGIN";
                        static const char END[] = "END";
                        static const char fmt[] = "%s%s%s%s\r\n";

#define LEN_OF(s) (_countof(s) - 1)

                        enum {
                            cch_prefix = LEN_OF(_____)*2 + LEN_OF(PUBLIC_KEY) + LEN_OF(BEGIN) + 2,
                            cch_suffix = LEN_OF(_____)*2 + LEN_OF(PUBLIC_KEY) + LEN_OF(END) + 2
                        };

                        while (HR(hr, CryptBinaryToStringA(pb, cb, CRYPT_STRING_BASE64, const_cast<PSTR>(psz), &cch)))
                        {
                            if (psz)
                            {
                                cch += len;

                                if (0 < (len = sprintf_s(buf + cch, cch_suffix + 1, fmt, _____, END, PUBLIC_KEY, _____)))
                                {
                                    cch += len;

                                    do 
                                    {
                                        len = min(0x80, cch);
                                        DbgPrint("%.*s", len, buf);

                                    } while (buf += len, cch -= len);
                                }
                                else
                                {
                                    hr = ERROR_INTERNAL_ERROR;
                                }

                                break;
                            }

                            buf = (PSTR)alloca(cch + cch_suffix + cch_prefix);

                            len = sprintf_s(buf, cch_prefix + 1, fmt, _____, BEGIN, PUBLIC_KEY, _____);

                            if (0 >= len)
                            {
                                hr = ERROR_INTERNAL_ERROR;
                                break;
                            }

                            psz = buf + len;
                        }

                        LocalFree(pb);
                    }

                    CertFreeCertificateContext(pCertContext);
                }
            }

            break;
        }

        hash.pbData = (PBYTE)alloca(hash.cbData);
    }

    return hr;
}
© www.soinside.com 2019 - 2024. All rights reserved.