PDA

View Full Version : Converting winows PRIVATEKEYBLOB to Qt's QSslKey



insha
14th December 2012, 22:06
I am working on an Qt application(windows service) which uses SSL encryption, i need to access the certificate and associated private key from the windows certificate store and pass it to my QSslSocket using setLocalCertificate and setPrivateKey which accepts QSslCertificate and QSslKey respectively.

I am able to get the certificate from the store and set it to QsslSocket using windows API '(CertOpenStore, CertFindCertificateInStore). Now as i have the certificate i need to extract its private key and set to ssl socket, i am using CryptAcquireCertificatePrivateKey, CryptGetUserKey and CryptExportKey windows api in the same order, which gives me a microsoft PRIVATEKEYBLOB and now i need to convert it to a format that QSslKey understands.

wysota
15th December 2012, 09:39
Point your favourite web search engine to PRIVATEKEYBLOB+OpenSSL.

insha
21st December 2012, 02:25
Solved it!! Thought of sharing teh solution here, it might be helpful to someone.

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

ChrisW67
21st December 2012, 04:11
Now please edit your post and put
tags around the code.

insha
22nd December 2012, 21:25
Solved it!! Thought of sharing the solution here, it might be helpful to someone.



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

Thanks, new to the forum so didn't knew how to do that