1

Following Exporting PFX file from windows certificates store

I am trying to export from windows key store a pfx file which contains both certificate and private key and dump it to PEM format file which shall be read by openssl.

The private key was marked as exportable during import the file into WCS

I dig into most of the questions here which deals with extracting certificate but none of them deals with pfx file which includes also private key or they use tool e.g. mmc etc and I have to code it as part of the application in C++.

The main issue after exporting the certificate from WCS is to separate between the certificate and the private key section before converting them from binary format to base64 encoding (section header and trailer should be added) and probably also converting from pfx to PEM.

In MS example which my code is based on certificate was serialized but in other examples here it wasn't.

I was also advised to import exported certificate into new "virtual" store but I don't understand why.

What is important for me is to export both certificate and private key from WCS to format and place which openssl can import them from.

If someone has other way to do it I shall be thankful for any information. Thanks in advance for all comments / answers.

My code:

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

#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;
PCCERT_CONTEXT     pCertContext = NULL;
char pszStoreName[256] = "root";
char               pszNameString[256] = "CARootTest"; 
char*              pbElement;
size_t              cbElement;
//-------------------------------------------------------------------
// 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.");
}
//-------------------------------------------------------------------
// 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.");
}

pbElement = base64_encode(pCertContext->pbCertEncoded,
                    sizeof (pCertContext->pbCertEncoded),
                    &cbElement);
/*
//-------------------------------------------------------------------
//  pbElement could be written to a file ??

FILE *fp;
errno_t err;
if ((err = fopen_s(&fp, "cert.p12", "w")) != 0)
    printf("File was not opened\n");
else
    fprintf(fp, "%s", pbElement);
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
  • what you try todo ? if you want export exactly *PFX* (*PKCS#12*) - you need call *PFXExportCertStoreEx* ? or you want not *PFX* but *PEM* ? for get private key associated with cert you need `CertGetCertificateContextProperty` with`CERT_KEY_PROV_INFO_PROP_ID` + `CryptAcquireContext` + `CryptGetUserKey` + `CryptExportKey` with `PRIVATEKEYBLOB` – RbMm Jul 12 '17 at 07:58
  • Thanks it worked. Should I convert it to base64 format before saving it to file or as is in binary format. – yes Jul 12 '17 at 19:36
  • I got bulk of base64 text . Can openssl import it and seperate the private key and certificate? – yes Jul 12 '17 at 19:38
  • `CryptExportKey` return to you private key in raw binary format. are you need convert it to base64 or not - depend from in what form you want store it. – RbMm Jul 12 '17 at 19:42
  • The main porpuse of it is to export pfx file which contains certificate + private key from WCS and extract them in a format which openssl can upload – yes Jul 12 '17 at 20:45
  • Today we save PEM file in a directory and openssl read it from their.But we want to use pfx format and Windows key store – yes Jul 12 '17 at 20:47
  • *PFX* in windows this is container file in *PKCS#12* format. here cert(s) + private key stored. if need *PFX (PKCS#12)* - you need call `PFXExportCertStoreEx`, if you need *PEM* - need separate get private key and store it. however you can convert [pfx to pem too](https://stackoverflow.com/questions/15413646/converting-pfx-to-pem-using-openssl) – RbMm Jul 12 '17 at 20:52
  • @yes Can you document the code in gist and share the link? Or share an example code some other way. Thanks in advance. – T.s. Arun Dec 11 '22 at 17:51

0 Answers0