2

我正在开发一个使用 SSL 加密的 Qt 应用程序(Windows 服务)。

我需要从 Windows 证书存储访问证书和关联的私钥,并使用 setLocalCertificate 和 setPrivateKey 将其传递给我的 QSslSocket,它们分别接受 QSslCertificate 和 QSslKey。

我能够从商店获取证书并使用 Windows API '(CertOpenStore、CertFindCertificateInStore)将其设置为 QsslSocket。现在有了证书,我需要提取其私钥并设置为 ssl 套接字。我正在以相同的顺序使用 CryptAcquireCertificatePrivateKey、CryptGetUserKey 和 CryptExportKey Windows API,这给了我一个 Microsoft PRIVATEKEYBLOB,现在我需要将其转换为 QSslKey 可以理解的格式。

我怎么做?

4

1 回答 1

2

解决了!!想到在这里分享解决方案,它可能对某人有所帮助。

// Open the certificate store to be searched.
HCERTSTORE hSystemStore = CertOpenStore((LPCSTR)(CERT_STORE_PROV_SYSTEM),  0, NULL,
                             CERT_SYSTEM_STORE_LOCAL_MACHINE, L"MY");

CRYPT_DATA_BLOB dataBlob = {0};
QString password("password"); // your password for the cretificate and private key goes here

if(PFXExportCertStoreEx(hSystemStore, &dataBlob, password.toStdWString().c_str(), NULL,
                            EXPORT_PRIVATE_KEYS | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY | REPORT_NO_PRIVATE_KEY))
{
    if (dataBlob.cbData > 0)
    {
        dataBlob.pbData = (BYTE*)malloc(dataBlob.cbData);
        if (PFXExportCertStoreEx(hSystemStore, &dataBlob, password.toStdWString().c_str(), NULL,
                                    EXPORT_PRIVATE_KEYS | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY | REPORT_NO_PRIVATE_KEY))
        {
            EVP_PKEY *pkey;
            X509 *cert;
            STACK_OF(X509) *ca = NULL;
            PKCS12 *p12;
            int i;
            CRYPTO_malloc_init();
            OpenSSL_add_all_algorithms();
            SSLeay_add_all_algorithms();
            ERR_load_crypto_strings();

            BIO* input = BIO_new_mem_buf((void*)dataBlob.pbData, dataBlob.cbData);
            p12 = d2i_PKCS12_bio(input, NULL);

            PKCS12_parse(p12, password.toStdString().c_str(), &pkey, &cert, &ca);
            PKCS12_free(p12);

            if (cert)
            {
                BIO *boCert = BIO_new( BIO_s_mem() );

                PEM_write_bio_X509(boCert, cert);
                if (ca && sk_X509_num(ca))
                {
                    for (i = 0; i < sk_X509_num(ca); i++)
                    {
                        PEM_write_bio_X509(boCert, sk_X509_value(ca, i));
                    }
                }
                char *certStr;
                long len = BIO_get_mem_data(boCert, &certStr);

                QSslCertificate localCertificate(QByteArray::fromRawData(certStr, len));
                mySslSocket->setLocalCertificate(localCertificate);

                BIO_free_all(boCert);
            }

            if (pkey)
            {
                BIO *bo = BIO_new( BIO_s_mem() );
                PEM_write_bio_PrivateKey(bo, pkey, NULL, (unsigned char*)(password.toStdString().c_str()), password.length(), NULL, (char*)(password.toStdString().c_str()));

                char *p;
                long len = BIO_get_mem_data(bo, &p);

                QSslKey key(QByteArray::fromRawData(p, len), QSsl::Rsa);
                mySslSocket->setPrivateKey(key);
                BIO_free_all(bo);
            }
           free(dataBlob.pbData);
        }
    }
}

if(hSystemStore)
    CertCloseStore(hSystemStore, 0);
于 2012-12-21T02:23:26.770 回答