C++ 从windows证书存储导出PFX文件
我们的应用程序使用OpenSSL保护客户端设备和服务器之间的通信。证书由客户CA生成,我们必须将服务器证书和私钥上载到基于Windows操作系统的计算机 到目前为止,我们指导客户将包含服务器证书和私钥的PEM文件保存在服务器文件系统的特定目录中,并从该目录上传应用程序。最近,客户要求我们从本地windows证书商店读取PFX证书 我可以想到两个选项,它们都结合使用CAPI库从WCS导出PFX文件(根据友好的名称),序列化文件,然后使用OpenSSL API上载文件 第一个选项将其保存为服务器文件系统上的临时文件,然后使用OpenSSL API像以前一样读取 第二个选项使用内存,即传递指针,而不是使用临时文件 我的团队花了很多时间搜索web(主要是堆栈溢出)和尝试代码片段,但没有找到有效的解决方案。我知道在将文件导入WCS期间,私钥应该是可导出的 当我尝试以下简单导出证书并将其保存到文件的代码时(基于MS示例代码的选项#1的前半部分),它只向文件写入一个字符 我错过了什么?我需要重新格式化证书吗 你知道什么是错误的,什么是正确的方法吗 可以用这种方法提取私钥吗 提前感谢您的评论C++ 从windows证书存储导出PFX文件,c++,windows,openssl,ssl-certificate,cryptoapi,C++,Windows,Openssl,Ssl Certificate,Cryptoapi,我们的应用程序使用OpenSSL保护客户端设备和服务器之间的通信。证书由客户CA生成,我们必须将服务器证书和私钥上载到基于Windows操作系统的计算机 到目前为止,我们指导客户将包含服务器证书和私钥的PEM文件保存在服务器文件系统的特定目录中,并从该目录上传应用程序。最近,客户要求我们从本地windows证书商店读取PFX证书 我可以想到两个选项,它们都结合使用CAPI库从WCS导出PFX文件(根据友好的名称),序列化文件,然后使用OpenSSL API上载文件 第一个选项将其保存为服务器文件
//-----------------------------------------
#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
//-----------------------------------------
#pragma注释(lib,“crypt32.lib”)
#包括
#包括
#包括
#定义MY_ENCODING_类型(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
无效MyHandleError(字符*s);
真空总管(真空)
{
//-------------------------------------------------------------------
//声明和初始化变量。
HCERTSTORE hsystore;
PCCERT_CONTEXT pCertContext=NULL;
Char pszStoreName[256]=“根目录”;
char pszNameString[256]=“CARootTest”;
字节pbElement[3000];
德沃德元素;
//-------------------------------------------------------------------
//打开系统证书存储。
if(hssystemstore=CertOpenSystemStore(
0,
pszStoreName)
{
printf(“已打开%s系统存储。继续。\n”,pszStoreName);
}
其他的
{
MyHandleError(“第一个系统存储未打开”);
}
//-------------------------------------------------------------------
//获取具有所需友好名称的证书。
如果(pCertContext=CertFindCertificateInstaller(
系统商店,
MY_ENCODING_TYPE,//使用X509_ASN_编码
0,//不需要dwFlags
证书名称\u友好\u显示\u类型,//查找证书
pszNameString,//要找到的Unicode字符串
//在证书的主题中
NULL))//第一次调用为NULL
{
printf(“找到%s证书。\n”,pszNameString);
}
其他的
{
MyHandleError(“找不到%s证书。”);
}
//-------------------------------------------------------------------
//找出要为序列化元素分配多少内存。
如果(证书)重新发布(
pCertContext,//现有证书。
0,//接受dwFlags的默认值,
NULL,//第一个函数调用为NULL。
&cbElement))//地址,其中
//将放置序列化的元素。
{
printf(“序列化字符串的长度为%d。\n”,
Cb元素);
}
其他的
{
MyHandleError(“查找序列化文件的长度”
“元素失败。”);
}
//-------------------------------------------------------------------
//为序列化元素分配内存。
if(pbElement=(字节*)malloc(cbElement+1))
{
printf(“内存已分配。继续。\n”);
}
其他的
{
MyHandleError(“内存分配失败”);
}
//-------------------------------------------------------------------
//从证书上下文创建序列化元素。
如果(证书)重新发布(
pCertContext,//证书的证书上下文源
//序列化元素。
0,//dwFlags。接受默认值。
pbElement,//指向新元素所在位置的指针
//被储存。
&cbElement))//序列化元素的长度,
{
printf(“编码元素已序列化。\n”);
}
其他的
{
MyHandleError(“元素无法序列化”);
}
//-------------------------------------------------------------------
//pbElement是否可以写入文件??
文件*fp;
错误没有错误;
如果((err=fopen_s(&fp,“cert.p12”,“wb”))!=0)
printf(“文件未打开\n”);
其他的
fprintf(fp,“%s”,pbElement);
fclose(fp);
//-------------------------------------------------------------------
//释放内存。
自由元素(PBE);
CertCloseStore(hSystemStore,0);
printf(“程序运行到最后没有错误。\n”);
}//主管道末端
//-------------------------------------------------------------------
无效MyHandleError(字符*s)
{
fprintf(stderr,“运行程序时出错。\n”);
fprintf(标准字符,“%s\n”,s);
fprintf(stderr,“错误号%x.\n”,GetLastError());
fprintf(stderr,“程序终止。\n”);
出口(1);
}//MyHandleError的结尾
为什么不使用PFXExportCertStoreEx
在pfx文件中保存证书?我们的应用程序作为服务运行,并使用PFXExportCertStore所需的密码“此函数创建的pfx BLOB受密码保护。”。我们不希望用户输入,硬编码密码应为Sequerity-breech。此外,如果我正确理解此命令,则会导出存储中的所有证书,而不仅仅是所需的证书。是的