2

I found this question Converting .PFX to .PEM programmatically? and I have same problem of programmatically export certificates and private key in pfx format from windows key store and convert them into PEM format file / memory.

Above link seems to do it but no real information how it was done and the internal links to github seem to be broken

We can't use pfx format because it contains certificates chain and openSSL library API for loading such chain of certificates works only on PEM file.

When the pfx file was imported into the windows key store the private key was checked as exportable.

I succedd to export the certificates by copying them to new memory store, export it to memory bolb and save it into file in different formats (base64 and binary) - see code below - but I am not sure it the right way of doing it , if all chain was exported and I also don't know how to convert it to PEM format

Thanks in advance for any help

#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(char *s);

char *base64_encode(const unsigned char *data,
                    size_t input_length,
                    size_t *output_length);

void main(void)
{
//-------------------------------------------------------------------
// Declare and initialize variables.
HCERTSTORE         hSystemStore;
HCERTSTORE         hTempStore;
PCCERT_CONTEXT     pCertContext = NULL;
char pszStoreName[256] = "root";
char               pszNameString[256] = "xyzabcfkjvfkvnrg"; 

//-------------------------------------------------------------------
// Open a system certificate store.
if(hSystemStore = CertOpenSystemStore(
    0,
    pszStoreName))
{
  printf("The %s system store is open. Continue.\n", pszStoreName );
}
else
{
  MyHandleError("The first system store did not open.");
}

//-------------------------------------------------------------------
// Open a temporary certificate store.
if(hTempStore = CertOpenStore(
    CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, 0 ))
{
  printf("Temp certificate store was created. Continue.\n");
}
else
{
  MyHandleError("The temp store wasn't not created.");
}
//-------------------------------------------------------------------
// Get a certificate that has the desired friendly name. 
if(pCertContext=CertFindCertificateInStore(
      hSystemStore,
      MY_ENCODING_TYPE,             // Use X509_ASN_ENCODING
      0,                            // No dwFlags needed 
      CERT_NAME_FRIENDLY_DISPLAY_TYPE,        // Find a certificate
      pszNameString, // The Unicode string to be found
                                    // in a certificate's subject
      NULL))                        // NULL for the first call 
{
  printf("The %s certificate was found. \n", pszNameString);
}
else
{
   MyHandleError("Could not find the %s certificate.");
}

//------------------------------------------------------------------
// add selected certificate into temporary store in memory

if(CertAddCertificateContextToStore(hTempStore, pCertContext, CERT_STORE_ADD_NEW, 0))
{
  printf("The %s certificate was added. \n", pszNameString);
}
else
{
   MyHandleError("Could not add %s ce


#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(char *s);

char *base64_encode(const unsigned char *data,
                    size_t input_length,
                    size_t *output_length);

void main(void)
{
//-------------------------------------------------------------------
// Declare and initialize variables.
HCERTSTORE         hSystemStore;
HCERTSTORE         hTempStore;
PCCERT_CONTEXT     pCertContext = NULL;
char pszStoreName[256] = "root";
char               pszNameString[256] = "xyzabcfkjvfkvnrg"; 

//-------------------------------------------------------------------
// Open a system certificate store.
if(hSystemStore = CertOpenSystemStore(
    0,
    pszStoreName))
{
  printf("The %s system store is open. Continue.\n", pszStoreName );
}
else
{
  MyHandleError("The first system store did not open.");
}

//-------------------------------------------------------------------
// Open a temporary certificate store.
if(hTempStore = CertOpenStore(
    CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, 0 ))
{
  printf("Temp certificate store was created. Continue.\n");
}
else
{
  MyHandleError("The temp store wasn't not created.");
}
//-------------------------------------------------------------------
// Get a certificate that has the desired friendly name. 
if(pCertContext=CertFindCertificateInStore(
      hSystemStore,
      MY_ENCODING_TYPE,             // Use X509_ASN_ENCODING
      0,                            // No dwFlags needed 
      CERT_NAME_FRIENDLY_DISPLAY_TYPE,        // Find a certificate
      pszNameString, // The Unicode string to be found
                                    // in a certificate's subject
      NULL))                        // NULL for the first call 
{
  printf("The %s certificate was found. \n", pszNameString);
}
else
{
   MyHandleError("Could not find the %s certificate.");
}

//------------------------------------------------------------------
// add selected certificate into temporary store in memory

if(CertAddCertificateContextToStore(hTempStore, pCertContext, CERT_STORE_ADD_NEW, 0))
{
  printf("The %s certificate was added. \n", pszNameString);
}
else
{
   MyHandleError("Could not add %s certificate.");
}

//------------------------------------------------------------------------------


CRYPT_DATA_BLOB* db= new (CRYPT_DATA_BLOB);
LPCWSTR szPassword = NULL;
db->cbData = 0;

if((!PFXExportCertStoreEx(
                        hTempStore, 
                        db, 
                        szPassword, 
                        0, 
                        EXPORT_PRIVATE_KEYS|REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY))&&(GetLastError()==0))
{
  printf("The %s certificate blob size is %d. \n", pszNameString, db->cbData);
}
else
{
   MyHandleError("Could not calculate size of certificate.");
}

//-------------------------------------------------------
// Allocate memory 
if(db->pbData = (BYTE*)malloc(db->cbData+1))
{
     printf("Memory has been allocated. Continue.\n");
}
else
{
     MyHandleError("The allocation of memory failed.");
}

// Export certificate from temporary store to blob

if(PFXExportCertStoreEx(
                        hTempStore, 
                        db, 
                        szPassword, 
                        0, 
                        EXPORT_PRIVATE_KEYS|REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY))
{
  printf("The %s certificate blob was exported %d. \n", pszNameString);
}
else
{
   MyHandleError("Could not export certificate.");
}


//-------------------------------------------------------------------
//Write blob to files

FILE *fp;
errno_t err;
if ((err = fopen_s(&fp, "cert_bin.p12", "wb")) != 0)
    printf("File was not opened\n");
else
    for (int i=0; i<db->cbData; i++)
    fprintf(fp,"%c", db->pbData + i);
fclose(fp);

size_t t;
char* c = base64_encode(db->pbData, db->cbData, &t);

if ((err = fopen_s(&fp, "cert_base64.p12", "w")) != 0)
    printf("File was not opened\n");
else
    fprintf(fp, "%s", c);
fclose(fp);

//-------------------------------------------------------------------
// Free memory.

//free(pbElement);
CertCloseStore(hSystemStore,0);
printf("The program ran without error to the end.\n");
} // End of main

//-------------------------------------------------------------------
void MyHandleError(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
yes
  • 71
  • 8

1 Answers1

1

This snippet export Certificate chain from WCS to pfx file

{
    CString errorS = NULL;
    CString  pkcs12File = pszNameString;
    CString szPassword = L"XXXXXXXXX";
    do {
        //-------------------------------------------------------------------
        // Declare and initialize variables.
        HCERTSTORE         hSystemStore = NULL;
        HCERTSTORE         hTempStore = NULL;
        PCCERT_CONTEXT     pCertContext = NULL;

        //-------------------------------------------------------------------
        // Open a system certificate store.
        if (!(hSystemStore = CertOpenSystemStore(
            0,
            (LPCWSTR)pszStoreName)))
        {
            errorS = ("system store did not open.");
            break;
        }

        //-------------------------------------------------------------------
        // Open a temporary certificate store.
        if (!(hTempStore = CertOpenStore(
            CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, 0)))
        {
            errorS = ("The temp store wasn't created.");
            break;
        }

        //-------------------------------------------------------------------
        // Get a certificate that has the desired friendly name. 
        if (!(pCertContext = CertFindCertificateInStore(
            hSystemStore,
            MY_ENCODING_TYPE,             // Use X509_ASN_ENCODING
            0,                            // No dwFlags needed 
            CERT_FIND_SUBJECT_STR,        // Find a certificate
            pszNameString, // The Unicode string to be found
            // in a certificate's subject
            NULL)))                        // NULL for the first call 
        {
            errorS = ("Could not find the certificate . " + pszNameString);
            break;
        }

            //-------------------------------------------------------------------
            PCCERT_CHAIN_CONTEXT     pChainContext = NULL;
            CERT_CHAIN_PARA          ChainPara;
            DWORD                    dwFlags = 0;
            CERT_ENHKEY_USAGE        EnhkeyUsage;
            CERT_USAGE_MATCH         CertUsage;

            EnhkeyUsage.cUsageIdentifier = 0;
            EnhkeyUsage.rgpszUsageIdentifier = NULL;
            CertUsage.dwType = USAGE_MATCH_TYPE_AND;
            CertUsage.Usage = EnhkeyUsage;
            ChainPara.cbSize = sizeof(CERT_CHAIN_PARA);
            ChainPara.RequestedUsage = CertUsage;

            if (!CertGetCertificateChain(
                NULL,                  // use the default chain engine
                pCertContext,          // pointer to the end certificate
                NULL,                  // use the default time
                NULL,                  // search no additional stores
                &ChainPara,            // use AND logic and enhanced key usage 
                //  as indicated in the ChainPara 
                //  data structure
                dwFlags,
                NULL,                  // currently reserved
                &pChainContext))       // return a pointer to the chain created
            {
                errorS = ("Could not get certificate chain.");
                break;
            }

        //------------------------------------------------------------------
        // add selected certificate into temporary store in memory
            for (int l_chain = 0; l_chain < (int)(pChainContext->cChain); l_chain++)
                for (int l_cert = 0; l_cert < (int)(pChainContext->rgpChain[l_chain]->cElement); l_cert++)
                {           
                    pCertContext = (PCCERT_CONTEXT)pChainContext->rgpChain[l_chain]->rgpElement[l_cert]->pCertContext;
        if (!(CertAddCertificateContextToStore(hTempStore, pCertContext, CERT_STORE_ADD_NEW, 0)))
        {
            errorS = ("Could not add certificate.");
            break;
        }
                }

            CertFreeCertificateChain(pChainContext);

        //------------------------------------------------------------------------------
            // Export certificates chain to memory bolb

        CRYPT_DATA_BLOB* db = new (CRYPT_DATA_BLOB);
            LPCWSTR szPassword = L"XXXXXXXXX";
        db->cbData = 0;

            // calculating required memory space

        if ((PFXExportCertStoreEx(
            hTempStore,
            db,
            szPassword,
            0,
            EXPORT_PRIVATE_KEYS | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY)) && (GetLastError() == 0))
        {
            errorS = ("Could not calculate size of certificate.");
            break;
        }

        // Allocate memory 
        if (!(db->pbData = (BYTE*)malloc(db->cbData)))
        {
            errorS = ("The allocation of memory failed.");
            break;
        }

        // Export certificate from temporary store to blob

        if (!PFXExportCertStoreEx(
            hTempStore,
            db,
            szPassword,
            0,
            EXPORT_PRIVATE_KEYS | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY))
        {
            errorS = ("Could not export certificate.");
            break;
        }

        //-------------------------------------------------------------------
        //Write blob to files

        FILE *fp = NULL;
        errno_t err;
        if ((err = fopen_s(&fp, CT2A(pkcs12File), "wb")) != 0)
        {
            errorS = ("File was not opened\n");
            break;
        }
        else
            fwrite(db->pbData, 1, db->cbData, fp);
        fclose(fp);
        //-------------------------------------------------------------------
        // Free memory.

        CertCloseStore(hSystemStore, 0);

        //--------------------------------------------------------------------------

    } while (0);
yes
  • 71
  • 8