问题
Our application uses OpenSSL for securing communication between client device and server. The certificates are generated by customers CA and we had to upload server certificate and private key to Windows OS based machine.
Until now we guide our customers to save a PEM files which include server certificate and private key at specific directory on server file system and our application upload it from there. Lately, we were asked by customer to read a PFX certificate from local windows certificate store.
I can think of 2 options which both combines use of CAPI library for exporting the PFX file from WCS (according to friendly name), serializing it and then uploading it using OpenSSL API.
The first option save it as temporary file on server file system then read as before with OpenSSL API.
The 2nd option uses memory i.e. pass pointers instead of using temporary file.
My team spent a lot of time searching the web (mainly Stack Overflow) and trying code snippets but didn't found working solution. I understood that the private key should be exportable marked during importing the file to WCS.
When I tried below code for simple exporting certificate and saving it to file (first half of option #1 based on MS example code) it writes only one character to file.
What do I miss here? Do I need to reformat certificate?
Any Idea of what is wrong and what is the right way to do it?
Can the private key be extract this way?
Thanks in advance for any comment
//-----------------------------------------
#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);
void main(void)
{
//-------------------------------------------------------------------
// Declare and initialize variables.
HCERTSTORE hSystemStore;
PCCERT_CONTEXT pCertContext = NULL;
Char pszStoreName[256] = "root";
char pszNameString[256] = "CARootTest";
BYTE pbElement[3000];
DWORD 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.");
}
//-------------------------------------------------------------------
// Find out how much memory to allocate for the serialized element.
if(CertSerializeCertificateStoreElement(
pCertContext, // The existing certificate.
0, // Accept default for dwFlags,
NULL, // NULL for the first function call.
&cbElement)) // Address where the length of the
// serialized element will be placed.
{
printf("The length of the serialized string is %d.\n",
cbElement);
}
else
{
MyHandleError("Finding the length of the serialized "
"element failed.");
}
//-------------------------------------------------------------------
// Allocate memory for the serialized element.
if(pbElement = (BYTE*)malloc(cbElement+1))
{
printf("Memory has been allocated. Continue.\n");
}
else
{
MyHandleError("The allocation of memory failed.");
}
//-------------------------------------------------------------------
// Create the serialized element from a certificate context.
if(CertSerializeCertificateStoreElement(
pCertContext, // The certificate context source for the
// serialized element.
0, // dwFlags. Accept the default.
pbElement, // A pointer to where the new element will
// be stored.
&cbElement)) // The length of the serialized element,
{
printf("The encoded element has been serialized. \n");
}
else
{
MyHandleError("The element could not be serialized.");
}
//-------------------------------------------------------------------
// pbElement could be written to a file ??
FILE *fp;
errno_t err;
if ((err = fopen_s(&fp, "cert.p12", "wb")) != 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
来源:https://stackoverflow.com/questions/44996810/exporting-pfx-file-from-windows-certificates-store